diff --git a/examples/3d-air-hockey/3d-air-hockey.json b/examples/3d-air-hockey/3d-air-hockey.json new file mode 100644 index 000000000..31ee290ca --- /dev/null +++ b/examples/3d-air-hockey/3d-air-hockey.json @@ -0,0 +1,42931 @@ +{ + "firstLayout": "Menu", + "gdVersion": { + "build": 286, + "major": 5, + "minor": 6, + "revision": 0 + }, + "initialGDVersion": "5.6.283", + "properties": { + "adaptGameResolutionAtRuntime": true, + "antialiasingMode": "MSAA", + "antialisingEnabledOnMobile": false, + "folderProject": false, + "orientation": "default", + "packageName": "com.example.gamename", + "pixelsRounding": false, + "projectUuid": "9933182e-d716-4ea5-a2e8-bb852de01a4a", + "scaleMode": "linear", + "sizeOnStartupMode": "adaptWidth", + "templateSlug": "", + "version": "0.1.0", + "name": "Air Hockey", + "description": "", + "author": "", + "windowWidth": 1920, + "windowHeight": 1080, + "latestCompilationDirectory": "", + "maxFPS": 60, + "minFPS": 20, + "verticalSync": false, + "platformSpecificAssets": {}, + "loadingScreen": { + "backgroundColor": 0, + "backgroundFadeInDuration": 0.2, + "backgroundImageResourceName": "", + "gdevelopLogoStyle": "light", + "logoAndProgressFadeInDuration": 0.2, + "logoAndProgressLogoFadeInDelay": 0, + "minDuration": 1.5, + "progressBarColor": 16777215, + "progressBarHeight": 20, + "progressBarMaxWidth": 200, + "progressBarMinWidth": 40, + "progressBarWidthPercent": 30, + "showGDevelopSplash": true, + "showProgressBar": true + }, + "watermark": { + "placement": "bottom-left", + "showWatermark": true + }, + "authorIds": [ + "R0F5QGNCzgOY5w2cxGeKJOq2UaD2" + ], + "authorUsernames": [ + "GDevelop" + ], + "categories": [], + "playableDevices": [], + "extensionProperties": [], + "platforms": [ + { + "name": "GDevelop JS platform" + } + ], + "currentPlatform": "GDevelop JS platform" + }, + "resources": { + "resources": [ + { + "file": "assets/models/Table.glb", + "kind": "model3D", + "metadata": "", + "name": "Table.glb", + "userAdded": false + }, + { + "file": "assets/models/Goal.glb", + "kind": "model3D", + "metadata": "", + "name": "Goal.glb", + "userAdded": false + }, + { + "file": "assets/models/Puck.glb", + "kind": "model3D", + "metadata": "", + "name": "Puck.glb", + "userAdded": false + }, + { + "file": "assets/images/FlagUSA.png", + "kind": "image", + "metadata": "", + "name": "FlagUSA.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/FlagBelgium.png", + "kind": "image", + "metadata": "", + "name": "FlagBelgium.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/fonts/Coiny-Regular.ttf", + "kind": "font", + "metadata": "", + "name": "Coiny-Regular.ttf", + "userAdded": false + }, + { + "file": "assets/sounds/PuckHit.aac", + "kind": "audio", + "metadata": "", + "name": "PuckHit.aac", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/WallBounce.aac", + "kind": "audio", + "metadata": "", + "name": "WallBounce.aac", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/GoalOpponent.aac", + "kind": "audio", + "metadata": "", + "name": "GoalOpponent.aac", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/ButtonClick.mp3", + "kind": "audio", + "metadata": "", + "name": "ButtonClick.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/MatchMusic.aac", + "kind": "audio", + "metadata": "", + "name": "MatchMusic.aac", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/Whistle.aac", + "kind": "audio", + "metadata": "", + "name": "Whistle.aac", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/images/Scoreboard.png", + "kind": "image", + "metadata": "", + "name": "Scoreboard.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/ResultPanel.png", + "kind": "image", + "metadata": "", + "name": "ResultPanel.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/fonts/RobotoMono-Bold.ttf", + "kind": "font", + "metadata": "", + "name": "RobotoMono-Bold.ttf", + "userAdded": false + }, + { + "file": "assets/images/ButtonIdle.png", + "kind": "image", + "metadata": "", + "name": "ButtonIdle.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/ButtonHovered.png", + "kind": "image", + "metadata": "", + "name": "ButtonHovered.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/ButtonPressed.png", + "kind": "image", + "metadata": "", + "name": "ButtonPressed.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/models/Stadium.glb", + "kind": "model3D", + "metadata": "", + "name": "Stadium.glb", + "userAdded": false + }, + { + "file": "assets/images/StadiumSky.png", + "kind": "image", + "metadata": "", + "name": "StadiumSky.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/Confetti.png", + "kind": "image", + "metadata": "", + "name": "Confetti.png", + "smoothed": true, + "userAdded": true + }, + { + "file": "assets/images/FlagFrance.png", + "kind": "image", + "metadata": "", + "name": "FlagFrance.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/FlagSpain.png", + "kind": "image", + "metadata": "", + "name": "FlagSpain.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/FlagCanada.png", + "kind": "image", + "metadata": "", + "name": "FlagCanada.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/FlagGermany.png", + "kind": "image", + "metadata": "", + "name": "FlagGermany.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/PuckTrail.png", + "kind": "image", + "metadata": "", + "name": "PuckTrail.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/SkyFront.png", + "kind": "image", + "metadata": "", + "name": "SkyFront.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/SkyBack.png", + "kind": "image", + "metadata": "", + "name": "SkyBack.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/SkyLeft.png", + "kind": "image", + "metadata": "", + "name": "SkyLeft.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/SkyRight.png", + "kind": "image", + "metadata": "", + "name": "SkyRight.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/SkyTop.png", + "kind": "image", + "metadata": "", + "name": "SkyTop.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/SkyBottom.png", + "kind": "image", + "metadata": "", + "name": "SkyBottom.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/Camera.glb", + "kind": "model3D", + "metadata": "", + "name": "Camera.glb", + "userAdded": false, + "origin": { + "identifier": "https://asset-resources.gdevelop.io/public-resources/3D Scene Essentials/Camera/0166f2883a3b3102d29043aae042e68a3ae47c6309a142239d135420ad38ada3_Camera.glb", + "name": "Camera.glb" + } + }, + { + "file": "assets/sounds/AnthemUSA.mp3", + "kind": "audio", + "metadata": "", + "name": "AnthemUSA.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/AnthemBelgium.mp3", + "kind": "audio", + "metadata": "", + "name": "AnthemBelgium.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/AnthemFrance.mp3", + "kind": "audio", + "metadata": "", + "name": "AnthemFrance.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/AnthemSpain.mp3", + "kind": "audio", + "metadata": "", + "name": "AnthemSpain.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/AnthemCanada.mp3", + "kind": "audio", + "metadata": "", + "name": "AnthemCanada.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/AnthemGermany.mp3", + "kind": "audio", + "metadata": "", + "name": "AnthemGermany.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/images/ModalPanel.png", + "kind": "image", + "metadata": "", + "name": "ModalPanel.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/ModalScrim.png", + "kind": "image", + "metadata": "", + "name": "ModalScrim.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/SecondaryButtonIdle.png", + "kind": "image", + "metadata": "", + "name": "SecondaryButtonIdle.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/SecondaryButtonHovered.png", + "kind": "image", + "metadata": "", + "name": "SecondaryButtonHovered.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/SecondaryButtonPressed.png", + "kind": "image", + "metadata": "", + "name": "SecondaryButtonPressed.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/CloseButtonIdle.png", + "kind": "image", + "metadata": "", + "name": "CloseButtonIdle.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/CloseButtonHovered.png", + "kind": "image", + "metadata": "", + "name": "CloseButtonHovered.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/CloseButtonPressed.png", + "kind": "image", + "metadata": "", + "name": "CloseButtonPressed.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/GearButtonIdle.png", + "kind": "image", + "metadata": "", + "name": "GearButtonIdle.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/GearButtonHovered.png", + "kind": "image", + "metadata": "", + "name": "GearButtonHovered.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/GearButtonPressed.png", + "kind": "image", + "metadata": "", + "name": "GearButtonPressed.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/PowerUpBigMallet.png", + "kind": "image", + "metadata": "", + "name": "PowerUpBigMallet.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/PowerUpFreeze.png", + "kind": "image", + "metadata": "", + "name": "PowerUpFreeze.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/PowerUpTurbo.png", + "kind": "image", + "metadata": "", + "name": "PowerUpTurbo.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/PowerUpShield.png", + "kind": "image", + "metadata": "", + "name": "PowerUpShield.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/sounds/PowerUpPickup.aac", + "kind": "audio", + "metadata": "", + "name": "PowerUpPickup.aac", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/PowerUpSpawn.aac", + "kind": "audio", + "metadata": "", + "name": "PowerUpSpawn.aac", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/images/TileIdle.png", + "kind": "image", + "metadata": "", + "name": "TileIdle.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/TileHovered.png", + "kind": "image", + "metadata": "", + "name": "TileHovered.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/TilePressed.png", + "kind": "image", + "metadata": "", + "name": "TilePressed.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/TileSelected.png", + "kind": "image", + "metadata": "", + "name": "TileSelected.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/TileOpponent.png", + "kind": "image", + "metadata": "", + "name": "TileOpponent.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/PowerUpRing100.png", + "kind": "image", + "metadata": "", + "name": "PowerUpRing100.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/PowerUpRing80.png", + "kind": "image", + "metadata": "", + "name": "PowerUpRing80.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/PowerUpRing60.png", + "kind": "image", + "metadata": "", + "name": "PowerUpRing60.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/PowerUpRing40.png", + "kind": "image", + "metadata": "", + "name": "PowerUpRing40.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/PowerUpRing25.png", + "kind": "image", + "metadata": "", + "name": "PowerUpRing25.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/images/GoalShieldWall.png", + "kind": "image", + "metadata": "", + "name": "GoalShieldWall.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/sounds/voice/default/01_good_game.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/default/01_good_game.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/default/02_goooooal.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/default/02_goooooal.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/default/03_go_go_go.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/default/03_go_go_go.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/default/04_great.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/default/04_great.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/default/05_here_we_go_again.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/default/05_here_we_go_again.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/default/06_lets_gooo.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/default/06_lets_gooo.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/default/07_nice.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/default/07_nice.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/default/08_nice.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/default/08_nice.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/default/09_nooo.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/default/09_nooo.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/default/10_nothing_but_net.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/default/10_nothing_but_net.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/default/11_not_bad.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/default/11_not_bad.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/default/12_oh_noo.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/default/12_oh_noo.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/default/13_scored.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/default/13_scored.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/default/14_thats_great.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/default/14_thats_great.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/default/15_thats_terrible.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/default/15_thats_terrible.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/default/16_what_was_the_plan.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/default/16_what_was_the_plan.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/default/17_yeahh.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/default/17_yeahh.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/default/18_yikes.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/default/18_yikes.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/Applause.mp3", + "kind": "audio", + "metadata": "", + "name": "Applause.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/CrowdNearMiss.mp3", + "kind": "audio", + "metadata": "", + "name": "CrowdNearMiss.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/Ambient1.mp3", + "kind": "audio", + "metadata": "", + "name": "Ambient1.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/Ambient2.mp3", + "kind": "audio", + "metadata": "", + "name": "Ambient2.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/Ambient3.mp3", + "kind": "audio", + "metadata": "", + "name": "Ambient3.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/fr/01_good_game.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/fr/01_good_game.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/fr/02_goooooal.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/fr/02_goooooal.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/fr/03_go_go_go.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/fr/03_go_go_go.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/fr/04_great.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/fr/04_great.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/fr/05_here_we_go_again.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/fr/05_here_we_go_again.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/fr/06_lets_gooo.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/fr/06_lets_gooo.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/fr/07_nice.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/fr/07_nice.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/fr/08_nice.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/fr/08_nice.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/fr/09_nooo.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/fr/09_nooo.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/fr/10_nothing_but_net.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/fr/10_nothing_but_net.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/fr/11_not_bad.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/fr/11_not_bad.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/fr/12_oh_noo.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/fr/12_oh_noo.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/fr/13_scored.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/fr/13_scored.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/fr/14_thats_great.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/fr/14_thats_great.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/fr/15_thats_terrible.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/fr/15_thats_terrible.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/fr/16_what_was_the_plan.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/fr/16_what_was_the_plan.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/fr/17_yeahh.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/fr/17_yeahh.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/sounds/voice/fr/18_yikes.mp3", + "kind": "audio", + "metadata": "", + "name": "voice/fr/18_yikes.mp3", + "preloadAsMusic": false, + "preloadAsSound": false, + "preloadInCache": false, + "userAdded": false + }, + { + "file": "assets/models/MalletBody.glb", + "kind": "model3D", + "metadata": "", + "name": "MalletBody.glb", + "userAdded": false + }, + { + "file": "assets/models/MalletUSA.glb", + "kind": "model3D", + "metadata": "", + "name": "MalletUSA.glb", + "userAdded": false + }, + { + "file": "assets/models/MalletBelgium.glb", + "kind": "model3D", + "metadata": "", + "name": "MalletBelgium.glb", + "userAdded": false + }, + { + "file": "assets/models/MalletFrance.glb", + "kind": "model3D", + "metadata": "", + "name": "MalletFrance.glb", + "userAdded": false + }, + { + "file": "assets/models/MalletSpain.glb", + "kind": "model3D", + "metadata": "", + "name": "MalletSpain.glb", + "userAdded": false + }, + { + "file": "assets/models/MalletCanada.glb", + "kind": "model3D", + "metadata": "", + "name": "MalletCanada.glb", + "userAdded": false + }, + { + "file": "assets/models/MalletGermany.glb", + "kind": "model3D", + "metadata": "", + "name": "MalletGermany.glb", + "userAdded": false + }, + { + "file": "assets/models/FlagUSA.glb", + "kind": "model3D", + "metadata": "", + "name": "FlagUSA.glb", + "userAdded": false + }, + { + "file": "assets/models/FlagBelgium.glb", + "kind": "model3D", + "metadata": "", + "name": "FlagBelgium.glb", + "userAdded": false + }, + { + "file": "assets/models/FlagFrance.glb", + "kind": "model3D", + "metadata": "", + "name": "FlagFrance.glb", + "userAdded": false + }, + { + "file": "assets/models/FlagSpain.glb", + "kind": "model3D", + "metadata": "", + "name": "FlagSpain.glb", + "userAdded": false + }, + { + "file": "assets/models/FlagCanada.glb", + "kind": "model3D", + "metadata": "", + "name": "FlagCanada.glb", + "userAdded": false + }, + { + "file": "assets/models/FlagGermany.glb", + "kind": "model3D", + "metadata": "", + "name": "FlagGermany.glb", + "userAdded": false + } + ] + }, + "objects": [ + { + "assetStoreId": "", + "name": "UI_OptionsModal", + "persistentUuid": "597ccd9e-38e1-467e-9209-528010ad0689", + "type": "AirHockeyUI::UI_OptionsModal", + "variant": "", + "variables": [], + "effects": [], + "behaviors": [], + "content": {} + }, + { + "assetStoreId": "", + "name": "OptionsButton", + "type": "PanelSpriteButton::PanelSpriteButton", + "variant": "IconGear", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "LabelText": "" + } + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "folderName": "UI", + "children": [ + { + "objectName": "UI_OptionsModal" + }, + { + "objectName": "OptionsButton" + } + ] + } + ] + }, + "objectsGroups": [], + "variables": [ + { + "name": "Selection", + "persistentUuid": "7cc850a8-eb99-443e-8545-d6bcc8d64c85", + "type": "structure", + "children": [ + { + "name": "OpponentCountry", + "persistentUuid": "d7e90afd-af2b-495c-9eaf-f0f4831b79b8", + "type": "string", + "value": "" + }, + { + "name": "PlayerCountry", + "persistentUuid": "07b9c114-2aa9-492c-af1b-61fc15eb6074", + "type": "string", + "value": "Canada" + } + ] + }, + { + "name": "Settings", + "persistentUuid": "89638796-ac22-4941-9ad2-c9cf05a7b440", + "type": "structure", + "children": [ + { + "name": "IsLoaded", + "persistentUuid": "6b3cfe7e-b25d-487b-bdd2-4fffad642215", + "type": "boolean", + "value": false + }, + { + "name": "MalletSensitivity", + "persistentUuid": "a383905a-041f-4b7e-b849-8c51780e8622", + "type": "number", + "value": 8 + }, + { + "name": "Volume", + "persistentUuid": "6a0efbbb-e060-4115-ac89-8ec637631c7c", + "type": "number", + "value": 80 + } + ] + }, + { + "name": "Ambience", + "persistentUuid": "63f3c2ad-bcf5-4c99-8777-7e70c769b10a", + "type": "structure", + "children": [ + { + "name": "Channel", + "persistentUuid": "6ef4bf53-0967-4585-95aa-75fc572d90c8", + "type": "number", + "value": 5 + }, + { + "name": "TrackCount", + "persistentUuid": "325c800b-ce7a-4e05-922b-d14796e418b1", + "type": "number", + "value": 3 + }, + { + "name": "Volume", + "persistentUuid": "30e60bb8-f519-4845-890a-60715b72aa77", + "type": "number", + "value": 75 + } + ] + }, + { + "name": "Countries", + "type": "structure", + "children": [ + { + "name": "Belgium", + "type": "structure", + "children": [ + { + "name": "Code", + "type": "string", + "value": "BEL" + }, + { + "name": "Language", + "type": "string", + "value": "" + }, + { + "name": "Name", + "type": "string", + "value": "BELGIUM" + } + ] + }, + { + "name": "Canada", + "type": "structure", + "children": [ + { + "name": "Code", + "type": "string", + "value": "CAN" + }, + { + "name": "Language", + "type": "string", + "value": "" + }, + { + "name": "Name", + "type": "string", + "value": "CANADA" + } + ] + }, + { + "name": "France", + "type": "structure", + "children": [ + { + "name": "Code", + "type": "string", + "value": "FRA" + }, + { + "name": "Language", + "type": "string", + "value": "fr" + }, + { + "name": "Name", + "type": "string", + "value": "FRANCE" + } + ] + }, + { + "name": "Germany", + "type": "structure", + "children": [ + { + "name": "Code", + "type": "string", + "value": "GER" + }, + { + "name": "Language", + "type": "string", + "value": "" + }, + { + "name": "Name", + "type": "string", + "value": "GERMANY" + } + ] + }, + { + "name": "Spain", + "type": "structure", + "children": [ + { + "name": "Code", + "type": "string", + "value": "ESP" + }, + { + "name": "Language", + "type": "string", + "value": "" + }, + { + "name": "Name", + "type": "string", + "value": "SPAIN" + } + ] + }, + { + "name": "USA", + "type": "structure", + "children": [ + { + "name": "Code", + "type": "string", + "value": "USA" + }, + { + "name": "Language", + "type": "string", + "value": "" + }, + { + "name": "Name", + "type": "string", + "value": "USA" + } + ] + } + ] + }, + { + "name": "CountryList", + "type": "array", + "children": [ + { + "type": "string", + "value": "USA" + }, + { + "type": "string", + "value": "Belgium" + }, + { + "type": "string", + "value": "France" + }, + { + "type": "string", + "value": "Spain" + }, + { + "type": "string", + "value": "Canada" + }, + { + "type": "string", + "value": "Germany" + } + ] + } + ], + "layouts": [ + { + "b": 110, + "disableInputWhenNotFocused": true, + "mangledName": "Menu", + "name": "Menu", + "r": 20, + "renderer3DWorldScale": 100, + "standardSortMethod": true, + "stopSoundsOnStartup": true, + "title": "Air Hockey", + "v": 40, + "uiSettings": { + "grid": false, + "gridType": "rectangular", + "gridWidth": 32, + "gridHeight": 32, + "gridDepth": 32, + "gridOffsetX": 0, + "gridOffsetY": 0, + "gridOffsetZ": 0, + "gridColor": 10401023, + "gridAlpha": 0.8, + "snap": false, + "zoomFactor": 0.561095208358207, + "windowMask": false, + "selectedLayer": "", + "gameEditorMode": "instances-editor" + }, + "objectsGroups": [ + { + "name": "MenuButtons", + "objects": [ + { + "name": "PlayButton" + } + ] + } + ], + "variables": [ + { + "name": "Menu", + "persistentUuid": "ff1ec479-9554-4ca3-89b2-5d95e2128431", + "type": "structure", + "children": [ + { + "name": "CountryIndex", + "persistentUuid": "24a10a4e-36e4-4821-9f99-a1736d123fd5", + "type": "number", + "value": 4 + }, + { + "name": "DrawSeconds", + "persistentUuid": "dbd335bb-c53e-4421-80f8-4773d7e568e2", + "type": "number", + "value": 3.4 + }, + { + "name": "OpponentIndex", + "persistentUuid": "4534a8c9-7d32-4581-9ce8-c2c7b227720d", + "type": "number", + "value": 0 + }, + { + "name": "RouletteIndex", + "persistentUuid": "1e47cb1e-95f9-4eab-a2ab-0eba6b71915e", + "type": "number", + "value": 0 + }, + { + "name": "RouletteSeconds", + "persistentUuid": "3594f488-0007-4038-9c8e-3330a585bec2", + "type": "number", + "value": 1.6 + }, + { + "name": "RouletteStepSeconds", + "persistentUuid": "0bb10bf2-d16a-4113-9a99-067e90a818b1", + "type": "number", + "value": 0.09 + }, + { + "name": "State", + "persistentUuid": "0bd123ea-6c69-42cd-8492-98d07fb22e52", + "type": "string", + "value": "Choosing" + }, + { + "name": "VsDelaySeconds", + "persistentUuid": "bf641a2b-3978-45de-a11a-77efba18c6be", + "type": "number", + "value": 0.5 + } + ] + } + ], + "instances": [ + { + "angle": 0, + "customSize": true, + "height": 1080, + "keepRatio": true, + "layer": "Background", + "name": "MenuBackground", + "persistentUuid": "e78f1003-db77-48fc-8bb6-216badd559ee", + "width": 1920, + "x": 0, + "y": 0, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 120, + "keepRatio": true, + "layer": "", + "name": "TitleText", + "persistentUuid": "2898e111-e7bf-415e-9617-a2601dafda80", + "width": 1920, + "x": 0, + "y": 75, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 1, + "height": 101, + "keepRatio": true, + "layer": "", + "name": "ChooseText", + "persistentUuid": "fe67e536-85d3-4088-a50e-633e9712fb18", + "width": 840, + "x": 80, + "y": 261, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 295, + "keepRatio": true, + "layer": "", + "name": "PlayerFlag", + "persistentUuid": "1b4629fc-8250-4bc7-82df-165a954277d4", + "width": 560, + "x": 220, + "y": 320, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 1, + "height": 174, + "keepRatio": true, + "layer": "", + "name": "PlayerName", + "persistentUuid": "b2bf7283-f21c-4308-9021-eef4a582d518", + "width": 840, + "x": 80, + "y": 703, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 1, + "height": 201, + "hidden": true, + "keepRatio": true, + "layer": "", + "name": "OpponentText", + "persistentUuid": "032b2674-b4c1-428c-95f9-cbe911fdb716", + "width": 840, + "x": 1000, + "y": 701, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 295, + "hidden": true, + "keepRatio": true, + "layer": "", + "name": "OpponentFlag", + "persistentUuid": "bb88fa5f-e268-4e74-983d-c65bc3a487e5", + "width": 560, + "x": 1140, + "y": 320, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 130, + "keepRatio": true, + "layer": "", + "name": "PlayButton", + "persistentUuid": "a694708e-b406-4de1-988d-6e08ec1a5a44", + "width": 400, + "x": 760, + "y": 890, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "Modal", + "name": "UI_OptionsModal", + "persistentUuid": "241b54ec-3e38-4749-92cf-a20d779e18a5", + "width": 0, + "x": 0, + "y": 0, + "zOrder": 10, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 120, + "keepRatio": true, + "layer": "HUD", + "name": "OptionsButton", + "persistentUuid": "992d9acb-f376-41ae-bd66-2e104d385bf6", + "width": 120, + "x": 1770, + "y": 30, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 600, + "keepRatio": true, + "layer": "", + "name": "TeamCard", + "persistentUuid": "e38b959c-0640-4d4a-bb52-b635990596bf", + "width": 840, + "x": 80, + "y": 215, + "zOrder": -1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 1, + "height": 91, + "keepRatio": true, + "layer": "", + "name": "HintText", + "persistentUuid": "3c262fcc-fce3-4552-b625-2e6744f2651a", + "width": 1920, + "x": 0, + "y": 851, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "", + "name": "FooterText", + "persistentUuid": "293144da-4d93-4587-b7ca-2c0348e4e4de", + "width": 0, + "x": 30, + "y": 1035, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 600, + "keepRatio": true, + "layer": "", + "name": "RosterCard", + "persistentUuid": "ac0986b3-57dd-43e0-97b5-3bdbce22fd49", + "width": 840, + "x": 1000, + "y": 215, + "zOrder": -1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 1, + "height": 103, + "keepRatio": true, + "layer": "", + "name": "RosterText", + "persistentUuid": "0dea520f-1c9b-4247-8c3a-7c582c449d7b", + "width": 840, + "x": 1000, + "y": 262, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 170, + "hidden": true, + "keepRatio": true, + "layer": "", + "name": "VsText", + "persistentUuid": "40c7ba0c-f3fc-43ba-956e-e790ca99b54a", + "width": 300, + "x": 810, + "y": 410, + "zOrder": 5, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "", + "name": "UI_CountryTile", + "persistentUuid": "9734dde6-b6ce-46d7-bc25-66bd32542e86", + "width": 0, + "x": 1040, + "y": 320, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [ + { + "name": "Country", + "type": "string", + "value": "USA" + } + ] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "", + "name": "UI_CountryTile", + "persistentUuid": "b81cd7a1-2cb0-45a7-81c2-8874673c6271", + "width": 0, + "x": 1300, + "y": 320, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [ + { + "name": "Country", + "type": "string", + "value": "Belgium" + } + ] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "", + "name": "UI_CountryTile", + "persistentUuid": "f0f570b2-a4cc-4079-b2b2-87ebbcc8187b", + "width": 0, + "x": 1560, + "y": 320, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [ + { + "name": "Country", + "type": "string", + "value": "France" + } + ] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "", + "name": "UI_CountryTile", + "persistentUuid": "eb54766d-2973-453d-ae31-f95d1dd7c2d6", + "width": 0, + "x": 1040, + "y": 530, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [ + { + "name": "Country", + "type": "string", + "value": "Spain" + } + ] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "", + "name": "UI_CountryTile", + "persistentUuid": "0b6c6781-9300-4381-8105-0c2a3408f886", + "width": 0, + "x": 1300, + "y": 530, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [ + { + "name": "Country", + "type": "string", + "value": "Canada" + } + ] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "", + "name": "UI_CountryTile", + "persistentUuid": "df7cd8cc-069d-46ea-8fba-c9b6468a3201", + "width": 0, + "x": 1560, + "y": 530, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [ + { + "name": "Country", + "type": "string", + "value": "Germany" + } + ] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "Background", + "name": "MenuParticles", + "persistentUuid": "66ef673f-b302-4f28-9f2c-9f8a20fc6acf", + "width": 0, + "x": 960, + "y": 540, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + } + ], + "objects": [ + { + "adaptCollisionMaskAutomatically": true, + "assetStoreId": "", + "name": "MenuBackground", + "persistentUuid": "5d68bfa5-e8ff-42d0-aad9-4dd7f8a02daa", + "type": "Sprite", + "updateIfNotVisible": false, + "variables": [], + "effects": [], + "behaviors": [], + "animations": [ + { + "name": "Idle", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "StadiumSky.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + } + ] + }, + { + "adaptCollisionMaskAutomatically": true, + "assetStoreId": "", + "name": "PlayerFlag", + "persistentUuid": "91db2bf0-d049-426b-a6b6-6fbcfacb4f9c", + "type": "Sprite", + "updateIfNotVisible": false, + "variables": [], + "effects": [], + "behaviors": [], + "animations": [ + { + "name": "Canada", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagCanada.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "USA", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagUSA.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "Belgium", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagBelgium.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "France", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagFrance.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "Spain", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagSpain.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "Germany", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagGermany.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + } + ] + }, + { + "adaptCollisionMaskAutomatically": true, + "assetStoreId": "", + "name": "OpponentFlag", + "type": "Sprite", + "updateIfNotVisible": false, + "variables": [], + "effects": [], + "behaviors": [], + "animations": [ + { + "name": "USA", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagUSA.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "Belgium", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagBelgium.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "France", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagFrance.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "Spain", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagSpain.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "Canada", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagCanada.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "Germany", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagGermany.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + } + ] + }, + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "TitleText", + "persistentUuid": "5ce32172-9127-49d7-b65c-e68ac570a0a7", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [], + "string": "AIR HOCKEY", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "characterSize": 130, + "color": { + "b": 255, + "g": 255, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": true, + "isShadowEnabled": true, + "italic": false, + "outlineColor": "30;40;110", + "outlineThickness": 10, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "10;20;60", + "shadowDistance": 5, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "AIR HOCKEY", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "verticalTextAlignment": "center", + "characterSize": 130, + "lineHeight": 0, + "color": "255;255;255" + } + }, + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "ChooseText", + "persistentUuid": "0e16103a-bc6a-43b8-9c07-82f583ccdad5", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [], + "string": "YOUR TEAM", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "characterSize": 46, + "color": { + "b": 255, + "g": 255, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": true, + "isShadowEnabled": true, + "italic": false, + "outlineColor": "30;40;110", + "outlineThickness": 6, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "10;20;60", + "shadowDistance": 5, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "YOUR TEAM", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "verticalTextAlignment": "center", + "characterSize": 46, + "lineHeight": 0, + "color": "255;255;255" + } + }, + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "PlayerName", + "persistentUuid": "e375b893-b487-4e15-b5c7-a8c8b304682c", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [], + "string": "CANADA", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "characterSize": 80, + "color": { + "b": 255, + "g": 255, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": true, + "isShadowEnabled": true, + "italic": false, + "outlineColor": "30;40;110", + "outlineThickness": 8, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "10;20;60", + "shadowDistance": 5, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "CANADA", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "verticalTextAlignment": "center", + "characterSize": 80, + "lineHeight": 0, + "color": "255;255;255" + } + }, + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "OpponentText", + "persistentUuid": "113564a4-4f9e-4f39-a6ee-7f03b74e0dbb", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [], + "string": "OPPONENT", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "characterSize": 80, + "color": { + "b": 255, + "g": 255, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": true, + "isShadowEnabled": true, + "italic": false, + "outlineColor": "30;40;110", + "outlineThickness": 8, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "10;20;60", + "shadowDistance": 5, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "OPPONENT", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "verticalTextAlignment": "center", + "characterSize": 80, + "lineHeight": 0, + "color": "255;255;255" + } + }, + { + "assetStoreId": "", + "name": "PlayButton", + "type": "PanelSpriteButton::PanelSpriteButton", + "variant": "Primary", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "LabelText": "PLAY" + } + }, + { + "assetStoreId": "", + "bottomMargin": 60, + "height": 32, + "leftMargin": 60, + "name": "TeamCard", + "rightMargin": 60, + "texture": "ModalPanel.png", + "tiled": false, + "topMargin": 60, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [], + "effects": [], + "behaviors": [] + }, + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "HintText", + "persistentUuid": "f2487698-cc3e-49a0-81ff-d072ef1e78d7", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [], + "string": "First to 5 goals wins! Roll the puck over power-ups to grab them.", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "characterSize": 34, + "color": { + "b": 255, + "g": 255, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": true, + "isShadowEnabled": true, + "italic": false, + "outlineColor": "30;40;110", + "outlineThickness": 4, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "10;20;60", + "shadowDistance": 5, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "First to 5 goals wins! Roll the puck over power-ups to grab them.", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "verticalTextAlignment": "center", + "characterSize": 34, + "lineHeight": 0, + "color": "255;255;255" + } + }, + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "FooterText", + "persistentUuid": "478a360a-9a78-4f2f-b82b-c9f8b5da233b", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [], + "string": "Made with GDevelop", + "font": "Coiny-Regular.ttf", + "textAlignment": "left", + "characterSize": 26, + "color": { + "b": 255, + "g": 215, + "r": 200 + }, + "content": { + "bold": false, + "isOutlineEnabled": false, + "isShadowEnabled": false, + "italic": false, + "outlineColor": "255;255;255", + "outlineThickness": 2, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "0;0;0", + "shadowDistance": 4, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "Made with GDevelop", + "font": "Coiny-Regular.ttf", + "textAlignment": "left", + "verticalTextAlignment": "top", + "characterSize": 26, + "lineHeight": 0, + "color": "200;215;255" + } + }, + { + "assetStoreId": "", + "name": "UI_CountryTile", + "persistentUuid": "12b100eb-926e-4620-bba6-2025b2a1abe0", + "type": "AirHockeyUI::UI_CountryTile", + "variant": "", + "variables": [ + { + "name": "Country", + "type": "string", + "value": "" + } + ], + "effects": [], + "behaviors": [], + "content": {} + }, + { + "assetStoreId": "", + "bottomMargin": 60, + "height": 60, + "leftMargin": 60, + "name": "RosterCard", + "rightMargin": 60, + "texture": "ModalPanel.png", + "tiled": false, + "topMargin": 60, + "type": "PanelSpriteObject::PanelSprite", + "width": 120, + "variables": [], + "effects": [], + "behaviors": [] + }, + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "RosterText", + "persistentUuid": "e50e3b80-b1d7-4759-995f-3828b36b4963", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [], + "string": "PICK A COUNTRY", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "characterSize": 46, + "color": { + "b": 255, + "g": 255, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": true, + "isShadowEnabled": true, + "italic": false, + "outlineColor": "30;40;110", + "outlineThickness": 6, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "10;20;60", + "shadowDistance": 5, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "PICK A COUNTRY", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "verticalTextAlignment": "center", + "characterSize": 46, + "lineHeight": 0, + "color": "255;255;255" + } + }, + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "VsText", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [], + "string": "VS", + "font": "RobotoMono-Bold.ttf", + "textAlignment": "center", + "characterSize": 130, + "color": { + "b": 40, + "g": 200, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": true, + "isShadowEnabled": true, + "italic": false, + "outlineColor": "30;40;110", + "outlineThickness": 10, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "10;20;60", + "shadowDistance": 5, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "VS", + "font": "RobotoMono-Bold.ttf", + "textAlignment": "center", + "verticalTextAlignment": "center", + "characterSize": 130, + "lineHeight": 0, + "color": "255;200;40" + } + }, + { + "additive": true, + "assetStoreId": "bb73dd3f9d73112c5c66f319c7714c5d32888cdb557d87ebb25d518666e95f95", + "destroyWhenNoParticles": false, + "emitterAngleA": 0, + "emitterAngleB": 360, + "emitterForceMax": 22, + "emitterForceMin": 4, + "flow": 18, + "jumpForwardInTimeOnCreation": 9, + "maxParticleNb": 240, + "name": "MenuParticles", + "particleAlpha1": 230, + "particleAlpha2": 0, + "particleAlphaRandomness1": 0, + "particleAlphaRandomness2": 0, + "particleAngle1": 0, + "particleAngle2": 0, + "particleAngleRandomness1": 0, + "particleAngleRandomness2": 0, + "particleBlue1": 214, + "particleBlue2": 255, + "particleColor1": "255;244;214", + "particleColor2": "190;220;255", + "particleGravityX": 3, + "particleGravityY": -9, + "particleGreen1": 244, + "particleGreen2": 220, + "particleLifeTimeMax": 12, + "particleLifeTimeMin": 7, + "particleRed1": 255, + "particleRed2": 190, + "particleSize1": 120, + "particleSize2": 50, + "particleSizeRandomness1": 0, + "particleSizeRandomness2": 0, + "persistentUuid": "1259b6e3-d7cc-40e9-a9ee-fad55e36235f", + "rendererParam1": 9, + "rendererParam2": 128, + "rendererType": "Point", + "tank": -1, + "textureParticleName": "", + "type": "ParticleSystem::ParticleEmitter", + "zoneRadius": 1150, + "variables": [], + "effects": [], + "behaviors": [] + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "folderName": "Background", + "children": [ + { + "objectName": "MenuBackground" + }, + { + "objectName": "MenuParticles" + } + ] + }, + { + "folderName": "Cards", + "children": [ + { + "objectName": "TeamCard" + }, + { + "objectName": "PlayerFlag" + }, + { + "objectName": "PlayerName" + }, + { + "objectName": "RosterCard" + }, + { + "objectName": "RosterText" + }, + { + "objectName": "UI_CountryTile" + }, + { + "objectName": "OpponentFlag" + }, + { + "objectName": "OpponentText" + }, + { + "objectName": "VsText" + } + ] + }, + { + "folderName": "Texts", + "children": [ + { + "objectName": "TitleText" + }, + { + "objectName": "ChooseText" + }, + { + "objectName": "HintText" + }, + { + "objectName": "FooterText" + } + ] + }, + { + "folderName": "Buttons", + "children": [ + { + "objectName": "PlayButton" + } + ] + } + ] + }, + "events": [ + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Menu setup", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "The match hides the mouse cursor (pointer lock): show it again. Each tile shows the country written in its instance variable Country (set on each instance in the editor).", + "comment2": "Tile Index() = position of its country in the global CountryList (keys and roulette use it). New tile = new instance with Country set." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "SceneJustBegins" + }, + "parameters": [ + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "ShowCursor" + }, + "parameters": [ + "" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::ForEachChildVariable", + "iterableVariableName": "CountryList", + "valueIteratorVariableName": "ListCountry", + "keyIteratorVariableName": "ListIndex", + "conditions": [], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringObjectVariable" + }, + "parameters": [ + "UI_CountryTile", + "Country", + "=", + "ListCountry" + ] + } + ], + "actions": [ + { + "type": { + "value": "AirHockeyUI::UI_CountryTile::SetCountry" + }, + "parameters": [ + "UI_CountryTile", + "ListCountry", + "Countries[ListCountry].Name", + "ToNumber(ListIndex)", + "" + ] + } + ] + } + ], + "variables": [ + { + "name": "ListCountry", + "type": "string", + "value": "" + }, + { + "name": "ListIndex", + "type": "string", + "value": "" + } + ] + } + ] + } + ], + "parameters": [] + }, + { + "type": "BuiltinCommonInstructions::Link", + "include": { + "includeConfig": 0 + }, + "target": "OptionsMenu" + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Options window over the menu", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Trigger once: the buttons are switched only on change, so the Drawing state can still switch the tiles off.", + "comment2": "After the OptionsMenu link, so buttons go off the frame the window opens. The not-open branch also fires on frame 1." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "AirHockeyUI::UI_OptionsModal::IsOpen" + }, + "parameters": [ + "UI_OptionsModal", + "" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "MenuButtons", + "no", + "" + ] + }, + { + "type": { + "value": "AirHockeyUI::UI_CountryTile::SetClickable" + }, + "parameters": [ + "UI_CountryTile", + "no", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "AirHockeyUI::UI_OptionsModal::IsOpen" + }, + "parameters": [ + "UI_OptionsModal", + "" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "MenuButtons", + "yes", + "" + ] + }, + { + "type": { + "value": "AirHockeyUI::UI_CountryTile::SetClickable" + }, + "parameters": [ + "UI_CountryTile", + "yes", + "" + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Menu transitions", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "The pointer lock is requested on the PLAY click itself: browsers grant it only during a real click.", + "comment2": "Only writer of Menu.State. MenuTimer, reset on Drawing entry, drives the roulette, VS reveal and scene change." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Menu.State", + "=", + "\"Choosing\"" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::IsClicked" + }, + "parameters": [ + "PlayButton", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Menu.State", + "=", + "\"Drawing\"" + ] + }, + { + "type": { + "value": "ResetTimer" + }, + "parameters": [ + "", + "\"MenuTimer\"" + ] + }, + { + "type": { + "value": "MousePointerLock::RequestPointerLock" + }, + "parameters": [ + "", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Menu.State", + "=", + "\"Drawing\"" + ] + }, + { + "type": { + "value": "CompareTimer" + }, + "parameters": [ + "", + "\"MenuTimer\"", + ">", + "Menu.DrawSeconds" + ] + } + ], + "actions": [ + { + "type": { + "value": "Scene" + }, + "parameters": [ + "", + "\"Game\"", + "yes" + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Menu states", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Selection.PlayerCountry", + "=", + "CountryList[Menu.CountryIndex]" + ] + }, + { + "type": { + "value": "TextContainerCapability::TextContainerBehavior::SetValue" + }, + "parameters": [ + "PlayerName", + "Text", + "=", + "Countries[Selection.PlayerCountry].Name" + ] + }, + { + "type": { + "value": "AnimatableCapability::AnimatableBehavior::SetName" + }, + "parameters": [ + "PlayerFlag", + "Animation", + "=", + "Selection.PlayerCountry" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Menu.State", + "=", + "\"Choosing\"" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "KeyFromTextJustPressed" + }, + "parameters": [ + "", + "\"Left\"" + ] + }, + { + "type": { + "inverted": true, + "value": "AirHockeyUI::UI_OptionsModal::IsOpen" + }, + "parameters": [ + "UI_OptionsModal", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Menu.CountryIndex", + "=", + "mod(Menu.CountryIndex - 1 + VariableChildCount(CountryList), VariableChildCount(CountryList))" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "KeyFromTextJustPressed" + }, + "parameters": [ + "", + "\"Right\"" + ] + }, + { + "type": { + "inverted": true, + "value": "AirHockeyUI::UI_OptionsModal::IsOpen" + }, + "parameters": [ + "UI_OptionsModal", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Menu.CountryIndex", + "=", + "mod(Menu.CountryIndex + 1, VariableChildCount(CountryList))" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "AirHockeyUI::UI_CountryTile::IsClicked" + }, + "parameters": [ + "UI_CountryTile", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Menu.CountryIndex", + "=", + "UI_CountryTile.Index()" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "mod(CountryIndex + a random 1..N-1, N) never lands on your own country: used for the opponent and each roulette jump.", + "comment2": "RouletteTimer paces the jumps; MenuTimer (reset in Menu transitions) ends the roulette and reveals the VS." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Menu.State", + "=", + "\"Drawing\"" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Menu.OpponentIndex", + "=", + "mod(Menu.CountryIndex + RandomInRange(1, VariableChildCount(CountryList) - 1), VariableChildCount(CountryList))" + ] + }, + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Selection.OpponentCountry", + "=", + "CountryList[Menu.OpponentIndex]" + ] + }, + { + "type": { + "value": "TextContainerCapability::TextContainerBehavior::SetValue" + }, + "parameters": [ + "OpponentText", + "Text", + "=", + "Countries[Selection.OpponentCountry].Name" + ] + }, + { + "type": { + "value": "AnimatableCapability::AnimatableBehavior::SetName" + }, + "parameters": [ + "OpponentFlag", + "Animation", + "=", + "Selection.OpponentCountry" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "PlayButton" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "HintText" + ] + }, + { + "type": { + "value": "AirHockeyUI::UI_CountryTile::SetClickable" + }, + "parameters": [ + "UI_CountryTile", + "no", + "" + ] + }, + { + "type": { + "value": "ResetTimer" + }, + "parameters": [ + "", + "\"RouletteTimer\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "CompareTimer" + }, + "parameters": [ + "", + "\"MenuTimer\"", + "<", + "Menu.RouletteSeconds" + ] + }, + { + "type": { + "value": "CompareTimer" + }, + "parameters": [ + "", + "\"RouletteTimer\"", + ">", + "Menu.RouletteStepSeconds" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Menu.RouletteIndex", + "=", + "mod(Menu.CountryIndex + RandomInRange(1, VariableChildCount(CountryList) - 1), VariableChildCount(CountryList))" + ] + }, + { + "type": { + "value": "ResetTimer" + }, + "parameters": [ + "", + "\"RouletteTimer\"" + ] + }, + { + "type": { + "value": "PlaySound" + }, + "parameters": [ + "", + "ButtonClick.mp3", + "", + "35", + "1.4" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "CompareTimer" + }, + "parameters": [ + "", + "\"MenuTimer\"", + ">=", + "Menu.RouletteSeconds" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Menu.RouletteIndex", + "=", + "Menu.OpponentIndex" + ] + }, + { + "type": { + "value": "PlaySound" + }, + "parameters": [ + "", + "Whistle.aac", + "", + "70", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "CompareTimer" + }, + "parameters": [ + "", + "\"MenuTimer\"", + ">", + "Menu.RouletteSeconds + Menu.VsDelaySeconds" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "Hide" + }, + "parameters": [ + "UI_CountryTile" + ] + }, + { + "type": { + "value": "TextContainerCapability::TextContainerBehavior::SetValue" + }, + "parameters": [ + "RosterText", + "Text", + "=", + "\"OPPONENT\"" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "OpponentFlag", + "" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "OpponentText", + "" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "VsText", + "" + ] + } + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Tile highlight", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::ForEach", + "object": "UI_CountryTile", + "conditions": [], + "actions": [ + { + "type": { + "value": "AirHockeyUI::UI_CountryTile::SetHighlight" + }, + "parameters": [ + "UI_CountryTile", + "\"None\"", + "" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "UI_CountryTile.Index()", + "=", + "Menu.CountryIndex" + ] + } + ], + "actions": [ + { + "type": { + "value": "AirHockeyUI::UI_CountryTile::SetHighlight" + }, + "parameters": [ + "UI_CountryTile", + "\"Player\"", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Menu.State", + "=", + "\"Drawing\"" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "UI_CountryTile.Index()", + "=", + "Menu.RouletteIndex" + ] + } + ], + "actions": [ + { + "type": { + "value": "AirHockeyUI::UI_CountryTile::SetHighlight" + }, + "parameters": [ + "UI_CountryTile", + "\"Opponent\"", + "" + ] + } + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Screen layout", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Wide screens: keep the 2D menu centred on its 1920x1080 design.", + "comment2": "UI layers (HUD, Modal) are centred in the OptionsMenu 'Screen layout' group; this scene also centres its base and Background layers." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetCameraCenterX" + }, + "parameters": [ + "", + "=", + "960", + "\"\"", + "0" + ] + }, + { + "type": { + "value": "SetCameraCenterY" + }, + "parameters": [ + "", + "=", + "540", + "\"\"", + "0" + ] + }, + { + "type": { + "value": "SetCameraCenterX" + }, + "parameters": [ + "", + "=", + "960", + "\"Background\"", + "0" + ] + }, + { + "type": { + "value": "SetCameraCenterY" + }, + "parameters": [ + "", + "=", + "540", + "\"Background\"", + "0" + ] + } + ] + } + ], + "parameters": [] + } + ], + "layers": [ + { + "ambientLightColorB": 200, + "ambientLightColorG": 200, + "ambientLightColorR": 200, + "camera2DPlaneMaxDrawingDistance": 5000, + "camera3DFarPlaneDistance": 10000, + "camera3DFieldOfView": 45, + "camera3DNearPlaneDistance": 3, + "cameraType": "", + "followBaseLayerCamera": false, + "isLightingLayer": false, + "isLocked": false, + "name": "Background", + "renderingType": "", + "visibility": true, + "cameras": [], + "effects": [] + }, + { + "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": [] + }, + { + "ambientLightColorB": 200, + "ambientLightColorG": 200, + "ambientLightColorR": 200, + "camera2DPlaneMaxDrawingDistance": 5000, + "camera3DFarPlaneDistance": 10000, + "camera3DFieldOfView": 45, + "camera3DNearPlaneDistance": 3, + "cameraType": "", + "followBaseLayerCamera": false, + "isLightingLayer": false, + "isLocked": false, + "name": "HUD", + "renderingType": "", + "visibility": true, + "cameras": [], + "effects": [] + }, + { + "ambientLightColorB": 200, + "ambientLightColorG": 200, + "ambientLightColorR": 200, + "camera2DPlaneMaxDrawingDistance": 5000, + "camera3DFarPlaneDistance": 10000, + "camera3DFieldOfView": 45, + "camera3DNearPlaneDistance": 3, + "cameraType": "", + "followBaseLayerCamera": false, + "isLightingLayer": false, + "isLocked": false, + "name": "Modal", + "renderingType": "", + "visibility": false, + "cameras": [], + "effects": [] + } + ], + "behaviorsSharedData": [ + { + "name": "Animation", + "type": "AnimatableCapability::AnimatableBehavior" + }, + { + "name": "Effect", + "type": "EffectCapability::EffectBehavior" + }, + { + "name": "Flippable", + "type": "FlippableCapability::FlippableBehavior" + }, + { + "name": "Opacity", + "type": "OpacityCapability::OpacityBehavior" + }, + { + "name": "Resizable", + "type": "ResizableCapability::ResizableBehavior" + }, + { + "name": "Scale", + "type": "ScalableCapability::ScalableBehavior" + }, + { + "name": "Text", + "type": "TextContainerCapability::TextContainerBehavior" + } + ] + }, + { + "b": 255, + "disableInputWhenNotFocused": true, + "mangledName": "Game", + "name": "Game", + "r": 247, + "renderer3DWorldScale": 100, + "standardSortMethod": true, + "stopSoundsOnStartup": true, + "title": "", + "v": 249, + "uiSettings": { + "grid": false, + "gridType": "rectangular", + "gridWidth": 32, + "gridHeight": 32, + "gridDepth": 32, + "gridOffsetX": 0, + "gridOffsetY": 0, + "gridOffsetZ": 0, + "gridColor": 10401023, + "gridAlpha": 0.8, + "snap": false, + "zoomFactor": 0.45985214267363295, + "windowMask": false, + "selectedLayer": "", + "gameEditorMode": "embedded-game" + }, + "objectsGroups": [ + { + "name": "Mallets", + "objects": [ + { + "name": "MalletPlayer" + }, + { + "name": "MalletOpponent" + } + ] + }, + { + "name": "PowerUpTokens", + "objects": [ + { + "name": "PowerUpBigMallet" + }, + { + "name": "PowerUpFreeze" + }, + { + "name": "PowerUpTurbo" + }, + { + "name": "PowerUpShield" + } + ] + }, + { + "name": "MalletSkins", + "objects": [ + { + "name": "MalletUSA" + }, + { + "name": "MalletBelgium" + }, + { + "name": "MalletFrance" + }, + { + "name": "MalletSpain" + }, + { + "name": "MalletCanada" + }, + { + "name": "MalletGermany" + } + ] + }, + { + "name": "CountryFlags", + "objects": [ + { + "name": "FlagUSA" + }, + { + "name": "FlagBelgium" + }, + { + "name": "FlagFrance" + }, + { + "name": "FlagSpain" + }, + { + "name": "FlagCanada" + }, + { + "name": "FlagGermany" + } + ] + } + ], + "variables": [ + { + "name": "CountryModels", + "persistentUuid": "54ba96b1-2265-44c3-93a5-5a077acfb5f4", + "type": "structure", + "children": [ + { + "name": "AreCreated", + "persistentUuid": "2a5f7e5d-a98a-4bb6-a7d2-8cd1cfc6cd8d", + "type": "boolean", + "value": false + }, + { + "name": "FlagSpots", + "persistentUuid": "60ee0538-dede-4c51-b32a-22aef6e2813c", + "type": "array", + "children": [] + } + ] + }, + { + "name": "Match", + "persistentUuid": "73049c35-0cfa-4ca3-8ae9-58404b703dc5", + "type": "structure", + "children": [ + { + "name": "ElapsedSeconds", + "persistentUuid": "959b86c1-b141-4f87-843f-16666a854114", + "type": "number", + "value": 0 + }, + { + "name": "GoalCelebrationSeconds", + "persistentUuid": "a4cd18a8-cbb2-4bea-9409-37fb93030d00", + "type": "number", + "value": 2 + }, + { + "name": "GoalsToWin", + "persistentUuid": "98c9346d-1afc-4b7c-b1e3-68760ba09c49", + "type": "number", + "value": 5 + }, + { + "name": "IntroSeconds", + "persistentUuid": "6fb0b77f-c13b-489b-b3b9-29327882b90f", + "type": "number", + "value": 4.5 + }, + { + "name": "KickoffSeconds", + "persistentUuid": "4fea0bcd-ead6-402b-ad37-ab62dcdb3793", + "type": "number", + "value": 1.5 + }, + { + "name": "LastHitter", + "persistentUuid": "a7ed50c7-6702-49fb-903d-ff1fba2a611f", + "type": "string", + "value": "" + }, + { + "name": "LastScorer", + "persistentUuid": "4eac570c-1e5e-4b85-be03-dda60e650106", + "type": "string", + "value": "None" + }, + { + "name": "MusicStarted", + "persistentUuid": "388dcd87-8e9a-46b1-9ed7-21dcffff41bf", + "type": "boolean", + "value": false + }, + { + "name": "OpponentCode", + "persistentUuid": "e1188467-c2fc-408e-a6c6-daeeeb606cda", + "type": "string", + "value": "BEL" + }, + { + "name": "OpponentCountry", + "persistentUuid": "098eddec-f0cf-4cd4-b15f-94e9e8c5a30a", + "type": "string", + "value": "Belgium" + }, + { + "name": "OpponentName", + "persistentUuid": "1da9b444-d2ef-4b3a-ba7c-b04dafac1642", + "type": "string", + "value": "BELGIUM" + }, + { + "name": "PlayerCode", + "persistentUuid": "ace3e2e3-0340-4083-876b-4b33ee64c0a7", + "type": "string", + "value": "USA" + }, + { + "name": "PlayerCountry", + "persistentUuid": "629270d7-e9ad-45a8-b46f-c2fcc7accffd", + "type": "string", + "value": "USA" + }, + { + "name": "ScoreOpponent", + "persistentUuid": "2626e9f4-bd06-4660-b51d-6bbd00185550", + "type": "number", + "value": 0 + }, + { + "name": "ScorePlayer", + "persistentUuid": "f2b93e1c-012d-469a-a00b-d7f1cebdfd68", + "type": "number", + "value": 0 + }, + { + "name": "State", + "persistentUuid": "89c842bb-4c87-4c00-ab67-2e41521cf91a", + "type": "string", + "value": "Intro" + } + ] + }, + { + "name": "Field", + "persistentUuid": "f58ff8d4-4feb-4c28-b71e-d706c91da4ba", + "type": "structure", + "children": [ + { + "name": "Bottom", + "persistentUuid": "73794eaf-24f5-4f6e-ba03-cb585699858f", + "type": "number", + "value": 1040 + }, + { + "name": "CenterX", + "persistentUuid": "0f1600b3-0867-4e3b-98f6-d9982ac6e766", + "type": "number", + "value": 960 + }, + { + "name": "CenterY", + "persistentUuid": "fbce9ddc-24b2-491d-b76f-07de3e946393", + "type": "number", + "value": 540 + }, + { + "name": "GoalHalfWidth", + "persistentUuid": "5feb48c8-8254-4b16-91e6-b24e81a56915", + "type": "number", + "value": 104 + }, + { + "name": "GoalLineMargin", + "persistentUuid": "82287a4a-58ba-4953-9e8c-c3c6f5d619fb", + "type": "number", + "value": 30 + }, + { + "name": "Left", + "persistentUuid": "477457ac-61e2-4da4-9e0d-ede4f4aa8e97", + "type": "number", + "value": 660 + }, + { + "name": "MalletRadius", + "persistentUuid": "a20a5baa-29d5-4ae5-ae68-2481bfc387a5", + "type": "number", + "value": 55 + }, + { + "name": "PuckRadius", + "persistentUuid": "e3ab5905-3314-4d12-889b-4618c074c164", + "type": "number", + "value": 33 + }, + { + "name": "Right", + "persistentUuid": "44287807-e3e8-4928-a229-1b7e29862d40", + "type": "number", + "value": 1260 + }, + { + "name": "Top", + "persistentUuid": "a3bc200e-2383-49fe-9e86-78e29464500a", + "type": "number", + "value": 40 + } + ] + }, + { + "name": "Tuning", + "persistentUuid": "69086384-5e11-4c7b-8bc5-8b2e7e799325", + "type": "structure", + "children": [ + { + "name": "Hit", + "persistentUuid": "9cdad8dd-7bc7-4247-b180-2aa60e626828", + "type": "structure", + "children": [ + { + "name": "ExtraHighScale", + "persistentUuid": "07e9458c-01f5-4df5-b065-34e8a52c6058", + "type": "number", + "value": 0.3 + }, + { + "name": "ExtraLowScale", + "persistentUuid": "6d01d3df-8eec-4ad9-904d-7c27acb457f3", + "type": "number", + "value": 0.65 + }, + { + "name": "ExtraLowSpeed", + "persistentUuid": "6878f7be-8370-45c9-a1c0-84bc67e31943", + "type": "number", + "value": 92 + }, + { + "name": "ExtraMidScale", + "persistentUuid": "34d95ce4-4404-4a40-b808-0c14e9719216", + "type": "number", + "value": 0.55 + }, + { + "name": "ExtraMidSpeed", + "persistentUuid": "ae2d710e-64ff-4058-98e4-3b5724f76853", + "type": "number", + "value": 420 + }, + { + "name": "ExtraSpeedCap", + "persistentUuid": "d76e4a7f-2f20-4c2d-a1fb-adf3c7f68006", + "type": "number", + "value": 840 + }, + { + "name": "FrictionShare", + "persistentUuid": "d9e9099a-10cd-415d-80e9-e0de01fe3c55", + "type": "number", + "value": 0.2857 + }, + { + "name": "MinSeparationSpeed", + "persistentUuid": "95407db8-8c38-41db-9a19-2d9d663f7ba1", + "type": "number", + "value": 120 + }, + { + "name": "Restitution", + "persistentUuid": "0587dcc1-2b9c-4ec8-8516-654391e28433", + "type": "number", + "value": 0 + } + ] + }, + { + "name": "Opponent", + "persistentUuid": "de4f5e40-b7dd-47f9-9cf3-9243957844b4", + "type": "structure", + "children": [ + { + "name": "AimError", + "persistentUuid": "1978e18d-8db2-4ecd-8e33-42103893967d", + "type": "number", + "value": 130 + }, + { + "name": "AimRefreshSeconds", + "persistentUuid": "ffb2c4bc-9601-42ff-a8a5-9e6477fdc277", + "type": "number", + "value": 0.8 + }, + { + "name": "AttackGain", + "persistentUuid": "8bba9b0b-0147-46b5-a0cc-76baef1e8563", + "type": "number", + "value": 7 + }, + { + "name": "AttackMaxSpeed", + "persistentUuid": "fbfc58ad-f84c-4c0d-8713-5ca2555bdfda", + "type": "number", + "value": 800 + }, + { + "name": "DefendGain", + "persistentUuid": "06381824-c144-445e-900a-76233917bf85", + "type": "number", + "value": 3 + }, + { + "name": "GuardLineY", + "persistentUuid": "d646343f-774f-4115-99b0-4062dff5b6f1", + "type": "number", + "value": 130 + }, + { + "name": "HesitationChance", + "persistentUuid": "10f3ea2a-da4e-4822-8e66-2c1c8ca9bd34", + "type": "number", + "value": 0.5 + }, + { + "name": "HesitationMaxSeconds", + "persistentUuid": "c542f096-d1fe-44e5-8d6f-b73a06f375fb", + "type": "number", + "value": 0.7 + }, + { + "name": "MaxSpeed", + "persistentUuid": "4b1be0d0-5102-4ccd-804e-b75ef75d2b22", + "type": "number", + "value": 420 + }, + { + "name": "SpeedFactorMin", + "persistentUuid": "ea949ca2-f3ce-48f7-9d76-29f763759027", + "type": "number", + "value": 0.45 + }, + { + "name": "StrikeChance", + "persistentUuid": "2a638c58-905a-41a0-b135-0ddfbe5ff35a", + "type": "number", + "value": 0.85 + }, + { + "name": "StrikeRange", + "persistentUuid": "abc4c590-13d1-46cb-9e2d-b56609b47faf", + "type": "number", + "value": 150 + }, + { + "name": "StrikeSeconds", + "persistentUuid": "3cb7d26d-b6f9-4291-a197-9185b5d31b4d", + "type": "number", + "value": 0.22 + }, + { + "name": "StrikeSpeed", + "persistentUuid": "5bda00f4-bd87-4adb-98f9-d6c8ef63bb1e", + "type": "number", + "value": 1150 + }, + { + "name": "StuckDistance", + "persistentUuid": "8c09584c-3d96-416a-a88d-f784a7bf1eff", + "type": "number", + "value": 6 + }, + { + "name": "StuckSeconds", + "persistentUuid": "3453959e-9f2b-4777-906d-7e1426d7641d", + "type": "number", + "value": 2 + }, + { + "name": "UnstickDistance", + "persistentUuid": "2ae2f9e6-2330-46e2-9272-ebf14384c4b8", + "type": "number", + "value": 220 + }, + { + "name": "UnstickSeconds", + "persistentUuid": "39cda840-13af-431f-a6d2-371cd606f93a", + "type": "number", + "value": 0.5 + } + ] + }, + { + "name": "Player", + "persistentUuid": "ac2bdac2-4eb7-46b1-b7cb-db3068974bd8", + "type": "structure", + "children": [ + { + "name": "MaxSpeed", + "persistentUuid": "8c30e1d0-4f21-48fe-b382-e699b3e8c250", + "type": "number", + "value": 2600 + } + ] + }, + { + "name": "Puck", + "persistentUuid": "bc60c527-1cbd-4307-ab53-c4129dd919f5", + "type": "structure", + "children": [ + { + "name": "MaxSpeed", + "persistentUuid": "a142c634-005f-4aff-be38-c41b72a8f836", + "type": "number", + "value": 1100 + }, + { + "name": "NudgeSpeed", + "persistentUuid": "0af091d3-38ea-48b2-add3-ef17484088cb", + "type": "number", + "value": 320 + }, + { + "name": "StuckSeconds", + "persistentUuid": "69f14fba-5d16-46eb-92be-a766fdd4000e", + "type": "number", + "value": 2 + }, + { + "name": "StuckSpeed", + "persistentUuid": "4c282697-1bcc-47af-8707-fad20ef59d3b", + "type": "number", + "value": 30 + } + ] + } + ] + }, + { + "name": "CameraSettings", + "persistentUuid": "99c97482-63a5-4b6b-baa1-6937e47c9cda", + "type": "structure", + "children": [ + { + "name": "FieldOfView", + "persistentUuid": "2a42675a-a870-4ff8-8b8c-7feff0adb8f4", + "type": "number", + "value": 48 + }, + { + "name": "IntroHeight", + "persistentUuid": "7946fa94-e004-443a-93e7-090a3304a738", + "type": "number", + "value": 1150 + }, + { + "name": "IntroRadius", + "persistentUuid": "7cba57d2-80f5-42f2-87c3-729dba28e828", + "type": "number", + "value": 1700 + }, + { + "name": "IntroStartAngle", + "persistentUuid": "d1b39b90-b153-4706-a121-e2f87150dbcf", + "type": "number", + "value": 200 + }, + { + "name": "ParallaxFollowSpeed", + "persistentUuid": "ad8188dc-ddf5-4b93-9a61-fb7fa99125b2", + "type": "number", + "value": 3 + }, + { + "name": "ParallaxX", + "persistentUuid": "21cf2892-6336-432b-82e8-802f80debf9c", + "type": "number", + "value": 28 + }, + { + "name": "ParallaxY", + "persistentUuid": "ef9919d2-01cd-48cc-a65c-ac9274d83fef", + "type": "number", + "value": 16 + }, + { + "name": "ScoreboardCentreY", + "persistentUuid": "6a7f4064-33bf-4395-b429-254c478a5b1d", + "type": "number", + "value": 465 + }, + { + "name": "ScoreboardTopY", + "persistentUuid": "49c287c1-cedf-4c65-b575-9df870f60af7", + "type": "number", + "value": 20 + }, + { + "name": "ShakeAmplitude", + "persistentUuid": "df425f62-6f38-42f0-9f36-d66a4d8e94b5", + "type": "number", + "value": 16 + }, + { + "name": "ShakeSeconds", + "persistentUuid": "a2c61b94-22dc-4055-86a9-bb30a388cd6c", + "type": "number", + "value": 0.55 + } + ] + }, + { + "name": "Crowd", + "persistentUuid": "002d70e6-8244-4439-beb9-bd768d6600a8", + "type": "structure", + "children": [ + { + "name": "IntroWaveDelaySeconds", + "persistentUuid": "cfdf5fe9-78af-4aa2-8ff3-701983afa753", + "type": "number", + "value": 1 + }, + { + "name": "WaveChanceOneIn", + "persistentUuid": "88b76656-a93e-446a-b346-e58f94a3fbf5", + "type": "number", + "value": 3 + }, + { + "name": "WaveCheckSeconds", + "persistentUuid": "d9244310-4812-4ff8-b0b3-3e4a1c399eb2", + "type": "number", + "value": 6 + } + ] + }, + { + "name": "TrailSettings", + "persistentUuid": "d8009e18-13dc-479d-b252-e75370e05cb0", + "type": "structure", + "children": [ + { + "name": "LifeSeconds", + "persistentUuid": "2c838efe-c515-4ebe-94ba-588f3dd9bbe5", + "type": "number", + "value": 0.45 + }, + { + "name": "MinStep", + "persistentUuid": "a8581769-0d5c-438a-b794-d3e1efed7997", + "type": "number", + "value": 1 + }, + { + "name": "Width", + "persistentUuid": "226cdd33-5ec9-4338-9ad4-0252da66bb5c", + "type": "number", + "value": 46 + } + ] + }, + { + "name": "CameraRig", + "persistentUuid": "975c3879-0f97-4149-9d4e-cfb46dd1904e", + "type": "structure", + "children": [ + { + "name": "ParallaxOffsetX", + "persistentUuid": "b0e3cd60-8a7e-4a70-869b-1240aa35d625", + "type": "number", + "value": 0 + }, + { + "name": "ParallaxOffsetY", + "persistentUuid": "9706e320-d79b-4879-9729-e8ec50348527", + "type": "number", + "value": 0 + }, + { + "name": "ShakeTimeLeft", + "persistentUuid": "11c93b26-4e83-4efc-b1d3-983b49d41f81", + "type": "number", + "value": 0 + } + ] + }, + { + "name": "PowerUps", + "persistentUuid": "93e503a7-c238-4ea3-9be4-b034a1b6d39b", + "type": "structure", + "children": [ + { + "name": "BigScale", + "persistentUuid": "669a99a8-fc4c-420c-a911-1c9c11d9f448", + "type": "number", + "value": 1.6 + }, + { + "name": "EffectSeconds", + "persistentUuid": "f54d76b8-0ccb-4912-8ed2-f865251bf785", + "type": "number", + "value": 6 + }, + { + "name": "FreezeSeconds", + "persistentUuid": "f9d61afa-6a39-4c33-b395-faefc4315fec", + "type": "number", + "value": 2.5 + }, + { + "name": "Kinds", + "persistentUuid": "fc285fd0-4861-4c76-9490-ab5d147270af", + "type": "array", + "children": [ + { + "persistentUuid": "405d478f-0312-4cae-85e6-e49dbb328832", + "type": "string", + "value": "BigMallet" + }, + { + "persistentUuid": "c49592d1-5a51-4ffc-930f-1112632f8086", + "type": "string", + "value": "Freeze" + }, + { + "persistentUuid": "687c51e1-3343-4f98-8f8c-a491ae683224", + "type": "string", + "value": "Turbo" + }, + { + "persistentUuid": "76960aaa-8960-448b-9421-c71cf6cf6c9b", + "type": "string", + "value": "Shield" + } + ] + }, + { + "name": "Labels", + "persistentUuid": "095fe677-3714-428c-8521-5d4d5f4cb35d", + "type": "structure", + "children": [ + { + "name": "BigMallet", + "persistentUuid": "b1814ee2-dbe6-43d9-a4ca-dcc0caf843ac", + "type": "string", + "value": "BIG MALLET!" + }, + { + "name": "Freeze", + "persistentUuid": "bccea996-4f1a-4363-9ec0-80c089d27ff2", + "type": "string", + "value": "FREEZE!" + }, + { + "name": "Shield", + "persistentUuid": "63b70b4a-ecb3-4def-b255-fdc3ea44b5f8", + "type": "string", + "value": "GOAL SHIELD!" + }, + { + "name": "Turbo", + "persistentUuid": "f64c90e7-c8de-4514-af4f-0c1ca717951b", + "type": "string", + "value": "TURBO PUCK!" + } + ] + }, + { + "name": "LifeSeconds", + "persistentUuid": "700f2287-364e-4d51-ab42-4e72ae1082dc", + "type": "number", + "value": 7 + }, + { + "name": "MessageSeconds", + "persistentUuid": "c53eebff-6296-4bb9-842e-1793a0c87f8c", + "type": "number", + "value": 1.4 + }, + { + "name": "PickupRadius", + "persistentUuid": "f82a16c5-2d34-4a1d-8337-caee9b08f044", + "type": "number", + "value": 90 + }, + { + "name": "PuckSpeedCap", + "persistentUuid": "b43569e6-9730-42e7-930e-8a193487d812", + "type": "number", + "value": 1100 + }, + { + "name": "RingBlinkSpeed", + "persistentUuid": "8ac047c3-26a1-4fbf-af81-f01c458c4d63", + "type": "number", + "value": 4 + }, + { + "name": "RingBlinkSpeedWarning", + "persistentUuid": "84a66746-b5b4-412a-949c-ed9077aad97c", + "type": "number", + "value": 12 + }, + { + "name": "RingRadius", + "persistentUuid": "d168f305-078d-4cad-b8a0-057ad4a7f94d", + "type": "number", + "value": 64 + }, + { + "name": "RingSegments", + "persistentUuid": "8c8213ec-400a-43f2-bc0a-dd67c7215bb3", + "type": "number", + "value": 48 + }, + { + "name": "RingWarningShare", + "persistentUuid": "4c5eefd3-c9af-4a14-8ceb-519b920a1853", + "type": "number", + "value": 0.33 + }, + { + "name": "ShieldIconTilt", + "persistentUuid": "574cae72-91bf-42e6-9c47-8995b6bddb4d", + "type": "number", + "value": -45 + }, + { + "name": "ShieldIconZ", + "persistentUuid": "7e183e7d-44d1-495a-b0bd-b9edf77eaa6f", + "type": "number", + "value": 110 + }, + { + "name": "SpawnSeconds", + "persistentUuid": "4c436709-be31-4a03-9089-9765662831af", + "type": "number", + "value": 7 + }, + { + "name": "TurboFactor", + "persistentUuid": "3a527f40-b744-489b-a034-4853b624eb2d", + "type": "number", + "value": 1.4 + }, + { + "name": "TurboMaxSpeed", + "persistentUuid": "fc51d0c6-c108-4bc9-94f3-cda995e760f1", + "type": "number", + "value": 1600 + }, + { + "name": "TurboSecondsLeft", + "persistentUuid": "63b60a7b-155a-4a1f-9ad2-0bd71de6945f", + "type": "number", + "value": 0 + } + ] + }, + { + "name": "Commentator", + "persistentUuid": "872a276b-136e-49c3-a9c9-f4bfb38fe351", + "type": "structure", + "children": [ + { + "name": "BouncesSinceHit", + "persistentUuid": "208a05a2-b0ef-4cdc-9f8e-2e62a9495db1", + "type": "number", + "value": 0 + }, + { + "name": "Channel", + "persistentUuid": "9f2c4053-0a59-4893-a78e-2c69c4230d1b", + "type": "number", + "value": 4 + }, + { + "name": "EffortTouches", + "persistentUuid": "8327e132-014d-4a71-9c0b-639494c94401", + "type": "number", + "value": 3 + }, + { + "name": "HitChance", + "persistentUuid": "19bd3bf4-c577-4c60-ac50-cde1d52cbb6f", + "type": "number", + "value": 0.35 + }, + { + "name": "HitCooldown", + "persistentUuid": "ddb401e6-20a1-4c58-957c-6adb813a4698", + "type": "number", + "value": 0 + }, + { + "name": "HitCooldownSeconds", + "persistentUuid": "3701fdad-9fc4-4a77-831d-521fc046096e", + "type": "number", + "value": 6 + }, + { + "name": "IdleLineSeconds", + "persistentUuid": "fa561de2-9425-46eb-8de9-7ce52d16c652", + "type": "number", + "value": 2 + }, + { + "name": "IdleRepeatSeconds", + "persistentUuid": "0331aa79-9c0f-44c2-b3ab-be63bfe0b80e", + "type": "number", + "value": 10 + }, + { + "name": "IdleSeconds", + "persistentUuid": "de6900dd-1bb0-4855-9935-edae40c88f62", + "type": "number", + "value": 0 + }, + { + "name": "IdleSpeed", + "persistentUuid": "ee364d5e-fea6-4db4-a705-afa091f01282", + "type": "number", + "value": 40 + }, + { + "name": "Language", + "persistentUuid": "07865508-0e8e-4b0f-a1cf-8ba5d7642b01", + "type": "string", + "value": "" + }, + { + "name": "LastVelocityX", + "persistentUuid": "1f29a6b2-afeb-4c55-93e9-540bd30c7e72", + "type": "number", + "value": 0 + }, + { + "name": "Lines", + "persistentUuid": "d9ee6248-4a76-4db0-a8ed-00373b55967b", + "type": "structure", + "children": [ + { + "name": "Hit", + "persistentUuid": "56832b15-2e0b-4d4b-8c34-d9e927018925", + "type": "array", + "children": [ + { + "persistentUuid": "23d1b99d-f308-4ef7-940d-3adbae09c85a", + "type": "string", + "value": "07_nice" + }, + { + "persistentUuid": "a309d016-116d-4d6e-b280-a6faa1c43c4f", + "type": "string", + "value": "17_yeahh" + } + ] + }, + { + "name": "Idle", + "persistentUuid": "d7dbcda4-abd5-415a-893b-3c964cf9b1b6", + "type": "array", + "children": [ + { + "persistentUuid": "d8002497-22af-4dba-ac2d-d76b04f9254a", + "type": "string", + "value": "03_go_go_go" + }, + { + "persistentUuid": "7d63a303-2d19-402d-b9c8-3f314e795438", + "type": "string", + "value": "05_here_we_go_again" + }, + { + "persistentUuid": "ab696409-cf92-4782-8797-ad73ebf64be1", + "type": "string", + "value": "06_lets_gooo" + } + ] + }, + { + "name": "NearMiss", + "persistentUuid": "a4b79d50-0856-41c3-a9e9-e3a4671e816d", + "type": "array", + "children": [ + { + "persistentUuid": "0a0cb377-aae7-42f9-9488-5c59dfc22ae9", + "type": "string", + "value": "15_thats_terrible" + } + ] + }, + { + "name": "OpponentNearMiss", + "persistentUuid": "cac04018-5f5c-4ccb-b06b-ed16e251020c", + "type": "array", + "children": [ + { + "persistentUuid": "3901f0c6-d9eb-4b18-b965-be06c60b39bc", + "type": "string", + "value": "09_nooo" + }, + { + "persistentUuid": "4987093d-a94d-42c7-80a4-67c3f3e52330", + "type": "string", + "value": "18_yikes" + } + ] + }, + { + "name": "OwnGoal", + "persistentUuid": "8d048b49-6e0e-458a-a376-78e08a2d3cde", + "type": "array", + "children": [ + { + "persistentUuid": "105a0b02-8d16-4d25-a8a2-8ab2b8a63ce8", + "type": "string", + "value": "15_thats_terrible" + }, + { + "persistentUuid": "db02322a-10d1-4055-baf9-f334cfc55325", + "type": "string", + "value": "16_what_was_the_plan" + }, + { + "persistentUuid": "43edcc14-0ee3-41fd-87a9-501e33a167b7", + "type": "string", + "value": "12_oh_noo" + } + ] + }, + { + "name": "PlayerGoal", + "persistentUuid": "813b08cc-10d0-4257-8504-423b1b111375", + "type": "array", + "children": [ + { + "persistentUuid": "e563db94-f3a1-4a5d-8a07-8ca23cd9cb3a", + "type": "string", + "value": "02_goooooal" + }, + { + "persistentUuid": "226a23a8-aa0c-44b1-a496-d7f6bc7315eb", + "type": "string", + "value": "06_lets_gooo" + } + ] + }, + { + "name": "StrongHit", + "persistentUuid": "d4d44ba9-6f69-46d5-bacf-8548f7c2da60", + "type": "array", + "children": [ + { + "persistentUuid": "8665415a-08c5-447b-8e22-26770cd9f684", + "type": "string", + "value": "04_great" + }, + { + "persistentUuid": "511ef8c4-afdd-436f-8bfd-738b49940eba", + "type": "string", + "value": "14_thats_great" + } + ] + } + ] + }, + { + "name": "NearMissArmed", + "persistentUuid": "85c1eb2b-eec7-4ed8-9bfb-a1276bbb5d15", + "type": "boolean", + "value": true + }, + { + "name": "NearMissMinSpeed", + "persistentUuid": "7be65a6f-8e30-4c33-80b4-e3497725a9dc", + "type": "number", + "value": 450 + }, + { + "name": "NearMissPostWidth", + "persistentUuid": "84f945ed-3c89-41e5-a98f-38c768c30cf4", + "type": "number", + "value": 70 + }, + { + "name": "NewHitBy", + "persistentUuid": "240ef3fa-5b7a-413e-8e0c-75dbfd2c6e0c", + "type": "string", + "value": "" + }, + { + "name": "NewHitSpeed", + "persistentUuid": "d38fce07-bcf2-4167-abb9-5d5a55fc5b23", + "type": "number", + "value": 0 + }, + { + "name": "PendingLine", + "persistentUuid": "c542dfa9-9507-4875-aaf9-f9d4fbb4df9e", + "type": "string", + "value": "" + }, + { + "name": "PendingTimeLeft", + "persistentUuid": "deeb4aa3-341a-47c5-bd9b-76a525095965", + "type": "number", + "value": 0 + }, + { + "name": "PlayerTouchesInRally", + "persistentUuid": "e6a641ab-e4cd-498c-9527-5d06f932fbe5", + "type": "number", + "value": 0 + }, + { + "name": "SaveZoneHeight", + "persistentUuid": "fd61de03-3032-4f0d-9bc8-d64910608fb2", + "type": "number", + "value": 180 + }, + { + "name": "StrongHitSpeed", + "persistentUuid": "1a0d5616-8231-4b7f-8968-6e5f4573d779", + "type": "number", + "value": 900 + }, + { + "name": "Volume", + "persistentUuid": "f85aedec-32a0-4ea9-955d-fe1782077fe8", + "type": "number", + "value": 100 + } + ] + }, + { + "name": "PointerLock", + "persistentUuid": "395b541a-f19e-4a51-b247-f77254dcc40e", + "type": "structure", + "children": [ + { + "name": "Speed", + "persistentUuid": "bf60b2f7-cb10-42d8-aa58-aa666fffce64", + "type": "number", + "value": 1.25 + }, + { + "name": "U", + "persistentUuid": "faccc3e1-da37-480d-8c26-6bdb72593029", + "type": "number", + "value": 0.5 + }, + { + "name": "V", + "persistentUuid": "55abfd0a-aaa6-450b-9e74-210579f9a200", + "type": "number", + "value": 0.5 + }, + { + "name": "WasLocked", + "persistentUuid": "8330f194-55cf-435d-ab01-fd02fdd9c33d", + "type": "boolean", + "value": false + } + ] + } + ], + "instances": [ + { + "angle": 0, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "Background", + "name": "StadiumBackground", + "persistentUuid": "e9da3ef3-02a3-4089-bd24-441fb7b468e0", + "width": 0, + "x": 0, + "y": 0, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "", + "name": "Table", + "persistentUuid": "59e2a992-7afb-47b7-8b55-9cb9fd8defc2", + "width": 0, + "x": 960, + "y": 540, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "", + "name": "Goal", + "persistentUuid": "7162a4d5-98b5-4af1-92b3-f9db67aa7106", + "width": 0, + "x": 960, + "y": 40, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 180, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "", + "name": "Goal", + "persistentUuid": "8db3693b-3cd3-49f8-8484-396010d4518f", + "width": 0, + "x": 960, + "y": 1040, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "hidden": true, + "keepRatio": true, + "layer": "Collisions", + "name": "MalletPlayer", + "persistentUuid": "5d5775fe-dcfe-49b4-b3cd-0765d5c05b79", + "width": 0, + "x": 960, + "y": 900, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "hidden": true, + "keepRatio": true, + "layer": "Collisions", + "name": "MalletOpponent", + "persistentUuid": "9b04e21f-af84-4430-9c3c-62197c2e6f7d", + "width": 0, + "x": 960, + "y": 180, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "", + "name": "Puck", + "persistentUuid": "2800c6e3-29dd-4572-a4d9-3abe5d13f085", + "width": 0, + "x": 960, + "y": 540, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 1600, + "hidden": true, + "keepRatio": true, + "layer": "Collisions", + "name": "Wall", + "persistentUuid": "0dbf8609-d904-4a06-8252-eb1268ebc58b", + "width": 200, + "x": 460, + "y": -260, + "z": -100, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 1600, + "hidden": true, + "keepRatio": true, + "layer": "Collisions", + "name": "Wall", + "persistentUuid": "a90cc9fd-4afb-4644-b7da-b25c105d35e7", + "width": 200, + "x": 1260, + "y": -260, + "z": -100, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 200, + "hidden": true, + "keepRatio": true, + "layer": "Collisions", + "name": "Wall", + "persistentUuid": "f7f4d34a-dd8b-4d97-bbea-45ff17f5c07f", + "width": 396, + "x": 460, + "y": -160, + "z": -100, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 200, + "hidden": true, + "keepRatio": true, + "layer": "Collisions", + "name": "Wall", + "persistentUuid": "8bbe9ce7-7ac2-4011-8114-586b250760b8", + "width": 396, + "x": 1064, + "y": -160, + "z": -100, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 200, + "hidden": true, + "keepRatio": true, + "layer": "Collisions", + "name": "Wall", + "persistentUuid": "a556f2fc-a848-47c5-8509-d7b377848fe0", + "width": 396, + "x": 460, + "y": 1040, + "z": -100, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 200, + "hidden": true, + "keepRatio": true, + "layer": "Collisions", + "name": "Wall", + "persistentUuid": "87258883-6216-4478-8ed8-70e6dcfae3bc", + "width": 396, + "x": 1064, + "y": 1040, + "z": -100, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 200, + "hidden": true, + "keepRatio": true, + "layer": "Collisions", + "name": "Wall", + "persistentUuid": "6301708b-ed43-4999-a373-2e17e1b51edd", + "width": 268, + "x": 826, + "y": -360, + "z": -100, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 200, + "hidden": true, + "keepRatio": true, + "layer": "Collisions", + "name": "Wall", + "persistentUuid": "d4dce90b-a734-46e6-9892-3c22e8f1252c", + "width": 268, + "x": 826, + "y": 1240, + "z": -100, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "", + "name": "Stadium", + "persistentUuid": "e910ebae-4efc-4d37-898a-d36970c678e2", + "width": 0, + "x": 960, + "y": 567, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 1000, + "hidden": true, + "keepRatio": true, + "layer": "Collisions", + "name": "PuckFloor", + "persistentUuid": "5e9487aa-02f7-4bf7-af12-7b1914a57714", + "width": 600, + "x": 660, + "y": 40, + "z": -100, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 1000, + "hidden": true, + "keepRatio": true, + "layer": "Collisions", + "name": "PuckCeiling", + "persistentUuid": "f51a71ec-3cac-41e3-b1c5-d9370a869188", + "width": 600, + "x": 660, + "y": 40, + "z": 16, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "HUD", + "name": "UI_Scoreboard", + "persistentUuid": "5c0e62ef-c02e-48a1-b28d-31a3faddeab7", + "width": 0, + "x": 510, + "y": 20, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "HUD", + "name": "UI_Announcement", + "persistentUuid": "b70d539f-d6c7-47c9-a0d4-38a0ec040fb0", + "width": 0, + "x": 360, + "y": 420, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "ResultMenu", + "name": "UI_ResultMenu", + "persistentUuid": "39ed8d3e-5a9a-423b-892a-74ea236e7ed2", + "width": 0, + "x": 610, + "y": 310, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 45, + "customSize": true, + "height": 120, + "hidden": true, + "keepRatio": true, + "layer": "Collisions", + "name": "Wall", + "persistentUuid": "d072b8d8-816c-4a52-b71c-00bb177eca6c", + "width": 120, + "x": 600, + "y": -20, + "z": -100, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 45, + "customSize": true, + "height": 120, + "hidden": true, + "keepRatio": true, + "layer": "Collisions", + "name": "Wall", + "persistentUuid": "1245b21e-c659-4330-ac44-db83bcd48772", + "width": 120, + "x": 1200, + "y": -20, + "z": -100, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 45, + "customSize": true, + "height": 120, + "hidden": true, + "keepRatio": true, + "layer": "Collisions", + "name": "Wall", + "persistentUuid": "98c3030f-6fbb-46d9-8453-9d4e3d35df7c", + "width": 120, + "x": 600, + "y": 980, + "z": -100, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 45, + "customSize": true, + "height": 120, + "hidden": true, + "keepRatio": true, + "layer": "Collisions", + "name": "Wall", + "persistentUuid": "b09259a4-6c27-46dd-9de9-f95408fad52c", + "width": 120, + "x": 1200, + "y": 980, + "z": -100, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 36, + "hidden": true, + "keepRatio": true, + "layer": "Collisions", + "name": "Wall", + "persistentUuid": "65ecc442-7ac0-41d2-899c-c9443590e700", + "width": 228, + "x": 846, + "y": -82, + "z": -100, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 36, + "hidden": true, + "keepRatio": true, + "layer": "Collisions", + "name": "Wall", + "persistentUuid": "f0f4549a-d791-45d9-b671-32f5246471e8", + "width": 228, + "x": 846, + "y": 1126, + "z": -100, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "hidden": true, + "keepRatio": true, + "layer": "", + "name": "Camera", + "persistentUuid": "e6c42883-ad16-4908-8308-69b536b6fbfb", + "rotationX": 46, + "width": 0, + "x": 960, + "y": 1534, + "z": 880, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "Modal", + "name": "UI_OptionsModal", + "persistentUuid": "00be8368-30cd-4f51-8798-6070b397e86b", + "width": 0, + "x": 0, + "y": 0, + "zOrder": 10, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 120, + "keepRatio": true, + "layer": "HUD", + "name": "OptionsButton", + "persistentUuid": "eff501b4-e491-4f3b-9724-c98571dc2b93", + "width": 120, + "x": 1770, + "y": 30, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 180, + "customSize": false, + "height": 0, + "hidden": true, + "keepRatio": true, + "layer": "", + "name": "FlagFrance", + "persistentUuid": "90b730f7-fe30-4027-8eae-3bc51072fa71", + "width": 0, + "x": 422, + "y": 120, + "z": -104, + "zOrder": 11, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 180, + "customSize": false, + "height": 0, + "hidden": true, + "keepRatio": true, + "layer": "", + "name": "FlagFrance", + "persistentUuid": "4455baa2-114c-478c-9899-846996aefdcf", + "width": 0, + "x": 422, + "y": 380, + "z": -104, + "zOrder": 11, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 180, + "customSize": false, + "height": 0, + "hidden": true, + "keepRatio": true, + "layer": "", + "name": "FlagFrance", + "persistentUuid": "1ff3f0be-ec8a-477a-b552-6cb393206994", + "width": 0, + "x": 1496, + "y": 120, + "z": -118, + "zOrder": 11, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 180, + "customSize": false, + "height": 0, + "hidden": true, + "keepRatio": true, + "layer": "", + "name": "FlagFrance", + "persistentUuid": "96aea54a-0b86-4dc8-a9a0-7c64b60a569c", + "width": 0, + "x": 1496, + "y": 380, + "z": -118, + "zOrder": 11, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "hidden": true, + "keepRatio": true, + "layer": "", + "name": "MalletFrance", + "persistentUuid": "6c4164fa-ed35-4d59-a7a1-12aa2635e379", + "width": 0, + "x": 960, + "y": 180, + "zOrder": 14, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 180, + "customSize": false, + "height": 0, + "hidden": true, + "keepRatio": true, + "layer": "", + "name": "FlagCanada", + "persistentUuid": "1df8b777-4d87-4cc6-9893-831093ff9af4", + "width": 0, + "x": 422, + "y": 700, + "z": -104, + "zOrder": 15, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 180, + "customSize": false, + "height": 0, + "hidden": true, + "keepRatio": true, + "layer": "", + "name": "FlagCanada", + "persistentUuid": "753bbafd-89ad-46af-931b-c49d4a6dfe68", + "width": 0, + "x": 422, + "y": 960, + "z": -104, + "zOrder": 15, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 180, + "customSize": false, + "height": 0, + "hidden": true, + "keepRatio": true, + "layer": "", + "name": "FlagCanada", + "persistentUuid": "752f76f6-d59f-4c80-a543-d76b7a8a291c", + "width": 0, + "x": 1496, + "y": 700, + "z": -118, + "zOrder": 15, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 180, + "customSize": false, + "height": 0, + "hidden": true, + "keepRatio": true, + "layer": "", + "name": "FlagCanada", + "persistentUuid": "c3cc28e1-cb24-492c-931c-0ab3ce341c39", + "width": 0, + "x": 1496, + "y": 960, + "z": -118, + "zOrder": 15, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "hidden": true, + "keepRatio": true, + "layer": "", + "name": "MalletCanada", + "persistentUuid": "cf0c9f4c-58d3-438d-9c69-0cadbe7b70ed", + "width": 0, + "x": 960, + "y": 900, + "zOrder": 16, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + } + ], + "objects": [ + { + "assetStoreId": "", + "name": "Table", + "persistentUuid": "02628ef0-e60b-4524-afc0-93e377090253", + "type": "Scene3D::Model3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "centerLocation": "CenteredOnZ", + "crossfadeDuration": 0.10000000149011612, + "depth": 135, + "height": 1200, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "Table.glb", + "originLocation": "ModelOrigin", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 800, + "animations": [] + } + }, + { + "assetStoreId": "", + "name": "Goal", + "persistentUuid": "5f1d6925-b998-41a5-bd2a-11eb554514d5", + "type": "Scene3D::Model3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "centerLocation": "CenteredOnZ", + "crossfadeDuration": 0.10000000149011612, + "depth": 85, + "height": 86.25, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "Goal.glb", + "originLocation": "ModelOrigin", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 218.5, + "animations": [] + } + }, + { + "assetStoreId": "", + "name": "MalletPlayer", + "persistentUuid": "92e11259-5677-473a-a1cb-e94f72c2a753", + "type": "Scene3D::Model3DObject", + "variables": [ + { + "name": "IsTouchingPuck", + "persistentUuid": "a6abfd36-487a-41fa-ae01-2ba7e29dba07", + "type": "boolean", + "value": false + }, + { + "name": "Radius", + "type": "number", + "value": 55 + }, + { + "name": "Effects", + "type": "structure", + "children": [ + { + "name": "BigSeconds", + "type": "number", + "value": 0 + }, + { + "name": "FrozenSeconds", + "type": "number", + "value": 0 + } + ] + } + ], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Kinematic", + "bullet": true, + "fixedRotation": false, + "shape": "Cylinder", + "meshShapeResourceName": "", + "shapeOrientation": "Z", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 1, + "friction": 0, + "restitution": 0.2, + "linearDamping": 0.1, + "angularDamping": 0.1, + "gravityScale": 0, + "layers": 4, + "masks": 4 + } + ], + "content": { + "centerLocation": "CenteredOnZ", + "crossfadeDuration": 0.10000000149011612, + "depth": 85, + "height": 110, + "isCastingShadow": false, + "isReceivingShadow": false, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "MalletBody.glb", + "originLocation": "ModelOrigin", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 110, + "animations": [] + } + }, + { + "assetStoreId": "", + "name": "MalletOpponent", + "type": "Scene3D::Model3DObject", + "variables": [ + { + "name": "State", + "type": "string", + "value": "Idle" + }, + { + "name": "AimErrorX", + "type": "number", + "value": 0 + }, + { + "name": "AimErrorCooldown", + "type": "number", + "value": 0 + }, + { + "name": "TrackedPuckX", + "type": "number", + "value": 960 + }, + { + "name": "CurrentMaxSpeed", + "type": "number", + "value": 420 + }, + { + "name": "ReactionDelay", + "type": "number", + "value": 0 + }, + { + "name": "SpeedFactor", + "type": "number", + "value": 1 + }, + { + "name": "StrikePlanned", + "type": "boolean", + "value": false + }, + { + "name": "StrikeTimeLeft", + "type": "number", + "value": 0 + }, + { + "name": "IsTouchingPuck", + "persistentUuid": "cf5b4991-3f2d-4ac7-84ad-e031f1d99f95", + "type": "boolean", + "value": false + }, + { + "name": "Radius", + "type": "number", + "value": 55 + }, + { + "name": "Effects", + "type": "structure", + "children": [ + { + "name": "BigSeconds", + "type": "number", + "value": 0 + }, + { + "name": "FrozenSeconds", + "type": "number", + "value": 0 + } + ] + }, + { + "name": "StillSeconds", + "type": "number", + "value": 0 + }, + { + "name": "UnstickTimeLeft", + "type": "number", + "value": 0 + }, + { + "name": "AnchorX", + "type": "number", + "value": 0 + }, + { + "name": "AnchorY", + "type": "number", + "value": 0 + } + ], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Kinematic", + "bullet": true, + "fixedRotation": false, + "shape": "Cylinder", + "meshShapeResourceName": "", + "shapeOrientation": "Z", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 1, + "friction": 0, + "restitution": 0.2, + "linearDamping": 0.1, + "angularDamping": 0.1, + "gravityScale": 0, + "layers": 4, + "masks": 4 + } + ], + "content": { + "centerLocation": "CenteredOnZ", + "crossfadeDuration": 0.10000000149011612, + "depth": 85, + "height": 110, + "isCastingShadow": false, + "isReceivingShadow": false, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "MalletBody.glb", + "originLocation": "ModelOrigin", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 110, + "animations": [] + } + }, + { + "assetStoreId": "", + "name": "Puck", + "persistentUuid": "80f84dea-9d82-42de-98a6-aa475329c02e", + "type": "Scene3D::Model3DObject", + "variables": [ + { + "name": "TrailLastX", + "type": "number", + "value": 960 + }, + { + "name": "TrailLastY", + "type": "number", + "value": 540 + }, + { + "name": "StillSeconds", + "type": "number", + "value": 0 + } + ], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Dynamic", + "bullet": true, + "fixedRotation": true, + "shape": "Cylinder", + "meshShapeResourceName": "", + "shapeOrientation": "Z", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 1, + "friction": 0, + "restitution": 0.7, + "linearDamping": 0.8, + "angularDamping": 0.1, + "gravityScale": 0, + "layers": 19, + "masks": 19 + } + ], + "content": { + "centerLocation": "CenteredOnZ", + "crossfadeDuration": 0.10000000149011612, + "depth": 14, + "height": 66, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "Puck.glb", + "originLocation": "ModelOrigin", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 66, + "animations": [] + } + }, + { + "assetStoreId": "", + "name": "Wall", + "persistentUuid": "7ac24f40-ede7-4dd5-ad77-23c45fedfc12", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Static", + "bullet": false, + "fixedRotation": false, + "shape": "Box", + "meshShapeResourceName": "", + "shapeOrientation": "Z", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 1, + "friction": 0, + "restitution": 0.9, + "linearDamping": 0.1, + "angularDamping": 0.1, + "gravityScale": 1, + "layers": 17, + "masks": 17 + } + ], + "content": { + "width": 100, + "height": 100, + "depth": 300, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "frontFaceResourceName": "", + "backFaceResourceName": "", + "backFaceUpThroughWhichAxisRotation": "X", + "leftFaceResourceName": "", + "rightFaceResourceName": "", + "topFaceResourceName": "", + "bottomFaceResourceName": "", + "frontFaceVisible": false, + "backFaceVisible": false, + "leftFaceVisible": false, + "rightFaceVisible": false, + "topFaceVisible": false, + "bottomFaceVisible": false, + "frontFaceResourceRepeat": false, + "backFaceResourceRepeat": false, + "leftFaceResourceRepeat": false, + "rightFaceResourceRepeat": false, + "topFaceResourceRepeat": false, + "bottomFaceResourceRepeat": false, + "tileScale": 1, + "materialType": "StandardWithoutMetalness", + "tint": "255;255;255", + "isCastingShadow": false, + "isReceivingShadow": false + } + }, + { + "adaptCollisionMaskAutomatically": true, + "assetStoreId": "", + "name": "StadiumBackground", + "persistentUuid": "5d9dcbf2-cc36-41bd-aeff-1bfb87f96ad6", + "type": "Sprite", + "updateIfNotVisible": false, + "variables": [], + "effects": [], + "behaviors": [], + "animations": [ + { + "name": "Idle", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "StadiumSky.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + } + ] + }, + { + "assetStoreId": "", + "name": "Stadium", + "persistentUuid": "caeb8b42-6db0-47b0-8c54-3997b014c91d", + "type": "Scene3D::Model3DObject", + "variables": [ + { + "name": "State", + "persistentUuid": "3fd66ed9-bba2-42ac-a77d-aaac7bf5f4cc", + "type": "string", + "value": "Cheer" + }, + { + "name": "WaveCheckCooldown", + "persistentUuid": "def1b0a9-b5b7-44ed-9240-f4e676e5ba02", + "type": "number", + "value": 8 + } + ], + "effects": [], + "behaviors": [], + "content": { + "centerLocation": "CenteredOnZ", + "crossfadeDuration": 0.10000000149011612, + "depth": 774, + "height": 8000, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "KeepOriginal", + "modelResourceName": "Stadium.glb", + "originLocation": "ModelOrigin", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 8000, + "animations": [ + { + "loop": true, + "name": "Cheer", + "source": "Cheer" + }, + { + "loop": false, + "name": "Wave", + "source": "Wave" + } + ] + } + }, + { + "assetStoreId": "", + "name": "PuckFloor", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Static", + "bullet": false, + "fixedRotation": false, + "shape": "Box", + "meshShapeResourceName": "", + "shapeOrientation": "Z", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 1, + "friction": 0, + "restitution": 0, + "linearDamping": 0.1, + "angularDamping": 0.1, + "gravityScale": 1, + "layers": 17, + "masks": 17 + } + ], + "content": { + "width": 100, + "height": 100, + "depth": 100, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "frontFaceResourceName": "", + "backFaceResourceName": "", + "backFaceUpThroughWhichAxisRotation": "X", + "leftFaceResourceName": "", + "rightFaceResourceName": "", + "topFaceResourceName": "", + "bottomFaceResourceName": "", + "frontFaceVisible": false, + "backFaceVisible": false, + "leftFaceVisible": false, + "rightFaceVisible": false, + "topFaceVisible": false, + "bottomFaceVisible": false, + "frontFaceResourceRepeat": false, + "backFaceResourceRepeat": false, + "leftFaceResourceRepeat": false, + "rightFaceResourceRepeat": false, + "topFaceResourceRepeat": false, + "bottomFaceResourceRepeat": false, + "tileScale": 1, + "materialType": "StandardWithoutMetalness", + "tint": "255;255;255", + "isCastingShadow": false, + "isReceivingShadow": false + } + }, + { + "assetStoreId": "", + "name": "PuckCeiling", + "persistentUuid": "7e743b4f-927f-4272-8632-d137bfddb342", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Static", + "bullet": false, + "fixedRotation": false, + "shape": "Box", + "meshShapeResourceName": "", + "shapeOrientation": "Z", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 1, + "friction": 0, + "restitution": 0, + "linearDamping": 0.1, + "angularDamping": 0.1, + "gravityScale": 1, + "layers": 2, + "masks": 2 + } + ], + "content": { + "width": 100, + "height": 100, + "depth": 100, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "frontFaceResourceName": "", + "backFaceResourceName": "", + "backFaceUpThroughWhichAxisRotation": "X", + "leftFaceResourceName": "", + "rightFaceResourceName": "", + "topFaceResourceName": "", + "bottomFaceResourceName": "", + "frontFaceVisible": false, + "backFaceVisible": false, + "leftFaceVisible": false, + "rightFaceVisible": false, + "topFaceVisible": false, + "bottomFaceVisible": false, + "frontFaceResourceRepeat": false, + "backFaceResourceRepeat": false, + "leftFaceResourceRepeat": false, + "rightFaceResourceRepeat": false, + "topFaceResourceRepeat": false, + "bottomFaceResourceRepeat": false, + "tileScale": 1, + "materialType": "StandardWithoutMetalness", + "tint": "255;255;255", + "isCastingShadow": false, + "isReceivingShadow": false + } + }, + { + "assetStoreId": "", + "name": "UI_Scoreboard", + "type": "AirHockeyUI::UI_Scoreboard", + "variant": "", + "variables": [], + "effects": [], + "behaviors": [], + "content": {} + }, + { + "assetStoreId": "", + "name": "UI_Announcement", + "type": "AirHockeyUI::UI_Announcement", + "variant": "", + "variables": [], + "effects": [], + "behaviors": [], + "content": {} + }, + { + "assetStoreId": "", + "name": "UI_ResultMenu", + "type": "AirHockeyUI::UI_ResultMenu", + "variant": "", + "variables": [], + "effects": [], + "behaviors": [], + "content": {} + }, + { + "assetStoreId": "", + "name": "Confetti", + "type": "ParticleEmitter3D::ParticleEmitter3D", + "variant": "", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "ShouldAutodestruct": true, + "AreParticlesRelative": false, + "GravityTop": "Z+", + "Gravity": 260, + "ZoneRadius": 0, + "EndScale": 1, + "RenderMode": "Billboard", + "Blending": "Normal", + "StartColor": "255;255;255", + "EndColor": "255;255;255", + "StartOpacity": 255, + "EndOpacity": 255, + "StartSizeMin": 45, + "StartSizeMax": 75, + "Flow": 2400, + "Duration": 0.05, + "LifespanMin": 2.2, + "LifespanMax": 3, + "StartSpeedMin": 350, + "StartSpeedMax": 650, + "SpayConeAngle": 35 + }, + "childrenContent": { + "Particle": { + "adaptCollisionMaskAutomatically": true, + "updateIfNotVisible": false, + "animations": [ + { + "name": "Image", + "useMultipleDirections": false, + "directions": [ + { + "looping": false, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": false, + "image": "Confetti.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + } + ] + } + } + }, + { + "assetStoreId": "", + "name": "PuckTrail", + "type": "Scene3D::Cube3DObject", + "variables": [ + { + "name": "Life", + "type": "number", + "value": 1 + }, + { + "name": "CenterX", + "type": "number", + "value": 0 + }, + { + "name": "CenterY", + "type": "number", + "value": 0 + } + ], + "effects": [], + "behaviors": [], + "content": { + "width": 100, + "height": 34, + "depth": 1, + "enableTextureTransparency": true, + "facesOrientation": "Y", + "frontFaceResourceName": "PuckTrail.png", + "backFaceResourceName": "PuckTrail.png", + "backFaceUpThroughWhichAxisRotation": "X", + "leftFaceResourceName": "PuckTrail.png", + "rightFaceResourceName": "PuckTrail.png", + "topFaceResourceName": "PuckTrail.png", + "bottomFaceResourceName": "PuckTrail.png", + "frontFaceVisible": true, + "backFaceVisible": false, + "leftFaceVisible": false, + "rightFaceVisible": false, + "topFaceVisible": false, + "bottomFaceVisible": false, + "frontFaceResourceRepeat": false, + "backFaceResourceRepeat": false, + "leftFaceResourceRepeat": false, + "rightFaceResourceRepeat": false, + "topFaceResourceRepeat": false, + "bottomFaceResourceRepeat": false, + "tileScale": 1, + "materialType": "Basic", + "tint": "255;255;255", + "isCastingShadow": false, + "isReceivingShadow": false + } + }, + { + "assetStoreId": "cce2941e93b9aaa172fb28726d2383ac1aff1121957d3adcce1ab0122211d5ff", + "name": "Camera", + "persistentUuid": "071af5fe-67b4-4a87-878b-e1c96241da64", + "type": "Scene3D::Model3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "centerLocation": "CenteredOnZ", + "crossfadeDuration": 0.10000000149011612, + "depth": 44, + "height": 44, + "isCastingShadow": false, + "isReceivingShadow": false, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "Camera.glb", + "originLocation": "ModelOrigin", + "rotationX": 0, + "rotationY": 0, + "rotationZ": 90, + "width": 44, + "animations": [] + } + }, + { + "assetStoreId": "", + "name": "PowerUpBigMallet", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 110, + "height": 110, + "depth": 4, + "enableTextureTransparency": true, + "facesOrientation": "Y", + "frontFaceResourceName": "PowerUpBigMallet.png", + "backFaceResourceName": "PuckTrail.png", + "backFaceUpThroughWhichAxisRotation": "X", + "leftFaceResourceName": "PuckTrail.png", + "rightFaceResourceName": "PuckTrail.png", + "topFaceResourceName": "PuckTrail.png", + "bottomFaceResourceName": "PuckTrail.png", + "frontFaceVisible": true, + "backFaceVisible": false, + "leftFaceVisible": false, + "rightFaceVisible": false, + "topFaceVisible": false, + "bottomFaceVisible": false, + "frontFaceResourceRepeat": false, + "backFaceResourceRepeat": false, + "leftFaceResourceRepeat": false, + "rightFaceResourceRepeat": false, + "topFaceResourceRepeat": false, + "bottomFaceResourceRepeat": false, + "tileScale": 1, + "materialType": "Basic", + "tint": "255;255;255", + "isCastingShadow": false, + "isReceivingShadow": false + } + }, + { + "assetStoreId": "", + "name": "PowerUpFreeze", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 110, + "height": 110, + "depth": 4, + "enableTextureTransparency": true, + "facesOrientation": "Y", + "frontFaceResourceName": "PowerUpFreeze.png", + "backFaceResourceName": "PuckTrail.png", + "backFaceUpThroughWhichAxisRotation": "X", + "leftFaceResourceName": "PuckTrail.png", + "rightFaceResourceName": "PuckTrail.png", + "topFaceResourceName": "PuckTrail.png", + "bottomFaceResourceName": "PuckTrail.png", + "frontFaceVisible": true, + "backFaceVisible": false, + "leftFaceVisible": false, + "rightFaceVisible": false, + "topFaceVisible": false, + "bottomFaceVisible": false, + "frontFaceResourceRepeat": false, + "backFaceResourceRepeat": false, + "leftFaceResourceRepeat": false, + "rightFaceResourceRepeat": false, + "topFaceResourceRepeat": false, + "bottomFaceResourceRepeat": false, + "tileScale": 1, + "materialType": "Basic", + "tint": "255;255;255", + "isCastingShadow": false, + "isReceivingShadow": false + } + }, + { + "assetStoreId": "", + "name": "PowerUpTurbo", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 110, + "height": 110, + "depth": 4, + "enableTextureTransparency": true, + "facesOrientation": "Y", + "frontFaceResourceName": "PowerUpTurbo.png", + "backFaceResourceName": "PuckTrail.png", + "backFaceUpThroughWhichAxisRotation": "X", + "leftFaceResourceName": "PuckTrail.png", + "rightFaceResourceName": "PuckTrail.png", + "topFaceResourceName": "PuckTrail.png", + "bottomFaceResourceName": "PuckTrail.png", + "frontFaceVisible": true, + "backFaceVisible": false, + "leftFaceVisible": false, + "rightFaceVisible": false, + "topFaceVisible": false, + "bottomFaceVisible": false, + "frontFaceResourceRepeat": false, + "backFaceResourceRepeat": false, + "leftFaceResourceRepeat": false, + "rightFaceResourceRepeat": false, + "topFaceResourceRepeat": false, + "bottomFaceResourceRepeat": false, + "tileScale": 1, + "materialType": "Basic", + "tint": "255;255;255", + "isCastingShadow": false, + "isReceivingShadow": false + } + }, + { + "assetStoreId": "", + "name": "PowerUpShield", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 110, + "height": 110, + "depth": 4, + "enableTextureTransparency": true, + "facesOrientation": "Y", + "frontFaceResourceName": "PowerUpShield.png", + "backFaceResourceName": "PuckTrail.png", + "backFaceUpThroughWhichAxisRotation": "X", + "leftFaceResourceName": "PuckTrail.png", + "rightFaceResourceName": "PuckTrail.png", + "topFaceResourceName": "PuckTrail.png", + "bottomFaceResourceName": "PuckTrail.png", + "frontFaceVisible": true, + "backFaceVisible": false, + "leftFaceVisible": false, + "rightFaceVisible": false, + "topFaceVisible": false, + "bottomFaceVisible": false, + "frontFaceResourceRepeat": false, + "backFaceResourceRepeat": false, + "leftFaceResourceRepeat": false, + "rightFaceResourceRepeat": false, + "topFaceResourceRepeat": false, + "bottomFaceResourceRepeat": false, + "tileScale": 1, + "materialType": "Basic", + "tint": "255;255;255", + "isCastingShadow": false, + "isReceivingShadow": false + } + }, + { + "assetStoreId": "", + "name": "GoalShield", + "type": "Scene3D::Cube3DObject", + "variables": [ + { + "name": "Owner", + "type": "string", + "value": "MalletPlayer" + } + ], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "", + "bodyType": "Static", + "bullet": false, + "fixedRotation": false, + "shape": "Box", + "meshShapeResourceName": "", + "shapeOrientation": "Z", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 1, + "friction": 0, + "restitution": 0.9, + "linearDamping": 0.1, + "angularDamping": 0.1, + "gravityScale": 1, + "layers": 17, + "masks": 17 + } + ], + "content": { + "width": 260, + "height": 24, + "depth": 60, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "frontFaceResourceName": "GoalShieldWall.png", + "backFaceResourceName": "GoalShieldWall.png", + "backFaceUpThroughWhichAxisRotation": "X", + "leftFaceResourceName": "GoalShieldWall.png", + "rightFaceResourceName": "GoalShieldWall.png", + "topFaceResourceName": "GoalShieldWall.png", + "bottomFaceResourceName": "GoalShieldWall.png", + "frontFaceVisible": true, + "backFaceVisible": true, + "leftFaceVisible": true, + "rightFaceVisible": true, + "topFaceVisible": true, + "bottomFaceVisible": true, + "frontFaceResourceRepeat": false, + "backFaceResourceRepeat": false, + "leftFaceResourceRepeat": false, + "rightFaceResourceRepeat": false, + "topFaceResourceRepeat": false, + "bottomFaceResourceRepeat": false, + "tileScale": 1, + "materialType": "StandardWithoutMetalness", + "tint": "255;255;255", + "isCastingShadow": true, + "isReceivingShadow": true + } + }, + { + "assetStoreId": "", + "name": "PowerUpRingSegment", + "type": "Scene3D::Cube3DObject", + "variables": [ + { + "name": "Step", + "type": "number", + "value": 0 + } + ], + "effects": [], + "behaviors": [], + "content": { + "width": 12, + "height": 6, + "depth": 1, + "enableTextureTransparency": true, + "facesOrientation": "Y", + "frontFaceResourceName": "PowerUpRing100.png", + "backFaceResourceName": "PuckTrail.png", + "backFaceUpThroughWhichAxisRotation": "X", + "leftFaceResourceName": "PuckTrail.png", + "rightFaceResourceName": "PuckTrail.png", + "topFaceResourceName": "PuckTrail.png", + "bottomFaceResourceName": "PuckTrail.png", + "frontFaceVisible": true, + "backFaceVisible": false, + "leftFaceVisible": false, + "rightFaceVisible": false, + "topFaceVisible": false, + "bottomFaceVisible": false, + "frontFaceResourceRepeat": false, + "backFaceResourceRepeat": false, + "leftFaceResourceRepeat": false, + "rightFaceResourceRepeat": false, + "topFaceResourceRepeat": false, + "bottomFaceResourceRepeat": false, + "tileScale": 1, + "materialType": "Basic", + "tint": "255;255;255", + "isCastingShadow": false, + "isReceivingShadow": false + } + }, + { + "assetStoreId": "", + "name": "GoalShieldIcon", + "type": "Scene3D::Cube3DObject", + "variables": [ + { + "name": "Owner", + "type": "string", + "value": "MalletPlayer" + } + ], + "effects": [], + "behaviors": [], + "content": { + "width": 110, + "height": 110, + "depth": 1, + "enableTextureTransparency": true, + "facesOrientation": "Y", + "frontFaceResourceName": "PowerUpShield.png", + "backFaceResourceName": "PuckTrail.png", + "backFaceUpThroughWhichAxisRotation": "X", + "leftFaceResourceName": "PuckTrail.png", + "rightFaceResourceName": "PuckTrail.png", + "topFaceResourceName": "PuckTrail.png", + "bottomFaceResourceName": "PuckTrail.png", + "frontFaceVisible": true, + "backFaceVisible": false, + "leftFaceVisible": false, + "rightFaceVisible": false, + "topFaceVisible": false, + "bottomFaceVisible": false, + "frontFaceResourceRepeat": false, + "backFaceResourceRepeat": false, + "leftFaceResourceRepeat": false, + "rightFaceResourceRepeat": false, + "topFaceResourceRepeat": false, + "bottomFaceResourceRepeat": false, + "tileScale": 1, + "materialType": "Basic", + "tint": "255;255;255", + "isCastingShadow": false, + "isReceivingShadow": false + } + }, + { + "assetStoreId": "", + "name": "FlagUSA", + "resourcesPreloading": "manually", + "type": "Scene3D::Model3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "centerLocation": "CenteredOnZ", + "crossfadeDuration": 0.1000000014901161, + "depth": 270, + "height": 25, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "FlagUSA.glb", + "originLocation": "ModelOrigin", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 150, + "animations": [ + { + "loop": true, + "name": "Wave", + "source": "Wave" + } + ] + } + }, + { + "assetStoreId": "", + "name": "MalletUSA", + "resourcesPreloading": "manually", + "type": "Scene3D::Model3DObject", + "variables": [ + { + "name": "IsPlayer", + "type": "boolean", + "value": false + } + ], + "effects": [], + "behaviors": [], + "content": { + "centerLocation": "CenteredOnZ", + "crossfadeDuration": 0.10000000149011612, + "depth": 85, + "height": 110, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "MalletUSA.glb", + "originLocation": "ModelOrigin", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 110, + "animations": [] + } + }, + { + "assetStoreId": "", + "name": "FlagBelgium", + "resourcesPreloading": "manually", + "type": "Scene3D::Model3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "centerLocation": "CenteredOnZ", + "crossfadeDuration": 0.1000000014901161, + "depth": 270, + "height": 25, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "FlagBelgium.glb", + "originLocation": "ModelOrigin", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 150, + "animations": [ + { + "loop": true, + "name": "Wave", + "source": "Wave" + } + ] + } + }, + { + "assetStoreId": "", + "name": "MalletBelgium", + "resourcesPreloading": "manually", + "type": "Scene3D::Model3DObject", + "variables": [ + { + "name": "IsPlayer", + "type": "boolean", + "value": false + } + ], + "effects": [], + "behaviors": [], + "content": { + "centerLocation": "CenteredOnZ", + "crossfadeDuration": 0.10000000149011612, + "depth": 85, + "height": 110, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "MalletBelgium.glb", + "originLocation": "ModelOrigin", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 110, + "animations": [] + } + }, + { + "assetStoreId": "", + "name": "FlagFrance", + "resourcesPreloading": "manually", + "type": "Scene3D::Model3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "centerLocation": "CenteredOnZ", + "crossfadeDuration": 0.1000000014901161, + "depth": 270, + "height": 25, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "FlagFrance.glb", + "originLocation": "ModelOrigin", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 150, + "animations": [ + { + "loop": true, + "name": "Wave", + "source": "Wave" + } + ] + } + }, + { + "assetStoreId": "", + "name": "MalletFrance", + "resourcesPreloading": "manually", + "type": "Scene3D::Model3DObject", + "variables": [ + { + "name": "IsPlayer", + "type": "boolean", + "value": false + } + ], + "effects": [], + "behaviors": [], + "content": { + "centerLocation": "CenteredOnZ", + "crossfadeDuration": 0.10000000149011612, + "depth": 85, + "height": 110, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "MalletFrance.glb", + "originLocation": "ModelOrigin", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 110, + "animations": [] + } + }, + { + "assetStoreId": "", + "name": "FlagSpain", + "resourcesPreloading": "manually", + "type": "Scene3D::Model3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "centerLocation": "CenteredOnZ", + "crossfadeDuration": 0.1000000014901161, + "depth": 270, + "height": 25, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "FlagSpain.glb", + "originLocation": "ModelOrigin", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 150, + "animations": [ + { + "loop": true, + "name": "Wave", + "source": "Wave" + } + ] + } + }, + { + "assetStoreId": "", + "name": "MalletSpain", + "resourcesPreloading": "manually", + "type": "Scene3D::Model3DObject", + "variables": [ + { + "name": "IsPlayer", + "type": "boolean", + "value": false + } + ], + "effects": [], + "behaviors": [], + "content": { + "centerLocation": "CenteredOnZ", + "crossfadeDuration": 0.10000000149011612, + "depth": 85, + "height": 110, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "MalletSpain.glb", + "originLocation": "ModelOrigin", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 110, + "animations": [] + } + }, + { + "assetStoreId": "", + "name": "FlagCanada", + "resourcesPreloading": "manually", + "type": "Scene3D::Model3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "centerLocation": "CenteredOnZ", + "crossfadeDuration": 0.1000000014901161, + "depth": 270, + "height": 25, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "FlagCanada.glb", + "originLocation": "ModelOrigin", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 150, + "animations": [ + { + "loop": true, + "name": "Wave", + "source": "Wave" + } + ] + } + }, + { + "assetStoreId": "", + "name": "MalletCanada", + "resourcesPreloading": "manually", + "type": "Scene3D::Model3DObject", + "variables": [ + { + "name": "IsPlayer", + "type": "boolean", + "value": false + } + ], + "effects": [], + "behaviors": [], + "content": { + "centerLocation": "CenteredOnZ", + "crossfadeDuration": 0.10000000149011612, + "depth": 85, + "height": 110, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "MalletCanada.glb", + "originLocation": "ModelOrigin", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 110, + "animations": [] + } + }, + { + "assetStoreId": "", + "name": "FlagGermany", + "resourcesPreloading": "manually", + "type": "Scene3D::Model3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "centerLocation": "CenteredOnZ", + "crossfadeDuration": 0.1000000014901161, + "depth": 270, + "height": 25, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "FlagGermany.glb", + "originLocation": "ModelOrigin", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 150, + "animations": [ + { + "loop": true, + "name": "Wave", + "source": "Wave" + } + ] + } + }, + { + "assetStoreId": "", + "name": "MalletGermany", + "resourcesPreloading": "manually", + "type": "Scene3D::Model3DObject", + "variables": [ + { + "name": "IsPlayer", + "type": "boolean", + "value": false + } + ], + "effects": [], + "behaviors": [], + "content": { + "centerLocation": "CenteredOnZ", + "crossfadeDuration": 0.10000000149011612, + "depth": 85, + "height": 110, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "MalletGermany.glb", + "originLocation": "ModelOrigin", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 110, + "animations": [] + } + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "folderName": "Gameplay", + "children": [ + { + "objectName": "MalletPlayer" + }, + { + "objectName": "MalletOpponent" + }, + { + "objectName": "Puck" + }, + { + "objectName": "PuckTrail" + }, + { + "folderName": "Mallets", + "children": [ + { + "objectName": "MalletUSA" + }, + { + "objectName": "MalletBelgium" + }, + { + "objectName": "MalletFrance" + }, + { + "objectName": "MalletSpain" + }, + { + "objectName": "MalletCanada" + }, + { + "objectName": "MalletGermany" + } + ] + } + ] + }, + { + "folderName": "ResultMenu" + }, + { + "folderName": "PowerUps", + "children": [ + { + "objectName": "PowerUpBigMallet" + }, + { + "objectName": "PowerUpFreeze" + }, + { + "objectName": "PowerUpTurbo" + }, + { + "objectName": "PowerUpShield" + }, + { + "objectName": "PowerUpRingSegment" + }, + { + "objectName": "GoalShield" + }, + { + "objectName": "GoalShieldIcon" + } + ] + }, + { + "folderName": "Field", + "children": [ + { + "objectName": "Table" + }, + { + "objectName": "Goal" + }, + { + "objectName": "Wall" + }, + { + "objectName": "PuckFloor" + }, + { + "objectName": "PuckCeiling" + } + ] + }, + { + "folderName": "Stadium", + "children": [ + { + "objectName": "Camera" + }, + { + "objectName": "Stadium" + }, + { + "objectName": "StadiumBackground" + }, + { + "objectName": "Confetti" + }, + { + "folderName": "Flags", + "children": [ + { + "objectName": "FlagUSA" + }, + { + "objectName": "FlagBelgium" + }, + { + "objectName": "FlagFrance" + }, + { + "objectName": "FlagSpain" + }, + { + "objectName": "FlagCanada" + }, + { + "objectName": "FlagGermany" + } + ] + } + ] + }, + { + "folderName": "UI", + "children": [ + { + "objectName": "UI_Scoreboard" + }, + { + "objectName": "UI_Announcement" + }, + { + "objectName": "UI_ResultMenu" + } + ] + } + ] + }, + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Initialization runs before the links: every system reads the teams from frame 1.", + "comment2": "Teams first: everything below reads Match.PlayerCountry / OpponentCountry." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "SceneJustBegins" + }, + "parameters": [ + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Match.PlayerCountry", + "=", + "Selection.PlayerCountry" + ] + }, + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Match.OpponentCountry", + "=", + "Selection.OpponentCountry" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Launched without the Menu scene, Selection.OpponentCountry is empty: the While then draws an opponent from CountryList.", + "comment2": "New country: Countries (Code, Name, Language) + CountryList entries, Mallet / Flag objects (groups MalletSkins, CountryFlags, preload manually), scoreboard flag animations, one anthem event below." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.OpponentCountry", + "=", + "\"\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Match.OpponentCountry", + "=", + "Match.PlayerCountry" + ] + } + ] + }, + { + "infiniteLoopWarning": true, + "type": "BuiltinCommonInstructions::While", + "whileConditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.OpponentCountry", + "=", + "Match.PlayerCountry" + ] + } + ], + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Match.OpponentCountry", + "=", + "CountryList[RandomInRange(0, VariableChildCount(CountryList) - 1)]" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "HUD and Collisions layers are hidden in the editor only.", + "comment2": "Camera copy mostly overridden the same frame by the Intro state (MatchFlow); the field of view is set only here." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Match.PlayerCode", + "=", + "Countries[Match.PlayerCountry].Code" + ] + }, + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Match.OpponentCode", + "=", + "Countries[Match.OpponentCountry].Code" + ] + }, + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Match.OpponentName", + "=", + "Countries[Match.OpponentCountry].Name" + ] + }, + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Commentator.Language", + "=", + "Countries[Match.PlayerCountry].Language" + ] + }, + { + "type": { + "value": "SetCameraCenterX" + }, + "parameters": [ + "", + "=", + "Camera.X()", + "\"\"", + "0" + ] + }, + { + "type": { + "value": "SetCameraCenterY" + }, + "parameters": [ + "", + "=", + "Camera.Y()", + "\"\"", + "0" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraZ" + }, + "parameters": [ + "", + "=", + "Camera.Z()", + "\"\"", + "0" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraRotationX" + }, + "parameters": [ + "", + "=", + "Camera.Object3D::RotationX()", + "\"\"", + "0" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraFov" + }, + "parameters": [ + "", + "=", + "CameraSettings.FieldOfView", + "\"\"", + "0" + ] + }, + { + "type": { + "value": "ResetTimer" + }, + "parameters": [ + "", + "\"StateTimer\"" + ] + }, + { + "type": { + "value": "AirHockeyUI::UI_Scoreboard::SetTeams" + }, + "parameters": [ + "UI_Scoreboard", + "Match.OpponentCountry", + "Match.OpponentCode", + "Match.PlayerCountry", + "Match.PlayerCode", + "" + ] + }, + { + "type": { + "value": "ShowLayer" + }, + "parameters": [ + "", + "\"Collisions\"" + ] + }, + { + "type": { + "value": "ShowLayer" + }, + "parameters": [ + "", + "\"HUD\"" + ] + }, + { + "type": { + "value": "HideCursor" + }, + "parameters": [ + "" + ] + }, + { + "type": { + "value": "AirHockeyUI::UI_OptionsModal::SetBackButtonVisible" + }, + "parameters": [ + "UI_OptionsModal", + "yes", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Sound actions only accept a fixed file name: one anthem event per country.", + "comment2": "Channel 2: MatchFlow starts the match music once it is silent." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.PlayerCountry", + "=", + "\"USA\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "AnthemUSA.mp3", + "2", + "no", + "85", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.PlayerCountry", + "=", + "\"Belgium\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "AnthemBelgium.mp3", + "2", + "no", + "85", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.PlayerCountry", + "=", + "\"France\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "AnthemFrance.mp3", + "2", + "no", + "85", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.PlayerCountry", + "=", + "\"Spain\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "AnthemSpain.mp3", + "2", + "no", + "85", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.PlayerCountry", + "=", + "\"Canada\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "AnthemCanada.mp3", + "2", + "no", + "85", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.PlayerCountry", + "=", + "\"Germany\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "AnthemGermany.mp3", + "2", + "no", + "85", + "1" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Link order = execution order, do not reorder: MatchFlow before CameraRig (the intro drives the camera), PuckAndSounds before Commentator (reads Commentator.NewHit*). Events after the links run last and override them.", + "comment2": "Commentator reads NewHit* written by PuckAndSounds the same frame." + }, + { + "type": "BuiltinCommonInstructions::Link", + "include": { + "includeConfig": 0 + }, + "target": "OptionsMenu" + }, + { + "type": "BuiltinCommonInstructions::Link", + "include": { + "includeConfig": 0 + }, + "target": "MatchFlow" + }, + { + "type": "BuiltinCommonInstructions::Link", + "include": { + "includeConfig": 0 + }, + "target": "CameraRig" + }, + { + "type": "BuiltinCommonInstructions::Link", + "include": { + "includeConfig": 0 + }, + "target": "PlayerMallet" + }, + { + "type": "BuiltinCommonInstructions::Link", + "include": { + "includeConfig": 0 + }, + "target": "OpponentAI" + }, + { + "type": "BuiltinCommonInstructions::Link", + "include": { + "includeConfig": 0 + }, + "target": "PowerUps" + }, + { + "type": "BuiltinCommonInstructions::Link", + "include": { + "includeConfig": 0 + }, + "target": "PuckAndSounds" + }, + { + "type": "BuiltinCommonInstructions::Link", + "include": { + "includeConfig": 0 + }, + "target": "Commentator" + }, + { + "type": "BuiltinCommonInstructions::Link", + "include": { + "includeConfig": 0 + }, + "target": "ScoreDisplay" + }, + { + "type": "BuiltinCommonInstructions::Link", + "include": { + "includeConfig": 0 + }, + "target": "StadiumCrowd" + }, + { + "type": "BuiltinCommonInstructions::Link", + "include": { + "includeConfig": 0 + }, + "target": "PuckTrail" + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "After the OptionsMenu link on purpose: overrides its Activate(yes) on window close, so the OPTIONS button never covers the result window.", + "comment2": "Activate(no) every frame of Finished." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Finished\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "Hide" + }, + "parameters": [ + "OptionsButton" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "OptionsButton", + "no", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "The Once of ShowCursor must stay a sub-event: merged into the IsOpen event, the else-if below would fire while the window stays open.", + "comment2": "Not during Finished: MatchFlow shows the cursor for the result menu." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "AirHockeyUI::UI_OptionsModal::IsOpen" + }, + "parameters": [ + "UI_OptionsModal", + "" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "ShowCursor" + }, + "parameters": [ + "" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [ + { + "type": { + "inverted": true, + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Finished\"" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "HideCursor" + }, + "parameters": [ + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Link", + "include": { + "includeConfig": 0 + }, + "target": "CountryModels" + } + ], + "layers": [ + { + "ambientLightColorB": 200, + "ambientLightColorG": 200, + "ambientLightColorR": 200, + "camera2DPlaneMaxDrawingDistance": 5000, + "camera3DFarPlaneDistance": 10000, + "camera3DFieldOfView": 45, + "camera3DNearPlaneDistance": 3, + "cameraType": "", + "followBaseLayerCamera": false, + "isLightingLayer": false, + "isLocked": false, + "name": "Background", + "renderingType": "", + "visibility": true, + "cameras": [], + "effects": [] + }, + { + "ambientLightColorB": 200, + "ambientLightColorG": 200, + "ambientLightColorR": 200, + "camera2DPlaneMaxDrawingDistance": 5000, + "camera3DFarPlaneDistance": 10000, + "camera3DFieldOfView": 45, + "camera3DNearPlaneDistance": 3, + "cameraType": "", + "followBaseLayerCamera": false, + "isLightingLayer": false, + "isLocked": false, + "name": "", + "renderingType": "", + "visibility": true, + "cameras": [ + { + "defaultSize": true, + "defaultViewport": true, + "height": 0, + "viewportBottom": 1, + "viewportLeft": 0, + "viewportRight": 1, + "viewportTop": 0, + "width": 0 + } + ], + "effects": [ + { + "effectType": "Scene3D::Skybox", + "name": "Sky", + "doubleParameters": { + "backgroundIntensity": 1, + "environmentIntensity": 1 + }, + "stringParameters": { + "backFaceResourceName": "SkyBack.png", + "bottomFaceResourceName": "SkyBack.png", + "frontFaceResourceName": "SkyFront.png", + "leftFaceResourceName": "SkyBack.png", + "rightFaceResourceName": "SkyBack.png", + "top": "Legacy", + "topFaceResourceName": "SkyBack.png" + }, + "booleanParameters": {} + }, + { + "effectType": "Scene3D::HemisphereLight", + "name": "SkyLight", + "doubleParameters": { + "elevation": 82, + "intensity": 0.55, + "rotation": -10 + }, + "stringParameters": { + "groundColor": "60;70;110", + "skyColor": "200;215;245", + "top": "Z+" + }, + "booleanParameters": {} + }, + { + "effectType": "Scene3D::DirectionalLight", + "name": "Sun", + "doubleParameters": { + "distanceFromCamera": 4000, + "elevation": 55, + "frustumSize": 4000, + "intensity": 0.9, + "minimumShadowBias": 0.0009, + "rotation": 40, + "shadowIntensity": 1, + "shadowNormalBias": 1 + }, + "stringParameters": { + "color": "255;250;235", + "shadowQuality": "high", + "shadowRenderingMode": "fittedToCameraView", + "top": "Z+" + }, + "booleanParameters": { + "isCastingShadow": true + } + } + ] + }, + { + "ambientLightColorB": 200, + "ambientLightColorG": 200, + "ambientLightColorR": 200, + "camera2DPlaneMaxDrawingDistance": 5000, + "camera3DFarPlaneDistance": 10000, + "camera3DFieldOfView": 45, + "camera3DNearPlaneDistance": 3, + "cameraType": "", + "followBaseLayerCamera": false, + "isLightingLayer": false, + "isLocked": false, + "name": "Collisions", + "renderingType": "", + "visibility": false, + "cameras": [], + "effects": [] + }, + { + "ambientLightColorB": 200, + "ambientLightColorG": 200, + "ambientLightColorR": 200, + "camera2DPlaneMaxDrawingDistance": 5000, + "camera3DFarPlaneDistance": 10000, + "camera3DFieldOfView": 45, + "camera3DNearPlaneDistance": 3, + "cameraType": "", + "followBaseLayerCamera": false, + "isLightingLayer": false, + "isLocked": false, + "name": "HUD", + "renderingType": "", + "visibility": true, + "cameras": [], + "effects": [] + }, + { + "ambientLightColorB": 200, + "ambientLightColorG": 200, + "ambientLightColorR": 200, + "camera2DPlaneMaxDrawingDistance": 5000, + "camera3DFarPlaneDistance": 10000, + "camera3DFieldOfView": 45, + "camera3DNearPlaneDistance": 3, + "cameraType": "", + "followBaseLayerCamera": false, + "isLightingLayer": false, + "isLocked": false, + "name": "ResultMenu", + "renderingType": "", + "visibility": true, + "cameras": [], + "effects": [] + }, + { + "ambientLightColorB": 200, + "ambientLightColorG": 200, + "ambientLightColorR": 200, + "camera2DPlaneMaxDrawingDistance": 5000, + "camera3DFarPlaneDistance": 10000, + "camera3DFieldOfView": 45, + "camera3DNearPlaneDistance": 3, + "cameraType": "", + "followBaseLayerCamera": false, + "isLightingLayer": false, + "isLocked": false, + "name": "Modal", + "renderingType": "", + "visibility": false, + "cameras": [], + "effects": [] + } + ], + "behaviorsSharedData": [ + { + "name": "Animation", + "type": "AnimatableCapability::AnimatableBehavior" + }, + { + "name": "Effect", + "type": "EffectCapability::EffectBehavior" + }, + { + "name": "Flippable", + "type": "FlippableCapability::FlippableBehavior" + }, + { + "name": "Object3D", + "type": "Scene3D::Base3DBehavior" + }, + { + "name": "Opacity", + "type": "OpacityCapability::OpacityBehavior" + }, + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "gravityX": 0, + "gravityY": 0, + "gravityZ": -9.8, + "worldScale": 100 + }, + { + "name": "Resizable", + "type": "ResizableCapability::ResizableBehavior" + }, + { + "name": "Scale", + "type": "ScalableCapability::ScalableBehavior" + } + ] + } + ], + "layoutsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "itemName": "Menu" + }, + { + "itemName": "Game" + } + ] + }, + "externalEvents": [ + { + "associatedLayout": "Game", + "name": "MatchFlow", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Match.State is written only in 'Match transitions'.", + "comment2": "StateTimer is reset on every transition and at scene start." + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Match transitions", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "GoalLineMargin: a puck bouncing on the goal mouth does not count.", + "comment2": "Puck origin = its centre." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Intro\"" + ] + }, + { + "type": { + "value": "CompareTimer" + }, + "parameters": [ + "", + "\"StateTimer\"", + ">", + "Match.IntroSeconds" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Kickoff\"" + ] + }, + { + "type": { + "value": "ResetTimer" + }, + "parameters": [ + "", + "\"StateTimer\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Kickoff\"" + ] + }, + { + "type": { + "value": "CompareTimer" + }, + "parameters": [ + "", + "\"StateTimer\"", + ">", + "Match.KickoffSeconds" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Playing\"" + ] + }, + { + "type": { + "value": "ResetTimer" + }, + "parameters": [ + "", + "\"StateTimer\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Playing\"" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Puck.Y()", + "<", + "Field.Top - Field.GoalLineMargin" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Match.ScorePlayer", + "+", + "1" + ] + }, + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Match.LastScorer", + "=", + "\"Player\"" + ] + }, + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Goal\"" + ] + }, + { + "type": { + "value": "ResetTimer" + }, + "parameters": [ + "", + "\"StateTimer\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Puck.Y()", + ">", + "Field.Bottom + Field.GoalLineMargin" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Match.ScoreOpponent", + "+", + "1" + ] + }, + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Match.LastScorer", + "=", + "\"Opponent\"" + ] + }, + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Goal\"" + ] + }, + { + "type": { + "value": "ResetTimer" + }, + "parameters": [ + "", + "\"StateTimer\"" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Goal\"" + ] + }, + { + "type": { + "value": "CompareTimer" + }, + "parameters": [ + "", + "\"StateTimer\"", + ">", + "Match.GoalCelebrationSeconds" + ] + } + ], + "actions": [ + { + "type": { + "value": "ResetTimer" + }, + "parameters": [ + "", + "\"StateTimer\"" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "max(Match.ScorePlayer, Match.ScoreOpponent)", + ">=", + "Match.GoalsToWin" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Finished\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Kickoff\"" + ] + } + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Match states", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "SetX / SetY on the Physics3D bodies are teleports only: Kickoff entry and the Goal clamp.", + "comment2": "Each teleport zeroes the velocities or clamps them." + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Intro: the orbit ends exactly on the Camera object and its last 20% (CameraLanding) blends the rotations into it, so CameraRig takes over without a jump.", + "comment2": "Progress = StateTimer / IntroSeconds, smoothstep eased. Knobs: CameraSettings.Intro*, ScoreboardCentreY / TopY." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Intro\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Progress", + "=", + "min(1, TimerElapsedTime(\"StateTimer\") / Match.IntroSeconds)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Eased", + "=", + "Progress * Progress * (3 - 2 * Progress)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CameraLanding", + "=", + "clamp((Progress - 0.8) / 0.2, 0, 1)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "OrbitAngle", + "=", + "ToDeg(atan2(Camera.X() - Field.CenterX, Camera.Y() - Field.CenterY)) + CameraSettings.IntroStartAngle * (1 - Eased)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "OrbitRadius", + "=", + "lerp(CameraSettings.IntroRadius, DistanceBetweenPositions(Field.CenterX, Field.CenterY, Camera.X(), Camera.Y()), Eased)" + ] + }, + { + "type": { + "value": "SetCameraCenterX" + }, + "parameters": [ + "", + "=", + "Field.CenterX + sin(ToRad(OrbitAngle)) * OrbitRadius", + "\"\"", + "0" + ] + }, + { + "type": { + "value": "SetCameraCenterY" + }, + "parameters": [ + "", + "=", + "Field.CenterY + cos(ToRad(OrbitAngle)) * OrbitRadius", + "\"\"", + "0" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraZ" + }, + "parameters": [ + "", + "=", + "lerp(CameraSettings.IntroHeight, Camera.Z(), Eased)", + "\"\"", + "0" + ] + }, + { + "type": { + "value": "Scene3D::TurnCameraTowardPosition" + }, + "parameters": [ + "", + "Field.CenterX", + "Field.CenterY", + "0", + "\"\"", + "0", + "no" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraRotationX" + }, + "parameters": [ + "", + "=", + "lerp(Scene3D::CameraRotationX(\"\", 0), Camera.Object3D::RotationX(), CameraLanding)", + "\"\"", + "0" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraRotationY" + }, + "parameters": [ + "", + "=", + "lerp(Scene3D::CameraRotationY(\"\", 0), Camera.Object3D::RotationY(), CameraLanding)", + "\"\"", + "0" + ] + }, + { + "type": { + "value": "SetCameraAngle" + }, + "parameters": [ + "", + "=", + "lerp(CameraAngle(\"\", 0), Camera.Angle(), CameraLanding)", + "\"\"", + "0" + ] + }, + { + "type": { + "value": "AirHockeyUI::UI_Scoreboard::SetIntroSlide" + }, + "parameters": [ + "UI_Scoreboard", + "clamp((Progress - 0.08) / 0.3, 0, 1)", + "" + ] + }, + { + "type": { + "value": "SetY" + }, + "parameters": [ + "UI_Scoreboard", + "=", + "lerp(CameraSettings.ScoreboardCentreY, CameraSettings.ScoreboardTopY, clamp((Progress - 0.7) / 0.25, 0, 1))" + ] + } + ], + "variables": [ + { + "name": "Progress", + "type": "number", + "value": 0 + }, + { + "name": "Eased", + "type": "number", + "value": 0 + }, + { + "name": "CameraLanding", + "type": "number", + "value": 0 + }, + { + "name": "OrbitAngle", + "type": "number", + "value": 0 + }, + { + "name": "OrbitRadius", + "type": "number", + "value": 0 + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Kickoff: the side that conceded serves, the puck starts 90 px into its half.", + "comment2": "Camera: CameraRig copies the Camera object every frame outside the Intro." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Kickoff\"" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "SetX" + }, + "parameters": [ + "Puck", + "=", + "Field.CenterX" + ] + }, + { + "type": { + "value": "SetY" + }, + "parameters": [ + "Puck", + "=", + "Field.CenterY" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetGravityScale" + }, + "parameters": [ + "Puck", + "Physics3D", + "=", + "0" + ] + }, + { + "type": { + "value": "Scene3D::Base3DBehavior::SetZ" + }, + "parameters": [ + "Puck", + "Object3D", + "=", + "0" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityX" + }, + "parameters": [ + "Puck", + "Physics3D", + "=", + "0" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityY" + }, + "parameters": [ + "Puck", + "Physics3D", + "=", + "0" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityZ" + }, + "parameters": [ + "Puck", + "Physics3D", + "=", + "0" + ] + }, + { + "type": { + "value": "SetX" + }, + "parameters": [ + "MalletOpponent", + "=", + "Field.CenterX" + ] + }, + { + "type": { + "value": "SetY" + }, + "parameters": [ + "MalletOpponent", + "=", + "Tuning.Opponent.GuardLineY + 50" + ] + }, + { + "type": { + "value": "SetY" + }, + "parameters": [ + "UI_Scoreboard", + "=", + "CameraSettings.ScoreboardTopY" + ] + }, + { + "type": { + "value": "AirHockeyUI::UI_Scoreboard::SetIntroSlide" + }, + "parameters": [ + "UI_Scoreboard", + "1", + "" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "max(Match.ScorePlayer, Match.ScoreOpponent)", + "=", + "Match.GoalsToWin - 1" + ] + } + ], + "actions": [ + { + "type": { + "value": "AirHockeyUI::UI_Announcement::ShowMessage" + }, + "parameters": [ + "UI_Announcement", + "\"MATCH POINT!\"", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [], + "actions": [ + { + "type": { + "value": "AirHockeyUI::UI_Announcement::ShowMessage" + }, + "parameters": [ + "UI_Announcement", + "\"FIRST TO \" + ToString(Match.GoalsToWin)", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.LastScorer", + "=", + "\"Player\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetY" + }, + "parameters": [ + "Puck", + "=", + "Field.CenterY - 90" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.LastScorer", + "=", + "\"Opponent\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetY" + }, + "parameters": [ + "Puck", + "=", + "Field.CenterY + 90" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Playing\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Match.ElapsedSeconds", + "+", + "TimeDelta()" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "AirHockeyUI::UI_Announcement::HideMessage" + }, + "parameters": [ + "UI_Announcement", + "" + ] + }, + { + "type": { + "value": "PlaySound" + }, + "parameters": [ + "", + "Whistle.aac", + "", + "70", + "1" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Goal\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityX" + }, + "parameters": [ + "Puck", + "Physics3D", + "*", + "0.9" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityY" + }, + "parameters": [ + "Puck", + "Physics3D", + "*", + "0.9" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetGravityScale" + }, + "parameters": [ + "Puck", + "Physics3D", + "=", + "0" + ] + }, + { + "type": { + "value": "PlaySound" + }, + "parameters": [ + "", + "Applause.mp3", + "no", + "40", + "1" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.LastScorer", + "=", + "\"Player\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "AirHockeyUI::UI_Announcement::ShowMessage" + }, + "parameters": [ + "UI_Announcement", + "\"GOAL!\"", + "" + ] + }, + { + "type": { + "value": "Create" + }, + "parameters": [ + "", + "Confetti", + "Field.CenterX", + "Field.Top", + "\"\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [], + "actions": [ + { + "type": { + "value": "AirHockeyUI::UI_Announcement::ShowMessage" + }, + "parameters": [ + "UI_Announcement", + "Match.OpponentName + \" SCORES\"", + "" + ] + }, + { + "type": { + "value": "PlaySound" + }, + "parameters": [ + "", + "GoalOpponent.aac", + "", + "90", + "1" + ] + }, + { + "type": { + "value": "Create" + }, + "parameters": [ + "", + "Confetti", + "Field.CenterX", + "Field.Bottom", + "\"\"" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "A puck bouncing off the net never comes back onto the field.", + "comment2": "Player scored = top goal (Y < Field.Top)." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.LastScorer", + "=", + "\"Player\"" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Puck.Y()", + ">", + "Field.Top - Field.PuckRadius" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetY" + }, + "parameters": [ + "Puck", + "=", + "Field.Top - Field.PuckRadius" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityY" + }, + "parameters": [ + "Puck", + "Physics3D", + "=", + "min(0, Puck.Physics3D::LinearVelocityY())" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.LastScorer", + "=", + "\"Opponent\"" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Puck.Y()", + "<", + "Field.Bottom + Field.PuckRadius" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetY" + }, + "parameters": [ + "Puck", + "=", + "Field.Bottom + Field.PuckRadius" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityY" + }, + "parameters": [ + "Puck", + "Physics3D", + "=", + "max(0, Puck.Physics3D::LinearVelocityY())" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Finished\"" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Match.ScorePlayer", + ">", + "Match.ScoreOpponent" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "ResultTitle", + "=", + "\"YOU WIN!\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Match.ScorePlayer", + "<", + "Match.ScoreOpponent" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "ResultTitle", + "=", + "\"DEFEAT\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "AirHockeyUI::UI_Announcement::HideMessage" + }, + "parameters": [ + "UI_Announcement", + "" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityX" + }, + "parameters": [ + "Puck", + "Physics3D", + "=", + "0" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityY" + }, + "parameters": [ + "Puck", + "Physics3D", + "=", + "0" + ] + }, + { + "type": { + "value": "PlaySound" + }, + "parameters": [ + "", + "Whistle.aac", + "", + "80", + "0.8" + ] + }, + { + "type": { + "value": "AirHockeyUI::UI_ResultMenu::Open" + }, + "parameters": [ + "UI_ResultMenu", + "ResultTitle", + "Match.PlayerCode + \" \" + ToString(Match.ScorePlayer) + \" - \" + ToString(Match.ScoreOpponent) + \" \" + Match.OpponentCode", + "" + ] + }, + { + "type": { + "value": "ShowCursor" + }, + "parameters": [ + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "AirHockeyUI::UI_ResultMenu::IsReplayClicked" + }, + "parameters": [ + "UI_ResultMenu", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "MousePointerLock::RequestPointerLock" + }, + "parameters": [ + "", + "" + ] + }, + { + "type": { + "value": "PlaySound" + }, + "parameters": [ + "", + "ButtonClick.mp3", + "", + "80", + "1" + ] + }, + { + "type": { + "value": "Scene" + }, + "parameters": [ + "", + "\"Game\"", + "yes" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Match.ScorePlayer", + "!=", + "Match.ScoreOpponent" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Repeat", + "repeatExpression": "8", + "conditions": [], + "actions": [ + { + "type": { + "value": "Create" + }, + "parameters": [ + "", + "Confetti", + "RandomInRange(Field.Left, Field.Right)", + "RandomInRange(Field.Top, Field.Bottom)", + "\"\"" + ] + } + ] + } + ] + } + ], + "variables": [ + { + "name": "ResultTitle", + "type": "string", + "value": "DRAW" + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Match music", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Channel 2 = the anthem started with the scene.", + "comment2": "MusicStarted keeps it from restarting; MatchMusic loops." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Match.MusicStarted", + "False", + "" + ] + }, + { + "type": { + "inverted": true, + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Intro\"" + ] + }, + { + "type": { + "inverted": true, + "value": "SoundPlaying" + }, + "parameters": [ + "", + "2" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlayMusic" + }, + "parameters": [ + "", + "MatchMusic.aac", + "yes", + "35", + "1" + ] + }, + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "Match.MusicStarted", + "True", + "" + ] + } + ] + } + ], + "parameters": [] + } + ] + }, + { + "associatedLayout": "Game", + "name": "PlayerMallet", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Kinematic body moved only through its velocity: Physics3D owns the position.", + "comment2": "Pointer lock writes PointerLock.U/V (0..1 over the screen) before Mallet movement reads them, same frame." + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Pointer lock", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Browsers keep Escape to leave the lock, the key may never reach the game: losing the lock opens the options window instead. Only while OptionsButton is active (off while the window is open or Finished), so closing it never reopens it.", + "comment2": "Browsers grant the lock only during a click: PLAY (Menu) and replay already request it. Harness tests cannot produce locked movement." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "PointerLock.WasLocked", + "True", + "" + ] + }, + { + "type": { + "inverted": true, + "value": "MousePointerLock::isPointerLocked" + }, + "parameters": [ + "", + "" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::IsActivated" + }, + "parameters": [ + "OptionsButton", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "AirHockeyUI::UI_OptionsModal::Open" + }, + "parameters": [ + "UI_OptionsModal", + "Settings.Volume", + "Settings.MalletSensitivity", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "MousePointerLock::isPointerLocked" + }, + "parameters": [ + "", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "PointerLock.WasLocked", + "True", + "" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Or" + }, + "parameters": [], + "subInstructions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Finished\"" + ] + }, + { + "type": { + "value": "AirHockeyUI::UI_OptionsModal::IsOpen" + }, + "parameters": [ + "UI_OptionsModal", + "" + ] + } + ] + } + ], + "actions": [ + { + "type": { + "value": "MousePointerLock::ExitPointerLock" + }, + "parameters": [ + "", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "PointerLock.U", + "=", + "clamp(PointerLock.U + MousePointerLock::MovementX() * PointerLock.Speed / CameraWidth(\"HUD\", 0), 0, 1)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "PointerLock.V", + "=", + "clamp(PointerLock.V + MousePointerLock::MovementY() * PointerLock.Speed / CameraHeight(\"HUD\", 0), 0, 1)" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "PointerLock.U", + "=", + "clamp((CursorX(\"HUD\", 0) - (CameraX(\"HUD\", 0) - CameraWidth(\"HUD\", 0) / 2)) / CameraWidth(\"HUD\", 0), 0, 1)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "PointerLock.V", + "=", + "clamp((CursorY(\"HUD\", 0) - (CameraY(\"HUD\", 0) - CameraHeight(\"HUD\", 0) / 2)) / CameraHeight(\"HUD\", 0), 0, 1)" + ] + }, + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "PointerLock.WasLocked", + "False", + "" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "HasAnyTouchOrMouseStarted" + }, + "parameters": [ + "" + ] + }, + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "!=", + "\"Finished\"" + ] + }, + { + "type": { + "inverted": true, + "value": "AirHockeyUI::UI_OptionsModal::IsOpen" + }, + "parameters": [ + "UI_OptionsModal", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "MousePointerLock::RequestPointerLock" + }, + "parameters": [ + "", + "" + ] + } + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Mallet movement", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "FollowGain = (1 - (1 - S/10)^(TimeDelta*60)) / TimeDelta: the share of the gap covered per frame does not depend on the frame rate, and is 0 while paused.", + "comment2": "S = Settings.MalletSensitivity (OPTIONS window, 1..10, 10 = sticks to the cursor)." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Finished\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TargetX", + "=", + "lerp(Field.Left + Field.MalletRadius, Field.Right - Field.MalletRadius, PointerLock.U)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TargetY", + "=", + "lerp(Field.CenterY + Field.MalletRadius, Field.Bottom - Field.MalletRadius, PointerLock.V)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "FollowGain", + "=", + "(1 - pow(1 - Settings.MalletSensitivity / 10, TimeDelta() * 60)) / max(TimeDelta(), 0.001)" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityX" + }, + "parameters": [ + "MalletPlayer", + "Physics3D", + "=", + "clamp((TargetX - MalletPlayer.X()) * FollowGain, -Tuning.Player.MaxSpeed, Tuning.Player.MaxSpeed)" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityY" + }, + "parameters": [ + "MalletPlayer", + "Physics3D", + "=", + "clamp((TargetY - MalletPlayer.Y()) * FollowGain, -Tuning.Player.MaxSpeed, Tuning.Player.MaxSpeed)" + ] + } + ], + "variables": [ + { + "name": "TargetX", + "type": "number", + "value": 0 + }, + { + "name": "TargetY", + "type": "number", + "value": 0 + }, + { + "name": "FollowGain", + "type": "number", + "value": 0 + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [], + "actions": [ + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityX" + }, + "parameters": [ + "MalletPlayer", + "Physics3D", + "=", + "0" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityY" + }, + "parameters": [ + "MalletPlayer", + "Physics3D", + "=", + "0" + ] + } + ] + } + ], + "parameters": [] + } + ] + }, + { + "associatedLayout": "Game", + "name": "OpponentAI", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "MalletOpponent.State is written only in 'Opponent transitions'. Difficulty knobs: Tuning.Opponent.*", + "comment2": "Kinematic body moved only through its velocity, like PlayerMallet." + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Opponent transitions", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Siblings run in order and re-test State: one frame can chain transitions (Idle -> Defend -> Attack).", + "comment2": "Not Playing -> Idle; the Else holds every in-play transition." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Playing\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "State", + "=", + "\"Idle\"" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "StillSeconds", + "=", + "0" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "State", + "=", + "\"Idle\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "State", + "=", + "\"Defend\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "State", + "=", + "\"Defend\"" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Puck.Y()", + "<", + "Field.CenterY" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Puck.Y()", + ">", + "MalletOpponent.Y() + 10" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "State", + "=", + "\"Attack\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "State", + "=", + "\"Attack\"" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "No Or here: when only the puck branch of an Or is true, no mallet is picked and State is not written.", + "comment2": "Else-if chain: Strike only when no retreat happened this frame." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Puck.Y()", + ">", + "Field.CenterY + 40" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "State", + "=", + "\"Defend\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Puck.Y()", + "<", + "MalletOpponent.Y() - 20" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "State", + "=", + "\"Defend\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [ + { + "type": { + "value": "BooleanObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "StrikePlanned", + "True", + "" + ] + }, + { + "type": { + "value": "NumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "ReactionDelay", + "<=", + "0" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "DistanceBetweenPositions(MalletOpponent.X(), MalletOpponent.Y(), Puck.X(), Puck.Y())", + "<", + "Tuning.Opponent.StrikeRange" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "State", + "=", + "\"Strike\"" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "StrikeTimeLeft", + "=", + "Tuning.Opponent.StrikeSeconds" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "SpeedFactor", + "=", + "RandomFloatInRange(0.65, 1)" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "State", + "=", + "\"Strike\"" + ] + }, + { + "type": { + "value": "NumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "StrikeTimeLeft", + "<=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "State", + "=", + "\"Defend\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "DistanceBetweenPositions(MalletOpponent.X(), MalletOpponent.Y(), MalletOpponent.AnchorX, MalletOpponent.AnchorY)", + "<", + "Tuning.Opponent.StuckDistance" + ] + }, + { + "type": { + "value": "NumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "Effects.FrozenSeconds", + "<=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "StillSeconds", + "+", + "TimeDelta()" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "StillSeconds", + "=", + "0" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "AnchorX", + "=", + "MalletOpponent.X()" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "AnchorY", + "=", + "MalletOpponent.Y()" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "StringObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "State", + "=", + "\"Unstick\"" + ] + }, + { + "type": { + "value": "NumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "StillSeconds", + ">=", + "Tuning.Opponent.StuckSeconds" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "State", + "=", + "\"Unstick\"" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "UnstickTimeLeft", + "=", + "Tuning.Opponent.UnstickSeconds" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "StillSeconds", + "=", + "0" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "State", + "=", + "\"Unstick\"" + ] + }, + { + "type": { + "value": "NumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "UnstickTimeLeft", + "<=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "State", + "=", + "\"Defend\"" + ] + } + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Opponent aim mistakes", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Defend follows a snapshot of the puck (TrackedPuckX), not the live puck: the AI reacts late, so fast shots can score.", + "comment2": "Refreshed every Tuning.Opponent.AimRefreshSeconds, in every state." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "AimErrorCooldown", + "-", + "TimeDelta()" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "AimErrorCooldown", + "<=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "AimErrorX", + "=", + "RandomFloatInRange(-Tuning.Opponent.AimError, Tuning.Opponent.AimError)" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "AimErrorCooldown", + "=", + "Tuning.Opponent.AimRefreshSeconds" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "TrackedPuckX", + "=", + "Puck.X()" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "SpeedFactor", + "=", + "RandomFloatInRange(Tuning.Opponent.SpeedFactorMin, 1)" + ] + } + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Opponent states", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "State", + "=", + "\"Idle\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TargetX", + "=", + "Field.CenterX" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TargetY", + "=", + "Tuning.Opponent.GuardLineY + 50" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "FollowGain", + "=", + "Tuning.Opponent.DefendGain" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "CurrentMaxSpeed", + "=", + "Tuning.Opponent.MaxSpeed" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "State", + "=", + "\"Defend\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TargetX", + "=", + "clamp(MalletOpponent.TrackedPuckX + MalletOpponent.AimErrorX, Field.CenterX - 150, Field.CenterX + 150)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TargetY", + "=", + "Tuning.Opponent.GuardLineY" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "FollowGain", + "=", + "Tuning.Opponent.DefendGain" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "CurrentMaxSpeed", + "=", + "Tuning.Opponent.MaxSpeed * MalletOpponent.SpeedFactor" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "State", + "=", + "\"Attack\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TargetX", + "=", + "Puck.X() + MalletOpponent.AimErrorX * 0.2" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TargetY", + "=", + "Puck.Y() - 20" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "FollowGain", + "=", + "Tuning.Opponent.AttackGain" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "CurrentMaxSpeed", + "=", + "Tuning.Opponent.AttackMaxSpeed * MalletOpponent.SpeedFactor" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Rolled once per attack: StrikePlanned and ReactionDelay are read by the Attack -> Strike transition.", + "comment2": "Trigger once = first frame of Attack." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "SpeedFactor", + "=", + "RandomFloatInRange(Tuning.Opponent.SpeedFactorMin, 1)" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "ReactionDelay", + "=", + "0" + ] + }, + { + "type": { + "value": "SetBooleanObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "StrikePlanned", + "False", + "" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "RandomFloat(1)", + "<", + "Tuning.Opponent.HesitationChance" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "ReactionDelay", + "=", + "RandomFloatInRange(0.15, Tuning.Opponent.HesitationMaxSeconds)" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "RandomFloat(1)", + "<", + "Tuning.Opponent.StrikeChance" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "StrikePlanned", + "True", + "" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "ReactionDelay", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "ReactionDelay", + "-", + "TimeDelta()" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TargetX", + "=", + "MalletOpponent.X()" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TargetY", + "=", + "MalletOpponent.Y()" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "State", + "=", + "\"Strike\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "StrikeTimeLeft", + "-", + "TimeDelta()" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "StrikeDistance", + "=", + "max(1, DistanceBetweenPositions(MalletOpponent.X(), MalletOpponent.Y(), Puck.X(), Puck.Y()))" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TargetX", + "=", + "Puck.X() + (Puck.X() - MalletOpponent.X()) / StrikeDistance * 150" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TargetY", + "=", + "Puck.Y() + (Puck.Y() - MalletOpponent.Y()) / StrikeDistance * 150" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "FollowGain", + "=", + "25" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "CurrentMaxSpeed", + "=", + "Tuning.Opponent.StrikeSpeed * MalletOpponent.SpeedFactor" + ] + } + ], + "variables": [ + { + "name": "StrikeDistance", + "type": "number", + "value": 1 + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "State", + "=", + "\"Unstick\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "UnstickTimeLeft", + "-", + "TimeDelta()" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TargetX", + "=", + "MalletOpponent.X()" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TargetY", + "=", + "MalletOpponent.Y() + Tuning.Opponent.UnstickDistance" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "FollowGain", + "=", + "Tuning.Opponent.AttackGain" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "CurrentMaxSpeed", + "=", + "Tuning.Opponent.AttackMaxSpeed" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TargetX", + "=", + "clamp(TargetX, Field.Left + Field.MalletRadius, Field.Right - Field.MalletRadius)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TargetY", + "=", + "clamp(TargetY, Field.Top + Field.MalletRadius, Field.CenterY - Field.MalletRadius)" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityX" + }, + "parameters": [ + "MalletOpponent", + "Physics3D", + "=", + "clamp((TargetX - MalletOpponent.X()) * FollowGain, -MalletOpponent.CurrentMaxSpeed, MalletOpponent.CurrentMaxSpeed)" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityY" + }, + "parameters": [ + "MalletOpponent", + "Physics3D", + "=", + "clamp((TargetY - MalletOpponent.Y()) * FollowGain, -MalletOpponent.CurrentMaxSpeed, MalletOpponent.CurrentMaxSpeed)" + ] + } + ] + } + ], + "variables": [ + { + "name": "TargetX", + "type": "number", + "value": 960 + }, + { + "name": "TargetY", + "type": "number", + "value": 130 + }, + { + "name": "FollowGain", + "type": "number", + "value": 6 + } + ] + } + ], + "parameters": [] + } + ] + }, + { + "associatedLayout": "Game", + "name": "PuckAndSounds", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "The mallets never touch the puck in the physics engine (Physics3D layers and masks 4): 'Mallet hit' computes each hit itself. Walls, corners and goal backs stay handled by the physics engine.", + "comment2": "Reads PowerUps.PuckSpeedCap (PowerUps sheet). Writes Match.LastHitter and Commentator.NewHitBy/NewHitSpeed on the first frame of each touch." + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Puck flat and speed cap", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Goal\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityZ" + }, + "parameters": [ + "Puck", + "Physics3D", + "=", + "0" + ] + }, + { + "type": { + "value": "Scene3D::Base3DBehavior::SetZ" + }, + "parameters": [ + "Puck", + "Object3D", + "=", + "0" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Physics3D::Physics3DBehavior::LinearVelocityLength" + }, + "parameters": [ + "Puck", + "Physics3D", + ">", + "PowerUps.PuckSpeedCap" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "SpeedRatio", + "=", + "PowerUps.PuckSpeedCap / Puck.Physics3D::LinearVelocityLength()" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityX" + }, + "parameters": [ + "Puck", + "Physics3D", + "*", + "SpeedRatio" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityY" + }, + "parameters": [ + "Puck", + "Physics3D", + "*", + "SpeedRatio" + ] + } + ], + "variables": [ + { + "name": "SpeedRatio", + "type": "number", + "value": 1 + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Safety net", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Last resort if the puck slips through a border: it is put back on the field and sent back toward the centre. No end-line check in front of a goal, where the puck must cross to score.", + "comment2": "One-off teleport under a guard (rule 1). Goal gap = |X - Field.CenterX| <= Field.GoalHalfWidth." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Puck.X()", + "<", + "Field.Left + Field.PuckRadius" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetX" + }, + "parameters": [ + "Puck", + "=", + "Field.Left + Field.PuckRadius" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityX" + }, + "parameters": [ + "Puck", + "Physics3D", + "=", + "abs(Puck.Physics3D::LinearVelocityX())" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Puck.X()", + ">", + "Field.Right - Field.PuckRadius" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetX" + }, + "parameters": [ + "Puck", + "=", + "Field.Right - Field.PuckRadius" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityX" + }, + "parameters": [ + "Puck", + "Physics3D", + "=", + "-abs(Puck.Physics3D::LinearVelocityX())" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "abs(Puck.X() - Field.CenterX)", + ">", + "Field.GoalHalfWidth" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Puck.Y()", + "<", + "Field.Top + Field.PuckRadius" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetY" + }, + "parameters": [ + "Puck", + "=", + "Field.Top + Field.PuckRadius" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityY" + }, + "parameters": [ + "Puck", + "Physics3D", + "=", + "abs(Puck.Physics3D::LinearVelocityY())" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Puck.Y()", + ">", + "Field.Bottom - Field.PuckRadius" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetY" + }, + "parameters": [ + "Puck", + "=", + "Field.Bottom - Field.PuckRadius" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityY" + }, + "parameters": [ + "Puck", + "Physics3D", + "=", + "-abs(Puck.Physics3D::LinearVelocityY())" + ] + } + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Impact sounds", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Physics3D::CollisionStarted" + }, + "parameters": [ + "Puck", + "Physics3D", + "MalletPlayer", + "Physics3D", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySound" + }, + "parameters": [ + "", + "PuckHit.aac", + "", + "90", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Physics3D::CollisionStarted" + }, + "parameters": [ + "Puck", + "Physics3D", + "MalletOpponent", + "Physics3D", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySound" + }, + "parameters": [ + "", + "PuckHit.aac", + "", + "90", + "0.9" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Physics3D::CollisionStarted" + }, + "parameters": [ + "Puck", + "Physics3D", + "Wall", + "Physics3D", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySound" + }, + "parameters": [ + "", + "WallBounce.aac", + "", + "70", + "1.2" + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Mallet hit", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Rocket League style hit (soccar): the puck is put back at the mallet edge, takes the mallet speed along the contact line with a little friction, gets an extra kick on the first frame of the touch, and always leaves at a minimum speed.", + "comment2": "Touch = Distance < Mallets.Radius + Field.PuckRadius, not in Goal state; IsTouchingPuck marks a running touch. Each step reads the puck velocity left by the previous one: keep the order." + }, + { + "type": "BuiltinCommonInstructions::ForEach", + "object": "Mallets", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Distance", + "=", + "max(0.001, DistanceBetweenPositions(Puck.X(), Puck.Y(), Mallets.X(), Mallets.Y()))" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "Distance", + "<", + "Mallets.Radius + Field.PuckRadius" + ] + }, + { + "type": { + "inverted": true, + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Goal\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "NormalX", + "=", + "(Puck.X() - Mallets.X()) / Distance" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "NormalY", + "=", + "(Puck.Y() - Mallets.Y()) / Distance" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ClosingSpeed", + "=", + "-((Puck.Physics3D::LinearVelocityX() - Mallets.Physics3D::LinearVelocityX()) * NormalX + (Puck.Physics3D::LinearVelocityY() - Mallets.Physics3D::LinearVelocityY()) * NormalY)" + ] + }, + { + "type": { + "value": "SetX" + }, + "parameters": [ + "Puck", + "=", + "clamp(Mallets.X() + NormalX * (Mallets.Radius + Field.PuckRadius), Field.Left + Field.PuckRadius, Field.Right - Field.PuckRadius)" + ] + }, + { + "type": { + "value": "SetY" + }, + "parameters": [ + "Puck", + "=", + "clamp(Mallets.Y() + NormalY * (Mallets.Radius + Field.PuckRadius), Field.Top + Field.PuckRadius, Field.Bottom - Field.PuckRadius)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ExtraSpeed", + "=", + "min(sqrt((Puck.Physics3D::LinearVelocityX() - Mallets.Physics3D::LinearVelocityX()) * (Puck.Physics3D::LinearVelocityX() - Mallets.Physics3D::LinearVelocityX()) + (Puck.Physics3D::LinearVelocityY() - Mallets.Physics3D::LinearVelocityY()) * (Puck.Physics3D::LinearVelocityY() - Mallets.Physics3D::LinearVelocityY())), Tuning.Hit.ExtraSpeedCap)" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Puck pinned against a wall: the mallet pushes it into a border, so it could not be put back at the mallet edge. It is pushed along the wall instead (toward the centre in a corner), so it always gets free.", + "comment2": "Pinned = still overlapping by more than 1 px after the clamp. Normal component into a side/end wall zeroed, fallback sign(Field.CenterX - X) if both zero, then renormalised and ClosingSpeed recomputed." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "DistanceBetweenPositions(Puck.X(), Puck.Y(), Mallets.X(), Mallets.Y())", + "<", + "Mallets.Radius + Field.PuckRadius - 1" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "abs(Puck.X() - Field.CenterX)", + ">=", + "(Field.Right - Field.Left) / 2 - Field.PuckRadius - 1" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "NormalX", + "=", + "0" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "abs(Puck.Y() - Field.CenterY)", + ">=", + "(Field.Bottom - Field.Top) / 2 - Field.PuckRadius - 1" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "NormalY", + "=", + "0" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "NormalX", + "=", + "0" + ] + }, + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "NormalY", + "=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "NormalX", + "=", + "sign(Field.CenterX - Puck.X() + 0.001)" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Distance", + "=", + "max(0.001, sqrt(NormalX * NormalX + NormalY * NormalY))" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "NormalX", + "/", + "Distance" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "NormalY", + "/", + "Distance" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ClosingSpeed", + "=", + "-((Puck.Physics3D::LinearVelocityX() - Mallets.Physics3D::LinearVelocityX()) * NormalX + (Puck.Physics3D::LinearVelocityY() - Mallets.Physics3D::LinearVelocityY()) * NormalY)" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "The mallet moves toward the puck: the puck takes the mallet speed along the contact line (no bounce), and a little friction drags it sideways with the mallet.", + "comment2": "ClosingSpeed > 0 only. v += (1 + Tuning.Hit.Restitution) * ClosingSpeed * n - FrictionSpeed * tangent; tangent slip cut by min(slip * Tuning.Hit.FrictionShare, 2 * ClosingSpeed)." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "ClosingSpeed", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TangentX", + "=", + "(Puck.Physics3D::LinearVelocityX() - Mallets.Physics3D::LinearVelocityX()) + ClosingSpeed * NormalX" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TangentY", + "=", + "(Puck.Physics3D::LinearVelocityY() - Mallets.Physics3D::LinearVelocityY()) + ClosingSpeed * NormalY" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "SlipSpeed", + "=", + "sqrt(TangentX * TangentX + TangentY * TangentY)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "FrictionSpeed", + "=", + "min(SlipSpeed * Tuning.Hit.FrictionShare, 2 * ClosingSpeed) / max(0.001, SlipSpeed)" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityX" + }, + "parameters": [ + "Puck", + "Physics3D", + "+", + "(1 + Tuning.Hit.Restitution) * ClosingSpeed * NormalX - FrictionSpeed * TangentX" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityY" + }, + "parameters": [ + "Puck", + "Physics3D", + "+", + "(1 + Tuning.Hit.Restitution) * ClosingSpeed * NormalY - FrictionSpeed * TangentY" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "First frame of a touch: an extra kick along the mallet-to-puck line, proportionally stronger on slow touches. The mallet becomes the last hitter (used by the power-ups and the commentator).", + "comment2": "IsTouchingPuck false = touch start. ExtraSpeed = min(relative speed, Tuning.Hit.ExtraSpeedCap) * scale; scale goes ExtraLowScale -> ExtraMidScale -> ExtraHighScale between ExtraLowSpeed, ExtraMidSpeed and ExtraSpeedCap." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "BooleanObjectVariable" + }, + "parameters": [ + "Mallets", + "IsTouchingPuck", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ExtraSpeed", + "*", + "Tuning.Hit.ExtraLowScale + (Tuning.Hit.ExtraMidScale - Tuning.Hit.ExtraLowScale) * clamp((ExtraSpeed - Tuning.Hit.ExtraLowSpeed) / (Tuning.Hit.ExtraMidSpeed - Tuning.Hit.ExtraLowSpeed), 0, 1) + (Tuning.Hit.ExtraHighScale - Tuning.Hit.ExtraMidScale) * clamp((ExtraSpeed - Tuning.Hit.ExtraMidSpeed) / (Tuning.Hit.ExtraSpeedCap - Tuning.Hit.ExtraMidSpeed), 0, 1)" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityX" + }, + "parameters": [ + "Puck", + "Physics3D", + "+", + "ExtraSpeed * NormalX" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityY" + }, + "parameters": [ + "Puck", + "Physics3D", + "+", + "ExtraSpeed * NormalY" + ] + }, + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Match.LastHitter", + "=", + "Mallets.ObjectName()" + ] + }, + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Commentator.NewHitBy", + "=", + "Mallets.ObjectName()" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Commentator.NewHitSpeed", + "=", + "Puck.Physics3D::LinearVelocityLength()" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Whatever happened above, the puck always leaves the mallet at a minimum speed, so it never stays glued to it (even against a wall). Then the mallet remembers that it touches the puck.", + "comment2": "Relative normal speed, read again after the impulses above, raised to Tuning.Hit.MinSeparationSpeed. Must stay after them. IsTouchingPuck set True here, set False by the next event once the mallet is away." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "(Puck.Physics3D::LinearVelocityX() - Mallets.Physics3D::LinearVelocityX()) * NormalX + (Puck.Physics3D::LinearVelocityY() - Mallets.Physics3D::LinearVelocityY()) * NormalY", + "<", + "Tuning.Hit.MinSeparationSpeed" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ExtraSpeed", + "=", + "(Tuning.Hit.MinSeparationSpeed - ((Puck.Physics3D::LinearVelocityX() - Mallets.Physics3D::LinearVelocityX()) * NormalX + (Puck.Physics3D::LinearVelocityY() - Mallets.Physics3D::LinearVelocityY()) * NormalY))" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityX" + }, + "parameters": [ + "Puck", + "Physics3D", + "+", + "ExtraSpeed * NormalX" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityY" + }, + "parameters": [ + "Puck", + "Physics3D", + "+", + "ExtraSpeed * NormalY" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetBooleanObjectVariable" + }, + "parameters": [ + "Mallets", + "IsTouchingPuck", + "True", + "" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "Distance", + ">=", + "Mallets.Radius + Field.PuckRadius" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanObjectVariable" + }, + "parameters": [ + "Mallets", + "IsTouchingPuck", + "False", + "" + ] + } + ] + } + ], + "variables": [ + { + "name": "Distance", + "type": "number", + "value": 0 + }, + { + "name": "NormalX", + "type": "number", + "value": 0 + }, + { + "name": "NormalY", + "type": "number", + "value": 0 + }, + { + "name": "ClosingSpeed", + "type": "number", + "value": 0 + }, + { + "name": "TangentX", + "type": "number", + "value": 0 + }, + { + "name": "TangentY", + "type": "number", + "value": 0 + }, + { + "name": "SlipSpeed", + "type": "number", + "value": 0 + }, + { + "name": "FrictionSpeed", + "type": "number", + "value": 0 + }, + { + "name": "ExtraSpeed", + "type": "number", + "value": 0 + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Stuck puck", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "A puck can stop where no mallet goes (in a corner behind the AI guard line): after a while it is nudged toward the centre of the field.", + "comment2": "Playing only. Puck var StillSeconds, reset by the Else and after the nudge." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Playing\"" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Physics3D::Physics3DBehavior::LinearVelocityLength" + }, + "parameters": [ + "Puck", + "Physics3D", + "<", + "Tuning.Puck.StuckSpeed" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "Puck", + "StillSeconds", + "+", + "TimeDelta()" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "Puck", + "StillSeconds", + "=", + "0" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberObjectVariable" + }, + "parameters": [ + "Puck", + "StillSeconds", + ">=", + "Tuning.Puck.StuckSeconds" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "NudgeDistance", + "=", + "max(1, DistanceBetweenPositions(Puck.X(), Puck.Y(), Field.CenterX, Field.CenterY))" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityX" + }, + "parameters": [ + "Puck", + "Physics3D", + "=", + "(Field.CenterX - Puck.X()) / NudgeDistance * Tuning.Puck.NudgeSpeed" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityY" + }, + "parameters": [ + "Puck", + "Physics3D", + "=", + "(Field.CenterY - Puck.Y()) / NudgeDistance * Tuning.Puck.NudgeSpeed" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "Puck", + "StillSeconds", + "=", + "0" + ] + } + ], + "variables": [ + { + "name": "NudgeDistance", + "type": "number", + "value": 1 + } + ] + } + ] + } + ], + "parameters": [] + } + ] + }, + { + "associatedLayout": "Game", + "name": "ScoreDisplay", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "AirHockeyUI::UI_Scoreboard::SetScore" + }, + "parameters": [ + "UI_Scoreboard", + "Match.ScoreOpponent", + "Match.ScorePlayer", + "" + ] + }, + { + "type": { + "value": "AirHockeyUI::UI_Scoreboard::SetClock" + }, + "parameters": [ + "UI_Scoreboard", + "\"FIRST TO \" + ToString(Match.GoalsToWin)", + "Match.ElapsedSeconds", + "" + ] + } + ] + } + ] + }, + { + "associatedLayout": "Game", + "name": "StadiumCrowd", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "The Wave clip of the stadium is not looped, so \"animation has ended\" tells when the Mexican wave is over. The clips live in the 3D model file (tools/set_model_animations.py).", + "comment2": "FSM Stadium.State (Cheer, Wave): written only in 'Crowd transitions', clip set once on state entry in 'Crowd states' (same frame). Wave = 16 shape keys in Stadium.glb." + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Crowd transitions", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringObjectVariable" + }, + "parameters": [ + "Stadium", + "State", + "=", + "\"Cheer\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "Stadium", + "WaveCheckCooldown", + "-", + "TimeDelta()" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberObjectVariable" + }, + "parameters": [ + "Stadium", + "WaveCheckCooldown", + "<=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "Stadium", + "WaveCheckCooldown", + "=", + "Crowd.WaveCheckSeconds" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "RandomInRange(1, Crowd.WaveChanceOneIn)", + "=", + "1" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringObjectVariable" + }, + "parameters": [ + "Stadium", + "State", + "=", + "\"Wave\"" + ] + } + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringObjectVariable" + }, + "parameters": [ + "Stadium", + "State", + "=", + "\"Wave\"" + ] + }, + { + "type": { + "value": "AnimatableCapability::AnimatableBehavior::HasAnimationEnded" + }, + "parameters": [ + "Stadium", + "Animation" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringObjectVariable" + }, + "parameters": [ + "Stadium", + "State", + "=", + "\"Cheer\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Goal\"" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "SetStringObjectVariable" + }, + "parameters": [ + "Stadium", + "State", + "=", + "\"Wave\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Intro\"" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "SetStringObjectVariable" + }, + "parameters": [ + "Stadium", + "State", + "=", + "\"Cheer\"" + ] + }, + { + "type": { + "value": "ResetObjectTimer" + }, + "parameters": [ + "Stadium", + "\"IntroWave\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringObjectVariable" + }, + "parameters": [ + "Stadium", + "State", + "=", + "\"Cheer\"" + ] + }, + { + "type": { + "value": "CompareObjectTimer" + }, + "parameters": [ + "Stadium", + "\"IntroWave\"", + ">=", + "Crowd.IntroWaveDelaySeconds" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "SetStringObjectVariable" + }, + "parameters": [ + "Stadium", + "State", + "=", + "\"Wave\"" + ] + } + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Crowd states", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringObjectVariable" + }, + "parameters": [ + "Stadium", + "State", + "=", + "\"Wave\"" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "AnimatableCapability::AnimatableBehavior::SetName" + }, + "parameters": [ + "Stadium", + "Animation", + "=", + "\"Wave\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringObjectVariable" + }, + "parameters": [ + "Stadium", + "State", + "=", + "\"Cheer\"" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "AnimatableCapability::AnimatableBehavior::SetName" + }, + "parameters": [ + "Stadium", + "Animation", + "=", + "\"Cheer\"" + ] + } + ] + } + ], + "parameters": [] + } + ] + }, + { + "associatedLayout": "Game", + "name": "PuckTrail", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "The trail is a chain of flat 3D boxes. A 3D box keeps its top-left corner when it is resized, so each segment stores its centre (CenterX, CenterY) and is put back on it after every resize.", + "comment2": "A step >= 200 px is a teleport (kickoff, safety net): no segment. TrailLastX/Y is updated after the segment is laid, which reads last frame's position." + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Lay segments", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "StepLength", + "=", + "DistanceBetweenPositions(Puck.TrailLastX, Puck.TrailLastY, Puck.X(), Puck.Y())" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "StepLength", + ">=", + "TrailSettings.MinStep" + ] + }, + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "StepLength", + "<", + "200" + ] + }, + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Playing\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "Create" + }, + "parameters": [ + "", + "PuckTrail", + "0", + "0", + "\"\"" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "PuckTrail", + "CenterX", + "=", + "(Puck.TrailLastX + Puck.X()) / 2" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "PuckTrail", + "CenterY", + "=", + "(Puck.TrailLastY + Puck.Y()) / 2" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "PuckTrail", + "Life", + "=", + "1" + ] + }, + { + "type": { + "value": "ResizableCapability::ResizableBehavior::SetWidth" + }, + "parameters": [ + "PuckTrail", + "Resizable", + "=", + "StepLength + 6" + ] + }, + { + "type": { + "value": "ResizableCapability::ResizableBehavior::SetHeight" + }, + "parameters": [ + "PuckTrail", + "Resizable", + "=", + "TrailSettings.Width" + ] + }, + { + "type": { + "value": "SetAngle" + }, + "parameters": [ + "PuckTrail", + "=", + "ToDeg(atan2(Puck.Y() - Puck.TrailLastY, Puck.X() - Puck.TrailLastX))" + ] + }, + { + "type": { + "value": "SetCenter" + }, + "parameters": [ + "PuckTrail", + "=", + "PuckTrail.CenterX", + "=", + "PuckTrail.CenterY" + ] + }, + { + "type": { + "value": "Scene3D::Base3DBehavior::SetZ" + }, + "parameters": [ + "PuckTrail", + "Object3D", + "=", + "3" + ] + } + ] + } + ], + "variables": [ + { + "name": "StepLength", + "type": "number", + "value": 0 + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "Puck", + "TrailLastX", + "=", + "Puck.X()" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "Puck", + "TrailLastY", + "=", + "Puck.Y()" + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Fade segments", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "PuckTrail", + "Life", + "-", + "TimeDelta() / TrailSettings.LifeSeconds" + ] + }, + { + "type": { + "value": "ResizableCapability::ResizableBehavior::SetHeight" + }, + "parameters": [ + "PuckTrail", + "Resizable", + "=", + "TrailSettings.Width * max(0, PuckTrail.Life)" + ] + }, + { + "type": { + "value": "SetCenter" + }, + "parameters": [ + "PuckTrail", + "=", + "PuckTrail.CenterX", + "=", + "PuckTrail.CenterY" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberObjectVariable" + }, + "parameters": [ + "PuckTrail", + "Life", + "<=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "Delete" + }, + "parameters": [ + "PuckTrail", + "" + ] + } + ] + } + ], + "parameters": [] + } + ] + }, + { + "associatedLayout": "Game", + "name": "CameraRig", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Owns the camera outside the Intro (MatchFlow drives it during the Intro): Camera object + mouse parallax + goal shake.", + "comment2": "Parallax: HUD mouse position mapped to -1..1. The shake starts on Goal entry and shows from the next frame." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Intro\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "FollowShare", + "=", + "min(1, CameraSettings.ParallaxFollowSpeed * TimeDelta())" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CameraRig.ParallaxOffsetX", + "=", + "lerp(CameraRig.ParallaxOffsetX, clamp(2 * MouseX(\"HUD\", 0) / SceneWindowWidth() - 1, -1, 1) * CameraSettings.ParallaxX, FollowShare)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CameraRig.ParallaxOffsetY", + "=", + "lerp(CameraRig.ParallaxOffsetY, clamp(2 * MouseY(\"HUD\", 0) / SceneWindowHeight() - 1, -1, 1) * CameraSettings.ParallaxY, FollowShare)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CameraRig.ShakeTimeLeft", + "=", + "max(0, CameraRig.ShakeTimeLeft - TimeDelta())" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ShakeStrength", + "=", + "CameraSettings.ShakeAmplitude * CameraRig.ShakeTimeLeft / CameraSettings.ShakeSeconds" + ] + }, + { + "type": { + "value": "SetCameraCenterX" + }, + "parameters": [ + "", + "=", + "Camera.X() + CameraRig.ParallaxOffsetX + RandomFloatInRange(-1, 1) * ShakeStrength", + "\"\"", + "0" + ] + }, + { + "type": { + "value": "SetCameraCenterY" + }, + "parameters": [ + "", + "=", + "Camera.Y() + CameraRig.ParallaxOffsetY + RandomFloatInRange(-1, 1) * ShakeStrength", + "\"\"", + "0" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraZ" + }, + "parameters": [ + "", + "=", + "Camera.Z() + RandomFloatInRange(-1, 1) * ShakeStrength * 0.5", + "\"\"", + "0" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraRotationX" + }, + "parameters": [ + "", + "=", + "Camera.Object3D::RotationX()", + "\"\"", + "0" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraRotationY" + }, + "parameters": [ + "", + "=", + "Camera.Object3D::RotationY()", + "\"\"", + "0" + ] + }, + { + "type": { + "value": "SetCameraAngle" + }, + "parameters": [ + "", + "=", + "Camera.Angle()", + "\"\"", + "0" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Goal\"" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CameraRig.ShakeTimeLeft", + "=", + "CameraSettings.ShakeSeconds" + ] + } + ] + } + ], + "variables": [ + { + "name": "FollowShare", + "type": "number", + "value": 0 + }, + { + "name": "ShakeStrength", + "type": "number", + "value": 0 + } + ] + } + ] + }, + { + "associatedLayout": "Menu", + "name": "OptionsMenu", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Linked in both the Menu and Game scenes.", + "comment2": "Settings persisted in storage AirHockey (Volume, MalletSensitivity). UI_OptionsModal and OptionsButton are global objects; the modal hides itself on the Modal layer (no external layout)." + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Settings loading", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Settings.IsLoaded", + "False", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "Settings.IsLoaded", + "True", + "" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "GroupExists" + }, + "parameters": [ + "\"AirHockey\"", + "\"Volume\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "ReadNumberFromStorage" + }, + "parameters": [ + "\"AirHockey\"", + "\"Volume\"", + "", + "Settings.Volume" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "GroupExists" + }, + "parameters": [ + "\"AirHockey\"", + "\"MalletSensitivity\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "ReadNumberFromStorage" + }, + "parameters": [ + "\"AirHockey\"", + "\"MalletSensitivity\"", + "", + "Settings.MalletSensitivity" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "SceneJustBegins" + }, + "parameters": [ + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetGlobalVolume" + }, + "parameters": [ + "", + "=", + "Settings.Volume" + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Options window", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::IsClicked" + }, + "parameters": [ + "OptionsButton", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "AirHockeyUI::UI_OptionsModal::Open" + }, + "parameters": [ + "UI_OptionsModal", + "Settings.Volume", + "Settings.MalletSensitivity", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "KeyFromTextJustPressed" + }, + "parameters": [ + "", + "\"Escape\"" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "AirHockeyUI::UI_OptionsModal::IsOpen" + }, + "parameters": [ + "UI_OptionsModal", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "AirHockeyUI::UI_OptionsModal::Close" + }, + "parameters": [ + "UI_OptionsModal", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [ + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::IsActivated" + }, + "parameters": [ + "OptionsButton", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "AirHockeyUI::UI_OptionsModal::Open" + }, + "parameters": [ + "UI_OptionsModal", + "Settings.Volume", + "Settings.MalletSensitivity", + "" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "BACK, shown only in the match, leaves it for the team menu.", + "comment2": "Pointer lock released and time scale reset before the scene change; the Menu scene stops the match sounds at startup. Hidden in Menu, so the condition never fires there." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "AirHockeyUI::UI_OptionsModal::IsBackClicked" + }, + "parameters": [ + "UI_OptionsModal", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "MousePointerLock::ExitPointerLock" + }, + "parameters": [ + "", + "" + ] + }, + { + "type": { + "value": "ChangeTimeScale" + }, + "parameters": [ + "", + "1" + ] + }, + { + "type": { + "value": "Scene" + }, + "parameters": [ + "", + "\"Menu\"", + "yes" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "AirHockeyUI::UI_OptionsModal::IsOpen" + }, + "parameters": [ + "UI_OptionsModal", + "" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "UI_OptionsModal.Volume()", + "!=", + "Settings.Volume" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Settings.Volume", + "=", + "UI_OptionsModal.Volume()" + ] + }, + { + "type": { + "value": "SetGlobalVolume" + }, + "parameters": [ + "", + "=", + "Settings.Volume" + ] + }, + { + "type": { + "value": "EcrireFichierExp" + }, + "parameters": [ + "\"AirHockey\"", + "\"Volume\"", + "Settings.Volume" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "UI_OptionsModal.Sensitivity()", + "!=", + "Settings.MalletSensitivity" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Settings.MalletSensitivity", + "=", + "UI_OptionsModal.Sensitivity()" + ] + }, + { + "type": { + "value": "EcrireFichierExp" + }, + "parameters": [ + "\"AirHockey\"", + "\"MalletSensitivity\"", + "Settings.MalletSensitivity" + ] + } + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Pause while the options window is open", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Trigger once: written only on change. The not-open branch also fires on the first frame, which hides the Modal layer.", + "comment2": "Modal layer hidden in the editor too (both scenes). Time scale 0 freezes timers, physics and TimeDelta movement." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "AirHockeyUI::UI_OptionsModal::IsOpen" + }, + "parameters": [ + "UI_OptionsModal", + "" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "ChangeTimeScale" + }, + "parameters": [ + "", + "0" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "OptionsButton", + "no", + "" + ] + }, + { + "type": { + "value": "ShowLayer" + }, + "parameters": [ + "", + "\"Modal\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "AirHockeyUI::UI_OptionsModal::IsOpen" + }, + "parameters": [ + "UI_OptionsModal", + "" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "ChangeTimeScale" + }, + "parameters": [ + "", + "1" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "OptionsButton", + "yes", + "" + ] + }, + { + "type": { + "value": "HideLayer" + }, + "parameters": [ + "", + "\"Modal\"" + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Screen layout", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "On wide screens the game widens its resolution (adaptWidth) instead of black bars: UI layers keep their camera on the 1920x1080 design centre.", + "comment2": "Modal scrims extend far past 1920x1080 in their variants to cover any width. Layers missing in a scene are ignored." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetCameraCenterX" + }, + "parameters": [ + "", + "=", + "960", + "\"HUD\"", + "0" + ] + }, + { + "type": { + "value": "SetCameraCenterY" + }, + "parameters": [ + "", + "=", + "540", + "\"HUD\"", + "0" + ] + }, + { + "type": { + "value": "SetCameraCenterX" + }, + "parameters": [ + "", + "=", + "960", + "\"Modal\"", + "0" + ] + }, + { + "type": { + "value": "SetCameraCenterY" + }, + "parameters": [ + "", + "=", + "540", + "\"Modal\"", + "0" + ] + }, + { + "type": { + "value": "SetCameraCenterX" + }, + "parameters": [ + "", + "=", + "960", + "\"ResultMenu\"", + "0" + ] + }, + { + "type": { + "value": "SetCameraCenterY" + }, + "parameters": [ + "", + "=", + "540", + "\"ResultMenu\"", + "0" + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Stadium ambience", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Sound actions only take a fixed file name: one event per track. New track = AmbientN.mp3 resource + Ambience.TrackCount + one Track = N event.", + "comment2": "Globals Ambience.Channel (5), Volume, TrackCount (3). This sheet is linked in Menu and Game, so the ambience runs in both." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "SoundPlaying" + }, + "parameters": [ + "", + "Ambience.Channel" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Track", + "=", + "RandomInRange(1, Ambience.TrackCount)" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "Track", + "=", + "1" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "Ambient1.mp3", + "Ambience.Channel", + "no", + "Ambience.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "Track", + "=", + "2" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "Ambient2.mp3", + "Ambience.Channel", + "no", + "Ambience.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "Track", + "=", + "3" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "Ambient3.mp3", + "Ambience.Channel", + "no", + "Ambience.Volume", + "1" + ] + } + ] + } + ], + "variables": [ + { + "name": "Track", + "type": "number", + "value": 0 + } + ] + } + ], + "parameters": [] + } + ] + }, + { + "associatedLayout": "Game", + "name": "PowerUps", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "This sheet is linked after PlayerMallet and OpponentAI: FREEZE sets the mallet speed to 0 after they moved the mallets.", + "comment2": "Match.LastHitter is written by PuckAndSounds on each new touch. Reads Match.State, never writes it. Tuning: scene structure PowerUps." + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Reset at kickoff", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Kickoff\"" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "Delete" + }, + "parameters": [ + "PowerUpTokens", + "" + ] + }, + { + "type": { + "value": "Delete" + }, + "parameters": [ + "GoalShield", + "" + ] + }, + { + "type": { + "value": "Delete" + }, + "parameters": [ + "GoalShieldIcon", + "" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "Mallets", + "Effects.BigSeconds", + "=", + "0" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "Mallets", + "Effects.FrozenSeconds", + "=", + "0" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "PowerUps.TurboSecondsLeft", + "=", + "0" + ] + }, + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Match.LastHitter", + "=", + "\"\"" + ] + }, + { + "type": { + "value": "ResetTimer" + }, + "parameters": [ + "", + "\"PowerUpSpawn\"" + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Tokens", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "3D boxes are created by their top-left corner, hence the half-size offsets in the Create actions. They have no opacity action: the ring pulses by swapping its front texture among PowerUpRing100/80/60/40/25.", + "comment2": "CreateByName picks PowerUp in group PowerUpTokens. Ring pieces with Step >= RingSegments x remaining share are deleted (clock)." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Playing\"" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "CompareTimer" + }, + "parameters": [ + "", + "\"PowerUpSpawn\"", + ">", + "PowerUps.SpawnSeconds" + ] + }, + { + "type": { + "value": "SceneInstancesCount" + }, + "parameters": [ + "", + "PowerUpTokens", + "=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "CreateByName" + }, + "parameters": [ + "", + "PowerUpTokens", + "\"PowerUp\" + PowerUps.Kinds[RandomInRange(0, VariableChildCount(PowerUps.Kinds) - 1)]", + "RandomInRange(Field.Left + 60, Field.Right - 170)", + "RandomInRange(Field.Top + 180, Field.Bottom - 290)", + "\"\"" + ] + }, + { + "type": { + "value": "Scene3D::Base3DBehavior::SetZ" + }, + "parameters": [ + "PowerUpTokens", + "Object3D", + "=", + "2" + ] + }, + { + "type": { + "value": "ResetObjectTimer" + }, + "parameters": [ + "PowerUpTokens", + "\"Life\"" + ] + }, + { + "type": { + "value": "PlaySound" + }, + "parameters": [ + "", + "PowerUpSpawn.aac", + "", + "60", + "1" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Repeat", + "repeatExpression": "PowerUps.RingSegments", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "SegmentAngle", + "=", + "-90 + 360 * (SegmentIndex + 0.5) / PowerUps.RingSegments" + ] + }, + { + "type": { + "value": "Create" + }, + "parameters": [ + "", + "PowerUpRingSegment", + "PowerUpTokens.CenterX() + cos(ToRad(SegmentAngle)) * PowerUps.RingRadius - 6", + "PowerUpTokens.CenterY() + sin(ToRad(SegmentAngle)) * PowerUps.RingRadius - 3", + "" + ] + }, + { + "type": { + "value": "SetAngle" + }, + "parameters": [ + "PowerUpRingSegment", + "=", + "SegmentAngle + 90" + ] + }, + { + "type": { + "value": "Scene3D::Base3DBehavior::SetZ" + }, + "parameters": [ + "PowerUpRingSegment", + "Object3D", + "=", + "7" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "PowerUpRingSegment", + "Step", + "=", + "SegmentIndex" + ] + } + ], + "variables": [ + { + "name": "SegmentIndex", + "type": "number", + "value": 0 + }, + { + "name": "SegmentAngle", + "type": "number", + "value": 0 + } + ], + "loopIndexVariable": "SegmentIndex" + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetAngle" + }, + "parameters": [ + "PowerUpTokens", + "+", + "90 * TimeDelta()" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "CompareObjectTimer" + }, + "parameters": [ + "PowerUpTokens", + "\"Life\"", + ">", + "PowerUps.LifeSeconds" + ] + } + ], + "actions": [ + { + "type": { + "value": "Delete" + }, + "parameters": [ + "PowerUpTokens", + "" + ] + }, + { + "type": { + "value": "ResetTimer" + }, + "parameters": [ + "", + "\"PowerUpSpawn\"" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "SceneInstancesCount" + }, + "parameters": [ + "", + "PowerUpTokens", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "RemainingShare", + "=", + "clamp(1 - PowerUpTokens.ObjectTimerElapsedTime(\"Life\") / PowerUps.LifeSeconds, 0, 1)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "BlinkSpeed", + "=", + "PowerUps.RingBlinkSpeed" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberObjectVariable" + }, + "parameters": [ + "PowerUpRingSegment", + "Step", + ">=", + "PowerUps.RingSegments * RemainingShare" + ] + } + ], + "actions": [ + { + "type": { + "value": "Delete" + }, + "parameters": [ + "PowerUpRingSegment", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "RemainingShare", + "<", + "PowerUps.RingWarningShare" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "BlinkSpeed", + "=", + "PowerUps.RingBlinkSpeedWarning" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Brightness", + "=", + "abs(cos(TimeFromStart() * BlinkSpeed))" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "Brightness", + ">", + "0.8" + ] + } + ], + "actions": [ + { + "type": { + "value": "Scene3D::Cube3DObject::SetFaceResource" + }, + "parameters": [ + "PowerUpRingSegment", + "\"front\"", + "PowerUpRing100.png" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "Brightness", + ">", + "0.6" + ] + } + ], + "actions": [ + { + "type": { + "value": "Scene3D::Cube3DObject::SetFaceResource" + }, + "parameters": [ + "PowerUpRingSegment", + "\"front\"", + "PowerUpRing80.png" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "Brightness", + ">", + "0.4" + ] + } + ], + "actions": [ + { + "type": { + "value": "Scene3D::Cube3DObject::SetFaceResource" + }, + "parameters": [ + "PowerUpRingSegment", + "\"front\"", + "PowerUpRing60.png" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "Brightness", + ">", + "0.2" + ] + } + ], + "actions": [ + { + "type": { + "value": "Scene3D::Cube3DObject::SetFaceResource" + }, + "parameters": [ + "PowerUpRingSegment", + "\"front\"", + "PowerUpRing40.png" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [], + "actions": [ + { + "type": { + "value": "Scene3D::Cube3DObject::SetFaceResource" + }, + "parameters": [ + "PowerUpRingSegment", + "\"front\"", + "PowerUpRing25.png" + ] + } + ] + } + ], + "variables": [ + { + "name": "RemainingShare", + "type": "number", + "value": 1 + }, + { + "name": "BlinkSpeed", + "type": "number", + "value": 4 + }, + { + "name": "Brightness", + "type": "number", + "value": 1 + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [], + "actions": [ + { + "type": { + "value": "Delete" + }, + "parameters": [ + "PowerUpRingSegment", + "" + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Pickup", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Kind = the token object name without its \"PowerUp\" prefix (7 letters). Only one token exists at a time, so the PowerUpTokens expressions read that one.", + "comment2": "Announcement hidden after PowerUps.MessageSeconds (scene timer PowerUpMessage)." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Playing\"" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "StringVariable" + }, + "parameters": [ + "Match.LastHitter", + "=", + "\"\"" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "DistanceBetweenPositions(Puck.X(), Puck.Y(), PowerUpTokens.CenterX(), PowerUpTokens.CenterY())", + "<", + "PowerUps.PickupRadius" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Kind", + "=", + "SubStr(PowerUpTokens.ObjectName(), 7, 20)" + ] + }, + { + "type": { + "value": "Delete" + }, + "parameters": [ + "PowerUpTokens", + "" + ] + }, + { + "type": { + "value": "ResetTimer" + }, + "parameters": [ + "", + "\"PowerUpSpawn\"" + ] + }, + { + "type": { + "value": "PlaySound" + }, + "parameters": [ + "", + "PowerUpPickup.aac", + "", + "85", + "1" + ] + }, + { + "type": { + "value": "AirHockeyUI::UI_Announcement::ShowMessage" + }, + "parameters": [ + "UI_Announcement", + "PowerUps.Labels[Kind]", + "" + ] + }, + { + "type": { + "value": "ResetTimer" + }, + "parameters": [ + "", + "\"PowerUpMessage\"" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Kind", + "=", + "\"BigMallet\"" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.LastHitter", + "=", + "\"MalletPlayer\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletPlayer", + "Effects.BigSeconds", + "=", + "PowerUps.EffectSeconds" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "Effects.BigSeconds", + "=", + "PowerUps.EffectSeconds" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Kind", + "=", + "\"Freeze\"" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.LastHitter", + "=", + "\"MalletPlayer\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletOpponent", + "Effects.FrozenSeconds", + "=", + "PowerUps.FreezeSeconds" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "MalletPlayer", + "Effects.FrozenSeconds", + "=", + "PowerUps.FreezeSeconds" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Kind", + "=", + "\"Turbo\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "PowerUps.TurboSecondsLeft", + "=", + "PowerUps.EffectSeconds" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityX" + }, + "parameters": [ + "Puck", + "Physics3D", + "*", + "PowerUps.TurboFactor" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityY" + }, + "parameters": [ + "Puck", + "Physics3D", + "*", + "PowerUps.TurboFactor" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Kind", + "=", + "\"Shield\"" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "The last event sets up every shield and icon of the scene, not only the new ones: fine because only one shield can exist at a time (a shield lasts less than the delay between two tokens).", + "comment2": "Create picking is not shared with sibling events. Keep PowerUps.EffectSeconds < SpawnSeconds, or move the setup into each Create branch." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringObjectVariable" + }, + "parameters": [ + "GoalShield", + "Owner", + "=", + "Match.LastHitter" + ] + } + ], + "actions": [ + { + "type": { + "value": "Delete" + }, + "parameters": [ + "GoalShield", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringObjectVariable" + }, + "parameters": [ + "GoalShieldIcon", + "Owner", + "=", + "Match.LastHitter" + ] + } + ], + "actions": [ + { + "type": { + "value": "Delete" + }, + "parameters": [ + "GoalShieldIcon", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.LastHitter", + "=", + "\"MalletPlayer\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "Create" + }, + "parameters": [ + "", + "GoalShield", + "Field.CenterX - 130", + "Field.Bottom - 24", + "" + ] + }, + { + "type": { + "value": "Create" + }, + "parameters": [ + "", + "GoalShieldIcon", + "Field.CenterX - 55", + "Field.Bottom - 55", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [], + "actions": [ + { + "type": { + "value": "Create" + }, + "parameters": [ + "", + "GoalShield", + "Field.CenterX - 130", + "Field.Top", + "" + ] + }, + { + "type": { + "value": "Create" + }, + "parameters": [ + "", + "GoalShieldIcon", + "Field.CenterX - 55", + "Field.Top - 55", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Scene3D::Base3DBehavior::SetZ" + }, + "parameters": [ + "GoalShield", + "Object3D", + "=", + "0" + ] + }, + { + "type": { + "value": "SetStringObjectVariable" + }, + "parameters": [ + "GoalShield", + "Owner", + "=", + "Match.LastHitter" + ] + }, + { + "type": { + "value": "ResetObjectTimer" + }, + "parameters": [ + "GoalShield", + "\"Life\"" + ] + }, + { + "type": { + "value": "Scene3D::Base3DBehavior::SetZ" + }, + "parameters": [ + "GoalShieldIcon", + "Object3D", + "=", + "PowerUps.ShieldIconZ" + ] + }, + { + "type": { + "value": "Scene3D::Base3DBehavior::SetRotationX" + }, + "parameters": [ + "GoalShieldIcon", + "Object3D", + "=", + "PowerUps.ShieldIconTilt" + ] + }, + { + "type": { + "value": "SetStringObjectVariable" + }, + "parameters": [ + "GoalShieldIcon", + "Owner", + "=", + "Match.LastHitter" + ] + }, + { + "type": { + "value": "ResetObjectTimer" + }, + "parameters": [ + "GoalShieldIcon", + "\"Life\"" + ] + } + ] + } + ] + } + ], + "variables": [ + { + "name": "Kind", + "type": "string", + "value": "" + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "AirHockeyUI::UI_Announcement::IsShowing" + }, + "parameters": [ + "UI_Announcement", + "" + ] + }, + { + "type": { + "value": "CompareTimer" + }, + "parameters": [ + "", + "\"PowerUpMessage\"", + ">", + "PowerUps.MessageSeconds" + ] + } + ], + "actions": [ + { + "type": { + "value": "AirHockeyUI::UI_Announcement::HideMessage" + }, + "parameters": [ + "UI_Announcement", + "" + ] + } + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Running powers", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Two opposite conditions instead of an Else: each mallet of the Mallets group is tested on its own, and the \"<= 0\" event must also run on the frame the countdown ends.", + "comment2": "Else is not per-instance with group picking. Actions on Mallets run per instance with its own Effects." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberObjectVariable" + }, + "parameters": [ + "Mallets", + "Effects.BigSeconds", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "Mallets", + "Effects.BigSeconds", + "-", + "TimeDelta()" + ] + }, + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "Mallets", + "Radius", + "=", + "Field.MalletRadius * PowerUps.BigScale" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberObjectVariable" + }, + "parameters": [ + "Mallets", + "Effects.BigSeconds", + "<=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "Mallets", + "Radius", + "=", + "Field.MalletRadius" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ScalableCapability::ScalableBehavior::SetValue" + }, + "parameters": [ + "Mallets", + "Scale", + "=", + "Mallets.Radius / Field.MalletRadius" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberObjectVariable" + }, + "parameters": [ + "Mallets", + "Effects.FrozenSeconds", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberObjectVariable" + }, + "parameters": [ + "Mallets", + "Effects.FrozenSeconds", + "-", + "TimeDelta()" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityX" + }, + "parameters": [ + "Mallets", + "Physics3D", + "=", + "0" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityY" + }, + "parameters": [ + "Mallets", + "Physics3D", + "=", + "0" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "PowerUps.TurboSecondsLeft", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "PowerUps.TurboSecondsLeft", + "-", + "TimeDelta()" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "PowerUps.PuckSpeedCap", + "=", + "PowerUps.TurboMaxSpeed" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "PowerUps.TurboSecondsLeft", + "<=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "PowerUps.PuckSpeedCap", + "=", + "Tuning.Puck.MaxSpeed" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "CompareObjectTimer" + }, + "parameters": [ + "GoalShield", + "\"Life\"", + ">", + "PowerUps.EffectSeconds" + ] + } + ], + "actions": [ + { + "type": { + "value": "Delete" + }, + "parameters": [ + "GoalShield", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "CompareObjectTimer" + }, + "parameters": [ + "GoalShieldIcon", + "\"Life\"", + ">", + "PowerUps.EffectSeconds" + ] + } + ], + "actions": [ + { + "type": { + "value": "Delete" + }, + "parameters": [ + "GoalShieldIcon", + "" + ] + } + ] + } + ], + "parameters": [] + } + ] + }, + { + "associatedLayout": "Game", + "name": "Commentator", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "One line at a time: the triggers only queue a line in Commentator.PendingLine, and 'Commentator voice' says it once the channel is free, or drops it when it waited too long. Big moments (first kickoff, near miss, goal, end of the match) replace the queued line; small reactions wait for an empty queue.", + "comment2": "NewHitBy/NewHitSpeed are written by PuckAndSounds on the first frame of each touch, cleared here. Random lines come from the Commentator.Lines arrays." + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Commentator triggers", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Commentator.HitCooldown", + "-", + "TimeDelta()" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Commentator.PendingTimeLeft", + "-", + "TimeDelta()" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Kickoff\"" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Commentator.BouncesSinceHit", + "=", + "0" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Commentator.PlayerTouchesInRally", + "=", + "0" + ] + }, + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "Commentator.NearMissArmed", + "True", + "" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Commentator.IdleSeconds", + "=", + "0" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Match.ScorePlayer + Match.ScoreOpponent", + "=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"03_go_go_go\"" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Commentator.PendingTimeLeft", + "=", + "3" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.LastScorer", + "=", + "\"Opponent\"" + ] + }, + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"05_here_we_go_again\"" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Commentator.PendingTimeLeft", + "=", + "3" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.NewHitBy", + "!=", + "\"\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Commentator.BouncesSinceHit", + "=", + "0" + ] + }, + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "Commentator.NearMissArmed", + "True", + "" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.NewHitBy", + "=", + "\"MalletOpponent\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Commentator.PlayerTouchesInRally", + "=", + "0" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.NewHitBy", + "=", + "\"MalletPlayer\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Commentator.PlayerTouchesInRally", + "+", + "1" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Playing\"" + ] + }, + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "Commentator.HitCooldown", + "<=", + "0" + ] + }, + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"\"" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Puck.Y()", + ">", + "Field.Bottom - Commentator.SaveZoneHeight" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"08_nice\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "Commentator.NewHitSpeed", + ">=", + "Commentator.StrongHitSpeed" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "RandomFloat(1)", + "<", + "Commentator.HitChance" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "Commentator.Lines.StrongHit[RandomInRange(0, VariableChildCount(Commentator.Lines.StrongHit) - 1)]" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "RandomFloat(1)", + "<", + "Commentator.HitChance * 0.5" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "Commentator.Lines.Hit[RandomInRange(0, VariableChildCount(Commentator.Lines.Hit) - 1)]" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "!=", + "\"\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Commentator.PendingTimeLeft", + "=", + "1" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Commentator.HitCooldown", + "=", + "Commentator.HitCooldownSeconds" + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Commentator.NewHitBy", + "=", + "\"\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Playing\"" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "The puck bounced on a side wall when its sideways speed changes sign. A player goal with no bounce since the player's touch is 'nothing but net'.", + "comment2": "Compares with Commentator.LastVelocityX (last frame), stored after this block. A touch resets BouncesSinceHit." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Puck.Physics3D::LinearVelocityX() * Commentator.LastVelocityX", + "<", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Commentator.BouncesSinceHit", + "+", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Commentator.NearMissArmed", + "True", + "" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "abs(Puck.X() - Field.CenterX)", + ">", + "Field.GoalHalfWidth" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "abs(Puck.X() - Field.CenterX)", + "<", + "Field.GoalHalfWidth + Commentator.NearMissPostWidth" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::LinearVelocityLength" + }, + "parameters": [ + "Puck", + "Physics3D", + ">", + "Commentator.NearMissMinSpeed" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.LastHitter", + "=", + "\"MalletPlayer\"" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Puck.Y()", + "<", + "Field.Top + Field.PuckRadius + 15" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "NearMissLine", + "=", + "Commentator.Lines.NearMiss[RandomInRange(0, VariableChildCount(Commentator.Lines.NearMiss) - 1)]" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.LastHitter", + "=", + "\"MalletOpponent\"" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Puck.Y()", + ">", + "Field.Bottom - Field.PuckRadius - 15" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "NearMissLine", + "=", + "Commentator.Lines.OpponentNearMiss[RandomInRange(0, VariableChildCount(Commentator.Lines.OpponentNearMiss) - 1)]" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "NearMissLine", + "!=", + "\"\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "Commentator.NearMissArmed", + "False", + "" + ] + }, + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "NearMissLine" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Commentator.PendingTimeLeft", + "=", + "1.5" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Commentator.HitCooldown", + "=", + "Commentator.HitCooldownSeconds" + ] + }, + { + "type": { + "value": "PlaySound" + }, + "parameters": [ + "", + "CrowdNearMiss.mp3", + "no", + "40", + "1" + ] + } + ] + } + ], + "variables": [ + { + "name": "NearMissLine", + "type": "string", + "value": "" + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "After an idle line, IdleSeconds goes negative so the line is not repeated at once. While the puck moves, the Else keeps that negative delay instead of resetting it.", + "comment2": "min(0, IdleSeconds) resets a positive count only. IdleRepeatSeconds = delay before the next idle line." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Physics3D::Physics3DBehavior::LinearVelocityLength" + }, + "parameters": [ + "Puck", + "Physics3D", + "<", + "Commentator.IdleSpeed" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Commentator.IdleSeconds", + "+", + "TimeDelta()" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Commentator.IdleSeconds", + "=", + "min(0, Commentator.IdleSeconds)" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "Commentator.IdleSeconds", + ">=", + "Commentator.IdleLineSeconds" + ] + }, + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "Commentator.Lines.Idle[RandomInRange(0, VariableChildCount(Commentator.Lines.Idle) - 1)]" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Commentator.PendingTimeLeft", + "=", + "1" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Commentator.IdleSeconds", + "=", + "-Commentator.IdleRepeatSeconds" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Stored in every match state, outside the Playing block: a speed left over from before a goal would count a fake bounce on the first frame of play.", + "comment2": "Must stay after the Playing block: the bounce test reads last frame's value." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Commentator.LastVelocityX", + "=", + "Puck.Physics3D::LinearVelocityX()" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Goal\"" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Commentator.PendingTimeLeft", + "=", + "5" + ] + }, + { + "type": { + "value": "StopSoundChannel" + }, + "parameters": [ + "", + "Commentator.Channel" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.LastScorer", + "=", + "\"Player\"" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "Commentator.BouncesSinceHit", + "=", + "0" + ] + }, + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.LastHitter", + "=", + "\"MalletPlayer\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"10_nothing_but_net\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "Commentator.PlayerTouchesInRally", + ">=", + "Commentator.EffortTouches" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"13_scored\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "Commentator.Lines.PlayerGoal[RandomInRange(0, VariableChildCount(Commentator.Lines.PlayerGoal) - 1)]" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.LastScorer", + "=", + "\"Opponent\"" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.LastHitter", + "=", + "\"MalletPlayer\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "Commentator.Lines.OwnGoal[RandomInRange(0, VariableChildCount(Commentator.Lines.OwnGoal) - 1)]" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"12_oh_noo\"" + ] + } + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Match.State", + "=", + "\"Finished\"" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Commentator.PendingTimeLeft", + "=", + "8" + ] + }, + { + "type": { + "value": "StopSoundChannel" + }, + "parameters": [ + "", + "Commentator.Channel" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Match.ScorePlayer", + ">", + "Match.ScoreOpponent" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"01_good_game\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "Match.ScorePlayer", + ">=", + "3" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"11_not_bad\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "Match.ScorePlayer", + ">=", + "1" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"16_what_was_the_plan\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"12_oh_noo\"" + ] + } + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Commentator voice", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "!=", + "\"\"" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "Commentator.PendingTimeLeft", + "<=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [ + { + "type": { + "inverted": true, + "value": "SoundPlaying" + }, + "parameters": [ + "", + "Commentator.Channel" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Sound actions only accept a fixed file name: one event per line, on purpose. French recordings when Commentator.Language is \"fr\", English otherwise. Both lists are folded: unfold them to add a line.", + "comment2": "New line = one event in each branch; new language = one more branch. No JS; the browser language is not read." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.Language", + "=", + "\"fr\"" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"01_good_game\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/fr/01_good_game.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"02_goooooal\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/fr/02_goooooal.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"03_go_go_go\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/fr/03_go_go_go.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"04_great\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/fr/04_great.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"05_here_we_go_again\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/fr/05_here_we_go_again.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"06_lets_gooo\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/fr/06_lets_gooo.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"07_nice\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/fr/07_nice.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"08_nice\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/fr/08_nice.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"09_nooo\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/fr/09_nooo.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"10_nothing_but_net\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/fr/10_nothing_but_net.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"11_not_bad\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/fr/11_not_bad.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"12_oh_noo\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/fr/12_oh_noo.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"13_scored\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/fr/13_scored.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"14_thats_great\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/fr/14_thats_great.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"15_thats_terrible\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/fr/15_thats_terrible.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"16_what_was_the_plan\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/fr/16_what_was_the_plan.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"17_yeahh\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/fr/17_yeahh.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"18_yikes\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/fr/18_yikes.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + } + ] + }, + { + "folded": true, + "type": "BuiltinCommonInstructions::Else", + "conditions": [], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"01_good_game\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/default/01_good_game.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"02_goooooal\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/default/02_goooooal.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"03_go_go_go\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/default/03_go_go_go.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"04_great\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/default/04_great.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"05_here_we_go_again\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/default/05_here_we_go_again.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"06_lets_gooo\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/default/06_lets_gooo.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"07_nice\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/default/07_nice.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"08_nice\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/default/08_nice.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"09_nooo\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/default/09_nooo.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"10_nothing_but_net\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/default/10_nothing_but_net.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"11_not_bad\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/default/11_not_bad.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"12_oh_noo\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/default/12_oh_noo.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"13_scored\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/default/13_scored.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"14_thats_great\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/default/14_thats_great.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"15_thats_terrible\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/default/15_thats_terrible.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"16_what_was_the_plan\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/default/16_what_was_the_plan.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"17_yeahh\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/default/17_yeahh.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"18_yikes\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlaySoundOnChannel" + }, + "parameters": [ + "", + "voice/default/18_yikes.mp3", + "Commentator.Channel", + "no", + "Commentator.Volume", + "1" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Commentator.PendingLine", + "=", + "\"\"" + ] + } + ] + } + ] + } + ] + } + ], + "parameters": [] + } + ] + }, + { + "associatedLayout": "Game", + "name": "CountryModels", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Only the two countries of the match are loaded: Mallet and Flag use the \"preload manually\" resource setting. The France / Canada instances placed in the editor are hidden markers: their place is read, then they are deleted.", + "comment2": "AreObjectAssetsLoaded is never true without resourcesPreloading = manually. MalletPlayer / MalletOpponent = hidden gameplay bodies on the Collisions layer (MalletBody.glb, mallet bounding box), copied by the skins." + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Load", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "SceneJustBegins" + }, + "parameters": [ + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "LoadObjectAssets" + }, + "parameters": [ + "", + "\"Mallet\" + Match.PlayerCountry", + "" + ] + }, + { + "type": { + "value": "LoadObjectAssets" + }, + "parameters": [ + "", + "\"Mallet\" + Match.OpponentCountry", + "" + ] + }, + { + "type": { + "value": "LoadObjectAssets" + }, + "parameters": [ + "", + "\"Flag\" + Match.PlayerCountry", + "" + ] + }, + { + "type": { + "value": "LoadObjectAssets" + }, + "parameters": [ + "", + "\"Flag\" + Match.OpponentCountry", + "" + ] + }, + { + "type": { + "value": "Delete" + }, + "parameters": [ + "MalletSkins", + "" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::ForEach", + "object": "CountryFlags", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CountryModels.FlagSpots[SpotIndex].X", + "=", + "CountryFlags.X()" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CountryModels.FlagSpots[SpotIndex].Y", + "=", + "CountryFlags.Y()" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CountryModels.FlagSpots[SpotIndex].Z", + "=", + "CountryFlags.Object3D::Z()" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CountryModels.FlagSpots[SpotIndex].Angle", + "=", + "CountryFlags.Angle()" + ] + }, + { + "type": { + "value": "Delete" + }, + "parameters": [ + "CountryFlags", + "" + ] + } + ], + "variables": [ + { + "name": "SpotIndex", + "type": "number", + "value": 0 + } + ], + "loopIndexVariable": "SpotIndex" + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Create", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "BooleanVariable" + }, + "parameters": [ + "CountryModels.AreCreated", + "True", + "" + ] + }, + { + "type": { + "value": "AreObjectAssetsLoaded" + }, + "parameters": [ + "", + "\"Mallet\" + Match.PlayerCountry", + "" + ] + }, + { + "type": { + "value": "AreObjectAssetsLoaded" + }, + "parameters": [ + "", + "\"Mallet\" + Match.OpponentCountry", + "" + ] + }, + { + "type": { + "value": "AreObjectAssetsLoaded" + }, + "parameters": [ + "", + "\"Flag\" + Match.PlayerCountry", + "" + ] + }, + { + "type": { + "value": "AreObjectAssetsLoaded" + }, + "parameters": [ + "", + "\"Flag\" + Match.OpponentCountry", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "CountryModels.AreCreated", + "True", + "" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "CreateByName" + }, + "parameters": [ + "", + "MalletSkins", + "\"Mallet\" + Match.PlayerCountry", + "MalletPlayer.X()", + "MalletPlayer.Y()", + "\"\"" + ] + }, + { + "type": { + "value": "SetBooleanObjectVariable" + }, + "parameters": [ + "MalletSkins", + "IsPlayer", + "True", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "CreateByName" + }, + "parameters": [ + "", + "MalletSkins", + "\"Mallet\" + Match.OpponentCountry", + "MalletOpponent.X()", + "MalletOpponent.Y()", + "\"\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Repeat", + "repeatExpression": "VariableChildCount(CountryModels.FlagSpots)", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Country", + "=", + "Match.PlayerCountry" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "CountryModels.FlagSpots[SpotIndex].Y", + "<", + "Field.CenterY" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Country", + "=", + "Match.OpponentCountry" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "CreateByName" + }, + "parameters": [ + "", + "CountryFlags", + "\"Flag\" + Country", + "CountryModels.FlagSpots[SpotIndex].X", + "CountryModels.FlagSpots[SpotIndex].Y", + "\"\"" + ] + }, + { + "type": { + "value": "Scene3D::Base3DBehavior::SetZ" + }, + "parameters": [ + "CountryFlags", + "Object3D", + "=", + "CountryModels.FlagSpots[SpotIndex].Z" + ] + }, + { + "type": { + "value": "SetAngle" + }, + "parameters": [ + "CountryFlags", + "=", + "CountryModels.FlagSpots[SpotIndex].Angle" + ] + } + ] + } + ], + "variables": [ + { + "name": "SpotIndex", + "type": "number", + "value": 0 + }, + { + "name": "Country", + "type": "string", + "value": "" + } + ], + "loopIndexVariable": "SpotIndex" + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Follow the gameplay bodies", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanObjectVariable" + }, + "parameters": [ + "MalletSkins", + "IsPlayer", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetXY" + }, + "parameters": [ + "MalletSkins", + "=", + "MalletPlayer.X()", + "=", + "MalletPlayer.Y()" + ] + }, + { + "type": { + "value": "Scene3D::Base3DBehavior::SetZ" + }, + "parameters": [ + "MalletSkins", + "Object3D", + "=", + "MalletPlayer.Object3D::Z()" + ] + }, + { + "type": { + "value": "ScalableCapability::ScalableBehavior::SetValue" + }, + "parameters": [ + "MalletSkins", + "Scale", + "=", + "MalletPlayer.Scale::Value()" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "BooleanObjectVariable" + }, + "parameters": [ + "MalletSkins", + "IsPlayer", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetXY" + }, + "parameters": [ + "MalletSkins", + "=", + "MalletOpponent.X()", + "=", + "MalletOpponent.Y()" + ] + }, + { + "type": { + "value": "Scene3D::Base3DBehavior::SetZ" + }, + "parameters": [ + "MalletSkins", + "Object3D", + "=", + "MalletOpponent.Object3D::Z()" + ] + }, + { + "type": { + "value": "ScalableCapability::ScalableBehavior::SetValue" + }, + "parameters": [ + "MalletSkins", + "Scale", + "=", + "MalletOpponent.Scale::Value()" + ] + } + ] + } + ], + "parameters": [] + } + ] + } + ], + "externalEventsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "folderName": "Match", + "children": [ + { + "itemName": "MatchFlow" + }, + { + "itemName": "CameraRig" + }, + { + "itemName": "ScoreDisplay" + }, + { + "itemName": "CountryModels" + } + ] + }, + { + "folderName": "Gameplay", + "children": [ + { + "itemName": "PlayerMallet" + }, + { + "itemName": "OpponentAI" + }, + { + "itemName": "PuckAndSounds" + }, + { + "itemName": "PowerUps" + } + ] + }, + { + "folderName": "Atmosphere", + "children": [ + { + "itemName": "StadiumCrowd" + }, + { + "itemName": "PuckTrail" + }, + { + "itemName": "Commentator" + } + ] + }, + { + "folderName": "Menus", + "children": [ + { + "itemName": "OptionsMenu" + } + ] + } + ] + }, + "tests": [ + { + "description": "A bot plays a whole match with the mouse (unlocked pointer path), first to 2 goals so it fits the 20000-frame cap of a test: it keeps the mallet moving, backs off regularly so it never pins the puck, and drives the puck toward the opponent goal until the match ends. Checks the end of match, that the player's mallet hits the puck, that nobody stays still (except under Freeze), that the puck is never blocked, the commentator lines and the applause. Official harness API only (run by the examples CI).", + "lastRunAt": 1793785602935, + "lastRunDurationMs": 17177, + "lastRunFramesExecuted": 3902, + "lastRunStatus": "passed", + "name": "FullMatchSimulation", + "type": "gameplay", + "source": [ + "// Official harness API only: the examples CI runs this test with the stock GDevelop harness.", + "// A full match takes thousands of frames: more than the default 30 s wall-clock budget on a slow CI machine.", + "harness.setTimeoutMs(120000);", + "harness.setRandomSeed(13);", + "await harness.goToScene(\"Game\");", + "const sceneValue = (path) => harness.getSceneVariable(path)?.value;", + "const matchState = () => sceneValue(\"Match.State\");", + "// A test may run 20000 frames at most, and goals are far apart (1 to 2 minutes without a goal happen, the puck", + "// stuck in the AI half): a first-to-5 match took 8000 to more than 18000 frames. The match is played first", + "// to 2, which keeps the whole flow (intro, \"FIRST TO\" and \"MATCH POINT!\" kickoffs, goals, end of match).", + "const goalsToWin = 2;", + "harness.setSceneVariable(\"Match.GoalsToWin\", goalsToWin);", + "const reachedPlaying = await harness.stepUntil(() => matchState() === \"Playing\", { maxFrames: 900 });", + "harness.assert(reachedPlaying, \"The intro and the kickoff lead to Playing\");", + "const fieldLeft = sceneValue(\"Field.Left\"), fieldRight = sceneValue(\"Field.Right\");", + "const fieldCenterX = sceneValue(\"Field.CenterX\"), fieldCenterY = sceneValue(\"Field.CenterY\"), fieldBottom = sceneValue(\"Field.Bottom\");", + "const malletRadius = sceneValue(\"Field.MalletRadius\");", + "const screenWidth = harness.getGameResolutionWidth(), screenHeight = harness.getGameResolutionHeight();", + "const clamp01 = (value) => Math.min(1, Math.max(0, value));", + "// Unlocked pointer path of PlayerMallet (the test never clicks, so the game never asks for the pointer lock):", + "// the whole screen maps onto the player's half, so a field target becomes a screen position.", + "const aimAt = (targetX, targetY) => {", + " const u = clamp01((targetX - (fieldLeft + malletRadius)) / (fieldRight - fieldLeft - 2 * malletRadius));", + " const v = clamp01((targetY - (fieldCenterY + malletRadius)) / (fieldBottom - fieldCenterY - 2 * malletRadius));", + " harness.setMousePositionScreen(u * screenWidth, v * screenHeight);", + "};", + "// Bot: every 2 s it backs off for 0.4 s. A puck the AI mallet contests on the centre line is left alone for", + "// 0.75 s, then driven through toward the middle for 0.75 s (pushing both ways at once only pins it).", + "// Otherwise it gets behind the puck and drives through it toward the opponent goal.", + "// It always sways a little, so it never stands still.", + "let contestedFrames = 0;", + "const botTarget = (frame, puck, player, opponent) => {", + " const towardCentre = puck.x < fieldCenterX ? 1 : -1;", + " const contestedOnCentreLine = puck.y > fieldCenterY - 40 && puck.y < fieldCenterY + 110 && Math.hypot(opponent.x - puck.x, opponent.y - puck.y) < 170;", + " contestedFrames = contestedOnCentreLine ? contestedFrames + 1 : 0;", + " if (frame % 120 < 24) return [puck.x + towardCentre * 160, puck.y + 220];", + " if (puck.y > fieldCenterY - 40) {", + " if (contestedOnCentreLine && contestedFrames % 90 < 45) return [puck.x + towardCentre * 120, puck.y + 260];", + " if (contestedOnCentreLine) return [puck.x + towardCentre * 140, puck.y - 200];", + " if (player.y > puck.y + 20) return [puck.x + (fieldCenterX - puck.x) * 0.35, puck.y - 200];", + " return [puck.x + (player.x < puck.x ? -80 : 80), puck.y + 110];", + " }", + " return [fieldCenterX + Math.sin(frame * 0.05) * 220, 760 + Math.cos(frame * 0.07) * 120];", + "};", + "const snapshotOf = (objectName) => harness.getObjects(objectName, { childrenDepth: 0 })[0];", + "const isFrozen = (snapshot) => (harness.getObjectVariable(snapshot.id, \"Effects.FrozenSeconds\")?.value || 0) > 0;", + "const round = (value) => Math.round(value);", + "const log = [];", + "const stillFrames = { player: 0, opponent: 0, puck: 0 };", + "const maxStillFrames = { player: 0, opponent: 0, puck: 0 };", + "const lastPositions = {};", + "let botFrame = 0;", + "let playerHitThePuck = false;", + "const driveBot = () => {", + " botFrame++;", + " if (sceneValue(\"Match.LastHitter\") === \"MalletPlayer\") playerHitThePuck = true;", + " const puck = snapshotOf(\"Puck\"), player = snapshotOf(\"MalletPlayer\"), opponent = snapshotOf(\"MalletOpponent\");", + " const [targetX, targetY] = botTarget(botFrame, puck, player, opponent);", + " aimAt(targetX + Math.sin(botFrame * 0.3) * 35, targetY + Math.cos(botFrame * 0.27) * 25);", + " const isPlaying = matchState() === \"Playing\";", + " for (const [key, snapshot] of [[\"player\", player], [\"opponent\", opponent], [\"puck\", puck]]) {", + " const last = lastPositions[key];", + " const moved = !last || Math.hypot(snapshot.x - last.x, snapshot.y - last.y) > 0.5;", + " const excused = !isPlaying || (key !== \"puck\" && isFrozen(snapshot));", + " stillFrames[key] = moved || excused ? 0 : stillFrames[key] + 1;", + " maxStillFrames[key] = Math.max(maxStillFrames[key], stillFrames[key]);", + " lastPositions[key] = { x: snapshot.x, y: snapshot.y };", + " }", + " if (botFrame % 300 === 0) log.push(`${botFrame / 60}s ${matchState()} ${sceneValue(\"Match.ScorePlayer\")}-${sceneValue(\"Match.ScoreOpponent\")} P(${round(puck.x)},${round(puck.y)}) me(${round(player.x)},${round(player.y)}) ai(${round(opponent.x)},${round(opponent.y)}) ${harness.getObjectVariable(opponent.id, \"State\")?.value}`);", + "};", + "// 5 minutes of match at most: with the intro, it stays under the 20000 frames a test may run.", + "const finished = await harness.stepUntil(() => matchState() === \"Finished\", { maxFrames: 60 * 60 * 5, onFrame: driveBot });", + "const scorePlayer = sceneValue(\"Match.ScorePlayer\");", + "const scoreOpponent = sceneValue(\"Match.ScoreOpponent\");", + "await harness.stepFrames(30);", + "const voiceLines = harness.getPlayedSounds().filter((played) => played.sound.startsWith(\"voice/\")).map((played) => played.sound.replace(\"voice/default/\", \"\").replace(\".mp3\", \"\"));", + "console.log(\"Every 5 s:\\n\" + log.join(\"\\n\"));", + "harness.assert(finished, \"Match finished within 5 minutes (\" + botFrame + \" frames): \" + scorePlayer + \" - \" + scoreOpponent);", + "harness.assert(Math.max(scorePlayer, scoreOpponent) === goalsToWin, \"The winner reached Match.GoalsToWin (\" + goalsToWin + \")\");", + "// Who wins a first-to-2 match is a coin toss (the AI can win 2 - 0): the test checks the player's mallet reaches", + "// the puck, not the strength of the bot.", + "harness.assert(playerHitThePuck, \"The player's mallet hit the puck (Match.LastHitter)\");", + "harness.assert(maxStillFrames.player < 30, \"Player mallet always moving outside Freeze (max still \" + maxStillFrames.player + \" frames)\");", + "harness.assert(maxStillFrames.opponent < 130, \"AI mallet never still for 2 s outside Freeze (max still \" + maxStillFrames.opponent + \" frames)\");", + "harness.assert(maxStillFrames.puck < 180, \"Puck never blocked for 3 s (max still \" + maxStillFrames.puck + \" frames)\");", + "harness.assert(voiceLines.length >= 3, \"Commentator spoke during the match: \" + voiceLines.join(\", \"));", + "harness.assert(harness.getPlayedSounds().some((played) => played.sound === \"Applause.mp3\"), \"Applause on goals\");" + ] + } + ], + "testsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "itemName": "FullMatchSimulation" + } + ] + }, + "eventsFunctionsExtensions": [ + { + "author": "", + "category": "User interface", + "dimension": "2D", + "extensionNamespace": "", + "fullName": "Labeled button", + "gdevelopVersion": ">=5.5.230", + "helpPath": "/objects/button", + "iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAyMy4wLjMsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iSWNvbnMiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgMzIgMzIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDMyIDMyOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KCS5zdDB7ZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9DQo8L3N0eWxlPg0KPHBhdGggY2xhc3M9InN0MCIgZD0iTTI5LDIzSDNjLTEuMSwwLTItMC45LTItMlYxMWMwLTEuMSwwLjktMiwyLTJoMjZjMS4xLDAsMiwwLjksMiwydjEwQzMxLDIyLjEsMzAuMSwyMywyOSwyM3oiLz4NCjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0xMywxOUwxMywxOWMtMS4xLDAtMi0wLjktMi0ydi0yYzAtMS4xLDAuOS0yLDItMmgwYzEuMSwwLDIsMC45LDIsMnYyQzE1LDE4LjEsMTQuMSwxOSwxMywxOXoiLz4NCjxsaW5lIGNsYXNzPSJzdDAiIHgxPSIxOCIgeTE9IjEzIiB4Mj0iMTgiIHkyPSIxOSIvPg0KPGxpbmUgY2xhc3M9InN0MCIgeDE9IjIxIiB5MT0iMTMiIHgyPSIxOCIgeTI9IjE3Ii8+DQo8bGluZSBjbGFzcz0ic3QwIiB4MT0iMjEiIHkxPSIxOSIgeDI9IjE5IiB5Mj0iMTYiLz4NCjwvc3ZnPg0K", + "name": "PanelSpriteButton", + "previewIconUrl": "https://resources.gdevelop-app.com/assets/Icons/Line Hero Pack/Master/SVG/Interface Elements/Interface Elements_interface_ui_button_ok_cta_clock_tap.svg", + "shortDescription": "Resizeable button with a label.", + "version": "2.2.1", + "description": [ + "A button that can be used for menus and most labelled buttons of a game. The button can be customized with a background for each state and a label. It handles user interactions and a simple condition can be used to check if it is clicked.", + "", + "There are ready-to-use buttons in the asset-store [menu buttons pack](https://editor.gdevelop.io/?initial-dialog=asset-store&asset-pack=menu-buttons-menu-buttons)." + ], + "origin": { + "identifier": "PanelSpriteButton", + "name": "gdevelop-extension-store" + }, + "tags": [ + "button", + "ui" + ], + "authorIds": [ + "IWykYNRvhCZBN3vEgKEbBPOR3Oc2" + ], + "changelog": [ + { + "version": "2.0.0", + "breaking": "- Buttons now use \"variants\", allowing easy swapping of their visual aspect. You will have to make some adjustments to existing buttons in your project. Follow this [migration documentation](https://wiki.gdevelop.io/gdevelop5/objects/custom-objects-prefab-template/migrate-to-variants/) to do these changes." + } + ], + "dependencies": [], + "globalVariables": [], + "sceneVariables": [], + "eventsFunctions": [ + { + "description": "Check if the events are running for the editor.", + "fullName": "Editor is running", + "functionType": "Condition", + "name": "IsInGameEdition", + "private": true, + "sentence": "Events are running for the editor", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const game = runtimeScene.getGame();\r", + "eventsFunctionContext.returnValue = game.isInGameEdition && game.isInGameEdition();" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "IsInGameEdition" + } + ] + }, + "eventsBasedBehaviors": [ + { + "description": "The finite state machine used internally by the button object.", + "fullName": "Button finite state machine", + "helpPath": "", + "iconUrl": "", + "name": "ButtonFSM", + "objectType": "", + "previewIconUrl": "", + "private": true, + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "doStepPostEvents", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "PanelSpriteButton::IsInGameEdition" + }, + "parameters": [ + "", + "" + ] + } + ], + "actions": [], + "events": [ + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Finite state machine", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "The \"Validated\" state only last one frame." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "State", + "=", + "\"Validated\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "State", + "=", + "\"Idle\"" + ] + } + ] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Check position", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Make sure the cursor position is only checked once per frame." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "MouseIsInside", + "False", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "ShouldCheckHovering", + "True", + "" + ] + }, + { + "type": { + "value": "CollisionPoint" + }, + "parameters": [ + "Object", + "MouseOnlyCursorX(Object.Layer(), 0)", + "MouseOnlyCursorY(Object.Layer(), 0)" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "MouseIsInside", + "True", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Touches are always pressed, so ShouldCheckHovering doesn't matter." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "TouchIsInside", + "False", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "TouchId", + "!=", + "0" + ] + }, + { + "type": { + "value": "CollisionPoint" + }, + "parameters": [ + "Object", + "TouchX(TouchId, Object.Layer(), 0)", + "TouchY(TouchId, Object.Layer(), 0)" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "TouchIsInside", + "True", + "" + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Handle touch start", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "HasAnyTouchOrMouseStarted" + }, + "parameters": [ + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Index", + "=", + "0" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Repeat", + "repeatExpression": "StartedTouchOrMouseCount()", + "conditions": [], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "CollisionPoint" + }, + "parameters": [ + "Object", + "TouchX(StartedTouchOrMouseId(Index), Object.Layer(), 0)", + "TouchY(StartedTouchOrMouseId(Index), Object.Layer(), 0)" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TouchId", + "=", + "StartedTouchOrMouseId(Index)" + ] + }, + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "TouchIsInside", + "True", + "" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Or" + }, + "parameters": [], + "subInstructions": [ + { + "type": { + "value": "PanelSpriteButton::ButtonFSM::PropertyState" + }, + "parameters": [ + "Object", + "Behavior", + "=", + "\"Hovered\"" + ] + }, + { + "type": { + "value": "PanelSpriteButton::ButtonFSM::PropertyState" + }, + "parameters": [ + "Object", + "Behavior", + "=", + "\"Idle\"" + ] + } + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "State", + "=", + "\"PressedInside\"" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Index", + "+", + "1" + ] + } + ] + } + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Apply position changes", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "BooleanVariable" + }, + "parameters": [ + "MouseIsInside", + "True", + "" + ] + }, + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "State", + "=", + "\"Hovered\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "State", + "=", + "\"Idle\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "MouseIsInside", + "True", + "" + ] + }, + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "State", + "=", + "\"Idle\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "State", + "=", + "\"Hovered\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "BooleanVariable" + }, + "parameters": [ + "TouchIsInside", + "True", + "" + ] + }, + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "State", + "=", + "\"PressedInside\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "State", + "=", + "\"PressedOutside\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "TouchIsInside", + "True", + "" + ] + }, + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "State", + "=", + "\"PressedOutside\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "State", + "=", + "\"PressedInside\"" + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Handle touch end", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "HasTouchEnded" + }, + "parameters": [ + "", + "TouchId" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TouchId", + "=", + "0" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "State", + "=", + "\"PressedInside\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "State", + "=", + "\"Validated\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "StringVariable" + }, + "parameters": [ + "State", + "=", + "\"PressedInside\"" + ] + }, + { + "type": { + "inverted": true, + "value": "StringVariable" + }, + "parameters": [ + "State", + "=", + "\"Validated\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "State", + "=", + "\"Idle\"" + ] + } + ] + } + ] + } + ], + "parameters": [] + } + ], + "parameters": [] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PanelSpriteButton::ButtonFSM", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "onDeActivate", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "PanelSpriteButton::ButtonFSM::ResetState" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PanelSpriteButton::ButtonFSM", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Reset the state of the button.", + "fullName": "Reset state", + "functionType": "Action", + "name": "ResetState", + "private": true, + "sentence": "Reset the button state of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "State", + "=", + "\"Idle\"" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TouchId", + "=", + "0" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PanelSpriteButton::ButtonFSM", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Check if the button is not used.", + "fullName": "Is idle", + "functionType": "Condition", + "name": "IsIdle", + "sentence": "_PARAM0_ is idle", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "State", + "=", + "\"Idle\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PanelSpriteButton::ButtonFSM", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Check if the button was just clicked.", + "fullName": "Is clicked", + "functionType": "Condition", + "name": "IsClicked", + "sentence": "_PARAM0_ is clicked", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "State", + "=", + "\"Validated\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PanelSpriteButton::ButtonFSM", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Check if the cursor is hovered over the button.", + "fullName": "Is hovered", + "functionType": "Condition", + "name": "IsHovered", + "sentence": "_PARAM0_ is hovered", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "State", + "=", + "\"Hovered\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PanelSpriteButton::ButtonFSM", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Check if the button is either hovered or pressed but not hovered.", + "fullName": "Is focused", + "functionType": "Condition", + "name": "IsFocused", + "sentence": "_PARAM0_ is focused", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "State", + "=", + "\"Hovered\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "State", + "=", + "\"PressedOutside\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PanelSpriteButton::ButtonFSM", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Check if the button is currently being pressed with mouse or touch.", + "fullName": "Is pressed", + "functionType": "Condition", + "name": "IsPressed", + "sentence": "_PARAM0_ is pressed", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "State", + "=", + "\"PressedInside\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PanelSpriteButton::ButtonFSM", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Check if the button is currently being pressed outside with mouse or touch.", + "fullName": "Is held outside", + "functionType": "Condition", + "name": "IsPressedOutside", + "sentence": "_PARAM0_ is held outside", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "State", + "=", + "\"PressedOutside\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PanelSpriteButton::ButtonFSM", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the touch id that is using the button or 0 if none.", + "fullName": "Touch id", + "functionType": "ExpressionAndCondition", + "name": "TouchId", + "sentence": "the touch id", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "TouchId" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PanelSpriteButton::ButtonFSM", + "type": "behavior" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "doStepPostEvents" + }, + { + "functionName": "onDeActivate" + }, + { + "functionName": "ResetState" + }, + { + "functionName": "IsIdle" + }, + { + "functionName": "IsClicked" + }, + { + "functionName": "IsHovered" + }, + { + "functionName": "IsFocused" + }, + { + "functionName": "IsPressed" + }, + { + "functionName": "IsPressedOutside" + }, + { + "functionName": "TouchId" + } + ] + }, + "propertyDescriptors": [ + { + "value": "true", + "type": "Boolean", + "label": "", + "description": "Should check hovering", + "hidden": true, + "name": "ShouldCheckHovering" + }, + { + "value": "Idle", + "type": "Choice", + "label": "State", + "choices": [ + { + "label": "Idle", + "value": "Idle" + }, + { + "label": "Hovered", + "value": "Hovered" + }, + { + "label": "PressedInside", + "value": "PressedInside" + }, + { + "label": "PressedOutside", + "value": "PressedOutside" + }, + { + "label": "Validated", + "value": "Validated" + } + ], + "hidden": true, + "name": "State" + }, + { + "value": "0", + "type": "Number", + "label": "Touch id", + "hidden": true, + "name": "TouchId" + }, + { + "value": "", + "type": "Boolean", + "label": "Touch is inside", + "hidden": true, + "name": "TouchIsInside" + }, + { + "value": "", + "type": "Boolean", + "label": "Mouse is inside", + "hidden": true, + "name": "MouseIsInside" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "Index" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "propertyName": "ShouldCheckHovering" + }, + { + "propertyName": "State" + }, + { + "propertyName": "TouchId" + }, + { + "propertyName": "TouchIsInside" + }, + { + "propertyName": "MouseIsInside" + }, + { + "propertyName": "Index" + } + ] + } + }, + { + "description": "Change the text style when the button is hovered.", + "fullName": "Hover text style", + "helpPath": "", + "iconUrl": "", + "name": "TextStyleState", + "objectType": "TextObject::Text", + "previewIconUrl": "", + "private": true, + "eventsFunctions": [ + { + "description": "Check if isHovered.", + "fullName": "IsHovered", + "functionType": "Condition", + "name": "IsHovered", + "sentence": "_PARAM0_ isHovered", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsHovered", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "TextObject::Text", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PanelSpriteButton::TextStyleState", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Change if isHovered.", + "fullName": "IsHovered", + "functionType": "Action", + "name": "SetIsHovered", + "sentence": "_PARAM0_ isHovered: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsHovered", + "False", + "" + ] + }, + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "IsHovered", + "True", + "" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "HoverFontSize", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "IdleFontSize", + "=", + "Object.FontSize()" + ] + }, + { + "type": { + "value": "TextObject::Text::SetFontSize" + }, + "parameters": [ + "Object", + "=", + "HoverFontSize" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "HoverColor", + "!=", + "\"\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "IdleColor", + "=", + "Object.Behavior::Color()" + ] + }, + { + "type": { + "value": "TextObject::ChangeColor" + }, + "parameters": [ + "Object", + "HoverColor" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "ShouldEnableShadowOnHover", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "TextObject::ShowShadow" + }, + "parameters": [ + "Object", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "ShouldEnableOutlineOnHover", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "TextObject::Text::SetOutlineEnabled" + }, + "parameters": [ + "Object", + "yes" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsHovered", + "True", + "" + ] + }, + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "False", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "IsHovered", + "False", + "" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "HoverFontSize", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "TextObject::Text::SetFontSize" + }, + "parameters": [ + "Object", + "=", + "IdleFontSize" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "HoverColor", + "!=", + "\"\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "TextObject::ChangeColor" + }, + "parameters": [ + "Object", + "IdleColor" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "ShouldEnableShadowOnHover", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "TextObject::ShowShadow" + }, + "parameters": [ + "Object", + "no" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "ShouldEnableOutlineOnHover", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "TextObject::Text::SetOutlineEnabled" + }, + "parameters": [ + "Object", + "no" + ] + } + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "TextObject::Text", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PanelSpriteButton::TextStyleState", + "type": "behavior" + }, + { + "defaultValue": "yes", + "description": "IsHovered", + "name": "Value", + "optional": true, + "type": "yesorno" + } + ], + "objectGroups": [] + }, + { + "description": "Return the text color", + "fullName": "Text color", + "functionType": "StringExpression", + "name": "Color", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "/** @type {gdjs.TextRuntimeObject} */", + "const object = eventsFunctionContext.getObjects(\"Object\")[0];", + "", + "eventsFunctionContext.returnValue = object._color.join(\";\");" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "color" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "TextObject::Text", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PanelSpriteButton::TextStyleState", + "type": "behavior" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "IsHovered" + }, + { + "functionName": "SetIsHovered" + }, + { + "functionName": "Color" + } + ] + }, + "propertyDescriptors": [ + { + "value": "", + "type": "Boolean", + "label": "Outline on hover", + "name": "ShouldEnableOutlineOnHover" + }, + { + "value": "", + "type": "Color", + "label": "Hover color", + "name": "HoverColor" + }, + { + "value": "", + "type": "Boolean", + "label": "Enable shadow on hover", + "name": "ShouldEnableShadowOnHover" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Hover font size", + "name": "HoverFontSize" + }, + { + "value": "", + "type": "Boolean", + "label": "", + "hidden": true, + "name": "IsHovered" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Idle font size", + "hidden": true, + "name": "IdleFontSize" + }, + { + "value": "", + "type": "Color", + "label": "Idle color", + "hidden": true, + "name": "IdleColor" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "propertyName": "IsHovered" + }, + { + "propertyName": "HoverFontSize" + }, + { + "propertyName": "IdleFontSize" + }, + { + "propertyName": "HoverColor" + }, + { + "propertyName": "IdleColor" + }, + { + "propertyName": "ShouldEnableOutlineOnHover" + }, + { + "propertyName": "ShouldEnableShadowOnHover" + } + ] + } + }, + { + "description": "Change the text style when the button is hovered.", + "fullName": "Hover bitmap text style", + "helpPath": "", + "iconUrl": "", + "name": "BitmapTextStyleState", + "objectType": "BitmapText::BitmapTextObject", + "previewIconUrl": "", + "private": true, + "eventsFunctions": [ + { + "description": "Check if isHovered.", + "fullName": "IsHovered", + "functionType": "Condition", + "name": "IsHovered", + "sentence": "_PARAM0_ isHovered", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsHovered", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "BitmapText::BitmapTextObject", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PanelSpriteButton::BitmapTextStyleState", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Change if isHovered.", + "fullName": "IsHovered", + "functionType": "Action", + "name": "SetIsHovered", + "sentence": "_PARAM0_ isHovered: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsHovered", + "False", + "" + ] + }, + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "IsHovered", + "True", + "" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "HoverColor", + "!=", + "\"\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "IdleColor", + "=", + "Object.Behavior::Color()" + ] + }, + { + "type": { + "value": "BitmapText::SetTint" + }, + "parameters": [ + "Object", + "HoverColor" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Or" + }, + "parameters": [], + "subInstructions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "HoverPrefix", + "!=", + "\"\"" + ] + }, + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "HoverSuffix", + "!=", + "\"\"" + ] + } + ] + } + ], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "IdleText", + "=", + "Object.Text::Value()" + ] + }, + { + "type": { + "value": "TextContainerCapability::TextContainerBehavior::SetValue" + }, + "parameters": [ + "Object", + "Text", + "=", + "HoverPrefix + Object.Text::Value() + HoverSuffix" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsHovered", + "True", + "" + ] + }, + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "False", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "IsHovered", + "False", + "" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "HoverColor", + "!=", + "\"\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "BitmapText::SetTint" + }, + "parameters": [ + "Object", + "IdleColor" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Or" + }, + "parameters": [], + "subInstructions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "HoverPrefix", + "!=", + "\"\"" + ] + }, + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "HoverSuffix", + "!=", + "\"\"" + ] + } + ] + } + ], + "actions": [ + { + "type": { + "value": "TextContainerCapability::TextContainerBehavior::SetValue" + }, + "parameters": [ + "Object", + "Text", + "=", + "IdleText" + ] + } + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "BitmapText::BitmapTextObject", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PanelSpriteButton::BitmapTextStyleState", + "type": "behavior" + }, + { + "defaultValue": "yes", + "description": "IsHovered", + "name": "Value", + "optional": true, + "type": "yesorno" + } + ], + "objectGroups": [] + }, + { + "description": "Return the text color", + "fullName": "Text color", + "functionType": "StringExpression", + "name": "Color", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "/** @type {gdjs.BitmapTextRuntimeObject} */", + "const object = eventsFunctionContext.getObjects(\"Object\")[0];", + "", + "eventsFunctionContext.returnValue = object._tint.join(\";\");" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "color" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "BitmapText::BitmapTextObject", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PanelSpriteButton::BitmapTextStyleState", + "type": "behavior" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "IsHovered" + }, + { + "functionName": "SetIsHovered" + }, + { + "functionName": "Color" + } + ] + }, + "propertyDescriptors": [ + { + "value": "", + "type": "Color", + "label": "Hover color", + "name": "HoverColor" + }, + { + "value": "", + "type": "String", + "label": "Hover prefix", + "name": "HoverPrefix" + }, + { + "value": "", + "type": "String", + "label": "Hover suffix", + "name": "HoverSuffix" + }, + { + "value": "", + "type": "Boolean", + "label": "", + "hidden": true, + "name": "IsHovered" + }, + { + "value": "", + "type": "String", + "label": "Idle text", + "hidden": true, + "name": "IdleText" + }, + { + "value": "", + "type": "Color", + "label": "Idle color", + "hidden": true, + "name": "IdleColor" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "propertyName": "IsHovered" + }, + { + "propertyName": "HoverPrefix" + }, + { + "propertyName": "HoverSuffix" + }, + { + "propertyName": "IdleText" + }, + { + "propertyName": "HoverColor" + }, + { + "propertyName": "IdleColor" + } + ] + } + } + ], + "eventsBasedObjects": [ + { + "areaMaxX": 256, + "areaMaxY": 64, + "areaMaxZ": 64, + "areaMinX": 0, + "areaMinY": 0, + "areaMinZ": 0, + "assetStoreTag": "menu buttons", + "defaultName": "Button", + "description": "Button with a label.", + "fullName": "Labeled button", + "helpPath": "", + "iconUrl": "", + "isInnerAreaFollowingParentSize": true, + "isUsingLegacyInstancesRenderer": false, + "name": "PanelSpriteButton", + "previewIconUrl": "", + "objects": [ + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "Label", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 4, + "topEdgeAnchor": 4, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "TextStyleState", + "type": "PanelSpriteButton::TextStyleState", + "ShouldEnableOutlineOnHover": false, + "HoverColor": "", + "ShouldEnableShadowOnHover": false, + "HoverFontSize": 0, + "IsHovered": false, + "IdleFontSize": 0, + "IdleColor": "" + } + ], + "string": "Text", + "font": "", + "textAlignment": "center", + "characterSize": 20, + "color": { + "b": 0, + "g": 0, + "r": 0 + }, + "content": { + "bold": false, + "isOutlineEnabled": false, + "isShadowEnabled": false, + "italic": false, + "outlineColor": "255;255;255", + "outlineThickness": 2, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "0;0;0", + "shadowDistance": 4, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "Text", + "font": "", + "textAlignment": "center", + "verticalTextAlignment": "center", + "characterSize": 20, + "lineHeight": 0, + "color": "0;0;0" + } + }, + { + "assetStoreId": "", + "bottomMargin": 0, + "height": 32, + "leftMargin": 0, + "name": "Idle", + "rightMargin": 0, + "texture": "", + "tiled": false, + "topMargin": 0, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [ + { + "folded": true, + "name": "State", + "type": "string", + "value": "Idle" + } + ], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "ButtonFSM", + "type": "PanelSpriteButton::ButtonFSM", + "ShouldCheckHovering": true + } + ] + }, + { + "assetStoreId": "", + "bottomMargin": 0, + "height": 32, + "leftMargin": 0, + "name": "Hovered", + "rightMargin": 0, + "texture": "", + "tiled": false, + "topMargin": 0, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "Tween", + "type": "Tween::TweenBehavior" + } + ] + }, + { + "assetStoreId": "", + "bottomMargin": 0, + "height": 32, + "leftMargin": 0, + "name": "Pressed", + "rightMargin": 0, + "texture": "", + "tiled": false, + "topMargin": 0, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + } + ] + }, + { + "assetStoreId": "", + "name": "BitmapLabel", + "type": "BitmapText::BitmapTextObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 4, + "topEdgeAnchor": 4, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "BitmapTextStyleState", + "type": "PanelSpriteButton::BitmapTextStyleState", + "HoverColor": "", + "HoverPrefix": "", + "HoverSuffix": "", + "IsHovered": false, + "IdleText": "", + "IdleColor": "" + } + ], + "content": { + "text": "Text", + "opacity": 255, + "scale": 1, + "fontSize": 20, + "tint": "255;255;255", + "bitmapFontResourceName": "", + "textureAtlasResourceName": "", + "align": "center", + "verticalTextAlignment": "center" + } + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "objectName": "Label" + }, + { + "objectName": "BitmapLabel" + }, + { + "objectName": "Idle" + }, + { + "objectName": "Hovered" + }, + { + "objectName": "Pressed" + } + ] + }, + "objectsGroups": [ + { + "name": "Background", + "objects": [ + { + "name": "Idle" + }, + { + "name": "Hovered" + }, + { + "name": "Pressed" + } + ] + }, + { + "name": "Labels", + "objects": [ + { + "name": "Label" + }, + { + "name": "BitmapLabel" + } + ] + } + ], + "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": 1, + "height": 64, + "layer": "", + "name": "Idle", + "persistentUuid": "24882334-eec8-403e-8bf1-70fc928a46e6", + "width": 256, + "x": 0, + "y": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 1, + "height": 64, + "layer": "", + "name": "Label", + "persistentUuid": "3b29c95c-5363-4e25-bf47-eecf13e8a226", + "width": 256, + "x": 0, + "y": 32, + "zOrder": 2, + "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": 2.734375, + "windowMask": false, + "selectedLayer": "", + "gameEditorMode": "instances-editor" + }, + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "onCreated", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Create one background instance for of each state.\nOnly the instance for the current state is shown." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Create" + }, + "parameters": [ + "", + "Hovered", + "0", + "0", + "" + ] + }, + { + "type": { + "value": "Create" + }, + "parameters": [ + "", + "Pressed", + "0", + "0", + "" + ] + }, + { + "type": { + "value": "ResizableCapability::ResizableBehavior::SetSize" + }, + "parameters": [ + "Hovered", + "Resizable", + "Idle.Width()", + "Idle.Height()" + ] + }, + { + "type": { + "value": "ResizableCapability::ResizableBehavior::SetSize" + }, + "parameters": [ + "Pressed", + "Resizable", + "Idle.Width()", + "Idle.Height()" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "Hovered" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "Pressed" + ] + }, + { + "type": { + "value": "SetZOrder" + }, + "parameters": [ + "Hovered", + "=", + "1" + ] + }, + { + "type": { + "value": "SetZOrder" + }, + "parameters": [ + "Pressed", + "=", + "1" + ] + }, + { + "type": { + "value": "TextContainerCapability::TextContainerBehavior::SetValue" + }, + "parameters": [ + "Labels", + "Text", + "=", + "LabelText" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "PanelSpriteButton::PanelSpriteButton", + "type": "object" + } + ], + "objectGroups": [ + { + "name": "Background", + "objects": [ + { + "name": "Idle" + }, + { + "name": "Hovered" + }, + { + "name": "Pressed" + } + ] + } + ] + }, + { + "fullName": "", + "functionType": "Action", + "name": "onHotReloading", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::IsPressed" + }, + "parameters": [ + "Object", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::SetLabelOffset" + }, + "parameters": [ + "Object", + "=", + "PressedLabelOffsetY", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "TextContainerCapability::TextContainerBehavior::SetValue" + }, + "parameters": [ + "Labels", + "Text", + "=", + "LabelText" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "PanelSpriteButton::PanelSpriteButton", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "doStepPostEvents", + "sentence": "", + "events": [ + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Apply states", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Show the right background accordingly to the new state." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::IsIdle" + }, + "parameters": [ + "Object", + "ButtonFSM" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "PanelSpriteButton::TextStyleState::SetIsHovered" + }, + "parameters": [ + "Label", + "TextStyleState", + "no", + "" + ] + }, + { + "type": { + "value": "PanelSpriteButton::BitmapTextStyleState::SetIsHovered" + }, + "parameters": [ + "BitmapLabel", + "BitmapTextStyleState", + "no", + "" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::SetLabelOffset" + }, + "parameters": [ + "Object", + "=", + "0", + "" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "Idle", + "" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "Pressed" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Visible" + }, + "parameters": [ + "Hovered" + ] + }, + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "HoveredFadeOutDuration", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "Tween::TweenBehavior::AddObjectOpacityTween2" + }, + "parameters": [ + "Hovered", + "Tween", + "\"Fadeout\"", + "0", + "\"linear\"", + "HoveredFadeOutDuration", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "HoveredFadeOutDuration", + "=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "Hide" + }, + "parameters": [ + "Hovered" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "OpacityCapability::OpacityBehavior::Value" + }, + "parameters": [ + "Hovered", + "Opacity", + "=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "Hide" + }, + "parameters": [ + "Hovered" + ] + }, + { + "type": { + "value": "OpacityCapability::OpacityBehavior::SetValue" + }, + "parameters": [ + "Hovered", + "Opacity", + "=", + "255" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::IsHovered" + }, + "parameters": [ + "Object", + "ButtonFSM" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "PanelSpriteButton::TextStyleState::SetIsHovered" + }, + "parameters": [ + "Label", + "TextStyleState", + "", + "" + ] + }, + { + "type": { + "value": "PanelSpriteButton::BitmapTextStyleState::SetIsHovered" + }, + "parameters": [ + "BitmapLabel", + "BitmapTextStyleState", + "yes", + "" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::SetLabelOffset" + }, + "parameters": [ + "Object", + "=", + "0", + "" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "Idle" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "Hovered", + "" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "Pressed" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "HoveredFadeOutDuration", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "Tween::RemoveTween" + }, + "parameters": [ + "Hovered", + "Tween", + "\"Fadeout\"" + ] + }, + { + "type": { + "value": "OpacityCapability::OpacityBehavior::SetValue" + }, + "parameters": [ + "Hovered", + "Opacity", + "=", + "255" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::IsPressed" + }, + "parameters": [ + "Object", + "ButtonFSM" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "PanelSpriteButton::TextStyleState::SetIsHovered" + }, + "parameters": [ + "Label", + "TextStyleState", + "no", + "" + ] + }, + { + "type": { + "value": "PanelSpriteButton::BitmapTextStyleState::SetIsHovered" + }, + "parameters": [ + "BitmapLabel", + "BitmapTextStyleState", + "no", + "" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::SetLabelOffset" + }, + "parameters": [ + "Object", + "=", + "PressedLabelOffsetY", + "" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "Idle" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "Hovered" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "Pressed", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::IsFocused" + }, + "parameters": [ + "Object", + "ButtonFSM" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "PanelSpriteButton::TextStyleState::SetIsHovered" + }, + "parameters": [ + "Label", + "TextStyleState", + "yes", + "" + ] + }, + { + "type": { + "value": "PanelSpriteButton::BitmapTextStyleState::SetIsHovered" + }, + "parameters": [ + "BitmapLabel", + "BitmapTextStyleState", + "yes", + "" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::SetLabelOffset" + }, + "parameters": [ + "Object", + "=", + "0", + "" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "Idle" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "Hovered", + "" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "Pressed" + ] + } + ] + } + ], + "parameters": [] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "PanelSpriteButton::PanelSpriteButton", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Check if the button is not used.", + "fullName": "Is idle", + "functionType": "Condition", + "name": "IsIdle", + "sentence": "_PARAM0_ is idle", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "PanelSpriteButton::ButtonFSM::IsIdle" + }, + "parameters": [ + "Idle", + "ButtonFSM", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "PanelSpriteButton::PanelSpriteButton", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Check if the button was just clicked.", + "fullName": "Is clicked", + "functionType": "Condition", + "name": "IsClicked", + "sentence": "_PARAM0_ is clicked", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "PanelSpriteButton::ButtonFSM::IsClicked" + }, + "parameters": [ + "Idle", + "ButtonFSM", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "PanelSpriteButton::PanelSpriteButton", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Check if the cursor is hovered over the button.", + "fullName": "Is hovered", + "functionType": "Condition", + "name": "IsHovered", + "sentence": "_PARAM0_ is hovered", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "PanelSpriteButton::ButtonFSM::IsHovered" + }, + "parameters": [ + "Idle", + "ButtonFSM", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "PanelSpriteButton::PanelSpriteButton", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Check if the button is either hovered or pressed but not hovered.", + "fullName": "Is focused", + "functionType": "Condition", + "name": "IsFocused", + "sentence": "_PARAM0_ is focused", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "PanelSpriteButton::ButtonFSM::IsFocused" + }, + "parameters": [ + "Idle", + "ButtonFSM", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "PanelSpriteButton::PanelSpriteButton", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Check if the button is currently being pressed with mouse or touch.", + "fullName": "Is pressed", + "functionType": "Condition", + "name": "IsPressed", + "sentence": "_PARAM0_ is pressed", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "PanelSpriteButton::ButtonFSM::IsPressed" + }, + "parameters": [ + "Idle", + "ButtonFSM", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "PanelSpriteButton::PanelSpriteButton", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Change the text of the button label.", + "fullName": "Label text", + "functionType": "Action", + "name": "SetLabelText", + "private": true, + "sentence": "Change the text of _PARAM0_ to _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "TextContainerCapability::TextContainerBehavior::SetValue" + }, + "parameters": [ + "Labels", + "Text", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "PanelSpriteButton::PanelSpriteButton", + "type": "object" + }, + { + "description": "Text", + "name": "Value", + "type": "string" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "LabelText", + "name": "SetLabelTextOp", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "TextContainerCapability::TextContainerBehavior::SetValue" + }, + "parameters": [ + "Labels", + "Text", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "PanelSpriteButton::PanelSpriteButton", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the label text.", + "fullName": "Label text", + "functionType": "ExpressionAndCondition", + "name": "LabelText", + "sentence": "the label text", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnString" + }, + "parameters": [ + "Labels.Text::Value()" + ] + } + ] + } + ], + "expressionType": { + "type": "string" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "PanelSpriteButton::PanelSpriteButton", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "De/activate interactions with the button.", + "fullName": "De/activate interactions", + "functionType": "Action", + "name": "Activate", + "sentence": "Activate interactions with _PARAM0_: _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "ShouldActivate", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "ActivateBehavior" + }, + "parameters": [ + "Idle", + "ButtonFSM", + "yes" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "BooleanVariable" + }, + "parameters": [ + "ShouldActivate", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "ActivateBehavior" + }, + "parameters": [ + "Idle", + "ButtonFSM", + "no" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "PanelSpriteButton::PanelSpriteButton", + "type": "object" + }, + { + "description": "Activate", + "name": "ShouldActivate", + "type": "yesorno" + } + ], + "objectGroups": [] + }, + { + "description": "Check if interactions are activated on the button.", + "fullName": "Interactions activated", + "functionType": "Condition", + "name": "IsActivated", + "sentence": "Interactions on _PARAM0_ are activated", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BehaviorActivated" + }, + "parameters": [ + "Idle", + "ButtonFSM" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "PanelSpriteButton::PanelSpriteButton", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the labelOffset of the object.", + "fullName": "LabelOffset", + "functionType": "ExpressionAndCondition", + "name": "LabelOffset", + "private": true, + "sentence": "the labelOffset", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "LabelOffset" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "PanelSpriteButton::PanelSpriteButton", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "LabelOffset", + "name": "SetLabelOffset", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetCenterY" + }, + "parameters": [ + "Labels", + "+", + "Value - LabelOffset" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "LabelOffset", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "PanelSpriteButton::PanelSpriteButton", + "type": "object" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "onCreated" + }, + { + "functionName": "onHotReloading" + }, + { + "functionName": "doStepPostEvents" + }, + { + "functionName": "IsIdle" + }, + { + "functionName": "IsClicked" + }, + { + "functionName": "IsHovered" + }, + { + "functionName": "IsFocused" + }, + { + "functionName": "IsPressed" + }, + { + "functionName": "SetLabelText" + }, + { + "functionName": "SetLabelTextOp" + }, + { + "functionName": "LabelText" + }, + { + "functionName": "Activate" + }, + { + "functionName": "IsActivated" + }, + { + "functionName": "LabelOffset" + }, + { + "functionName": "SetLabelOffset" + } + ] + }, + "propertyDescriptors": [ + { + "value": "", + "type": "MultilineString", + "label": "Label", + "name": "LabelText" + }, + { + "value": "0.25", + "type": "Number", + "unit": "Second", + "label": "Hovered fade out duration", + "group": "States", + "name": "HoveredFadeOutDuration" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Label offset on Y axis when pressed", + "group": "States", + "name": "PressedLabelOffsetY" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "", + "group": "States", + "hidden": true, + "name": "LabelOffset" + }, + { + "value": "", + "type": "Choice", + "label": "", + "choices": [ + { + "label": "Label.Text=LabelText", + "value": "Label.Text=LabelText" + }, + { + "label": "BitmapLabel.Text=LabelText", + "value": "BitmapLabel.Text=LabelText" + } + ], + "hidden": true, + "name": "_PropertyMapping" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "propertyName": "LabelText" + }, + { + "propertyName": "_PropertyMapping" + }, + { + "folderName": "States", + "children": [ + { + "propertyName": "HoveredFadeOutDuration" + }, + { + "propertyName": "PressedLabelOffsetY" + }, + { + "propertyName": "LabelOffset" + } + ] + } + ] + }, + "variants": [ + { + "areaMaxX": 256, + "areaMaxY": 64, + "areaMaxZ": 64, + "areaMinX": 0, + "areaMinY": 0, + "areaMinZ": 0, + "name": "Primary", + "objects": [ + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "Label", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 4, + "topEdgeAnchor": 4, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "TextStyleState", + "type": "PanelSpriteButton::TextStyleState", + "ShouldEnableOutlineOnHover": false, + "HoverColor": "", + "ShouldEnableShadowOnHover": false, + "HoverFontSize": 0, + "IsHovered": false, + "IdleFontSize": 0, + "IdleColor": "" + } + ], + "string": "Text", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "characterSize": 44, + "color": { + "b": 255, + "g": 255, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": false, + "isShadowEnabled": false, + "italic": false, + "outlineColor": "255;255;255", + "outlineThickness": 2, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "0;0;0", + "shadowDistance": 4, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "Text", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "verticalTextAlignment": "center", + "characterSize": 44, + "lineHeight": 0, + "color": "255;255;255" + } + }, + { + "assetStoreId": "", + "bottomMargin": 56, + "height": 32, + "leftMargin": 56, + "name": "Idle", + "rightMargin": 56, + "texture": "ButtonIdle.png", + "tiled": false, + "topMargin": 56, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [ + { + "folded": true, + "name": "State", + "type": "string", + "value": "Idle" + } + ], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "ButtonFSM", + "type": "PanelSpriteButton::ButtonFSM", + "ShouldCheckHovering": true + } + ] + }, + { + "assetStoreId": "", + "bottomMargin": 56, + "height": 32, + "leftMargin": 56, + "name": "Hovered", + "rightMargin": 56, + "texture": "ButtonHovered.png", + "tiled": false, + "topMargin": 56, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "Tween", + "type": "Tween::TweenBehavior" + } + ] + }, + { + "assetStoreId": "", + "bottomMargin": 56, + "height": 32, + "leftMargin": 56, + "name": "Pressed", + "rightMargin": 56, + "texture": "ButtonPressed.png", + "tiled": false, + "topMargin": 56, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + } + ] + }, + { + "assetStoreId": "", + "name": "BitmapLabel", + "type": "BitmapText::BitmapTextObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 4, + "topEdgeAnchor": 4, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "BitmapTextStyleState", + "type": "PanelSpriteButton::BitmapTextStyleState", + "HoverColor": "", + "HoverPrefix": "", + "HoverSuffix": "", + "IsHovered": false, + "IdleText": "", + "IdleColor": "" + } + ], + "content": { + "text": "Text", + "opacity": 255, + "scale": 1, + "fontSize": 20, + "tint": "255;255;255", + "bitmapFontResourceName": "", + "textureAtlasResourceName": "", + "align": "center", + "verticalTextAlignment": "center" + } + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "objectName": "Label" + }, + { + "objectName": "BitmapLabel" + }, + { + "objectName": "Idle" + }, + { + "objectName": "Hovered" + }, + { + "objectName": "Pressed" + } + ] + }, + "objectsGroups": [ + { + "name": "Background", + "objects": [ + { + "name": "Idle" + }, + { + "name": "Hovered" + }, + { + "name": "Pressed" + } + ] + }, + { + "name": "Labels", + "objects": [ + { + "name": "Label" + }, + { + "name": "BitmapLabel" + } + ] + } + ], + "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": 1, + "height": 64, + "layer": "", + "name": "Idle", + "persistentUuid": "24882334-eec8-403e-8bf1-70fc928a46e6", + "width": 256, + "x": 0, + "y": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 1, + "height": 64, + "layer": "", + "name": "Label", + "persistentUuid": "3b29c95c-5363-4e25-bf47-eecf13e8a226", + "width": 256, + "x": 0, + "y": 32, + "zOrder": 2, + "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": 2.734375, + "windowMask": false, + "selectedLayer": "", + "gameEditorMode": "instances-editor" + } + }, + { + "areaMaxX": 256, + "areaMaxY": 64, + "areaMaxZ": 64, + "areaMinX": 0, + "areaMinY": 0, + "areaMinZ": 0, + "name": "Secondary", + "objects": [ + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "Label", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 4, + "topEdgeAnchor": 4, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "TextStyleState", + "type": "PanelSpriteButton::TextStyleState", + "ShouldEnableOutlineOnHover": false, + "HoverColor": "", + "ShouldEnableShadowOnHover": false, + "HoverFontSize": 0, + "IsHovered": false, + "IdleFontSize": 0, + "IdleColor": "" + } + ], + "string": "Text", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "characterSize": 36, + "color": { + "b": 255, + "g": 255, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": false, + "isShadowEnabled": false, + "italic": false, + "outlineColor": "255;255;255", + "outlineThickness": 2, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "0;0;0", + "shadowDistance": 4, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "Text", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "verticalTextAlignment": "center", + "characterSize": 36, + "lineHeight": 0, + "color": "255;255;255" + } + }, + { + "assetStoreId": "", + "bottomMargin": 56, + "height": 32, + "leftMargin": 56, + "name": "Idle", + "rightMargin": 56, + "texture": "SecondaryButtonIdle.png", + "tiled": false, + "topMargin": 56, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [ + { + "folded": true, + "name": "State", + "type": "string", + "value": "Idle" + } + ], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "ButtonFSM", + "type": "PanelSpriteButton::ButtonFSM", + "ShouldCheckHovering": true + } + ] + }, + { + "assetStoreId": "", + "bottomMargin": 56, + "height": 32, + "leftMargin": 56, + "name": "Hovered", + "rightMargin": 56, + "texture": "SecondaryButtonHovered.png", + "tiled": false, + "topMargin": 56, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "Tween", + "type": "Tween::TweenBehavior" + } + ] + }, + { + "assetStoreId": "", + "bottomMargin": 56, + "height": 32, + "leftMargin": 56, + "name": "Pressed", + "rightMargin": 56, + "texture": "SecondaryButtonPressed.png", + "tiled": false, + "topMargin": 56, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + } + ] + }, + { + "assetStoreId": "", + "name": "BitmapLabel", + "type": "BitmapText::BitmapTextObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 4, + "topEdgeAnchor": 4, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "BitmapTextStyleState", + "type": "PanelSpriteButton::BitmapTextStyleState", + "HoverColor": "", + "HoverPrefix": "", + "HoverSuffix": "", + "IsHovered": false, + "IdleText": "", + "IdleColor": "" + } + ], + "content": { + "text": "Text", + "opacity": 255, + "scale": 1, + "fontSize": 20, + "tint": "255;255;255", + "bitmapFontResourceName": "", + "textureAtlasResourceName": "", + "align": "center", + "verticalTextAlignment": "center" + } + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "objectName": "Label" + }, + { + "objectName": "BitmapLabel" + }, + { + "objectName": "Idle" + }, + { + "objectName": "Hovered" + }, + { + "objectName": "Pressed" + } + ] + }, + "objectsGroups": [ + { + "name": "Background", + "objects": [ + { + "name": "Idle" + }, + { + "name": "Hovered" + }, + { + "name": "Pressed" + } + ] + }, + { + "name": "Labels", + "objects": [ + { + "name": "Label" + }, + { + "name": "BitmapLabel" + } + ] + } + ], + "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": 1, + "height": 64, + "layer": "", + "name": "Idle", + "persistentUuid": "24882334-eec8-403e-8bf1-70fc928a46e6", + "width": 256, + "x": 0, + "y": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 1, + "height": 64, + "layer": "", + "name": "Label", + "persistentUuid": "3b29c95c-5363-4e25-bf47-eecf13e8a226", + "width": 256, + "x": 0, + "y": 32, + "zOrder": 2, + "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": 2.734375, + "windowMask": false, + "selectedLayer": "", + "gameEditorMode": "instances-editor" + } + }, + { + "areaMaxX": 256, + "areaMaxY": 64, + "areaMaxZ": 64, + "areaMinX": 0, + "areaMinY": 0, + "areaMinZ": 0, + "name": "Close", + "objects": [ + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "Label", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 4, + "topEdgeAnchor": 4, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "TextStyleState", + "type": "PanelSpriteButton::TextStyleState", + "ShouldEnableOutlineOnHover": false, + "HoverColor": "", + "ShouldEnableShadowOnHover": false, + "HoverFontSize": 0, + "IsHovered": false, + "IdleFontSize": 0, + "IdleColor": "" + } + ], + "string": "Text", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "characterSize": 44, + "color": { + "b": 255, + "g": 255, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": false, + "isShadowEnabled": false, + "italic": false, + "outlineColor": "255;255;255", + "outlineThickness": 2, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "0;0;0", + "shadowDistance": 4, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "Text", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "verticalTextAlignment": "center", + "characterSize": 44, + "lineHeight": 0, + "color": "255;255;255" + } + }, + { + "assetStoreId": "", + "bottomMargin": 56, + "height": 32, + "leftMargin": 56, + "name": "Idle", + "rightMargin": 56, + "texture": "CloseButtonIdle.png", + "tiled": false, + "topMargin": 56, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [ + { + "folded": true, + "name": "State", + "type": "string", + "value": "Idle" + } + ], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "ButtonFSM", + "type": "PanelSpriteButton::ButtonFSM", + "ShouldCheckHovering": true + } + ] + }, + { + "assetStoreId": "", + "bottomMargin": 56, + "height": 32, + "leftMargin": 56, + "name": "Hovered", + "rightMargin": 56, + "texture": "CloseButtonHovered.png", + "tiled": false, + "topMargin": 56, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "Tween", + "type": "Tween::TweenBehavior" + } + ] + }, + { + "assetStoreId": "", + "bottomMargin": 56, + "height": 32, + "leftMargin": 56, + "name": "Pressed", + "rightMargin": 56, + "texture": "CloseButtonPressed.png", + "tiled": false, + "topMargin": 56, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + } + ] + }, + { + "assetStoreId": "", + "name": "BitmapLabel", + "type": "BitmapText::BitmapTextObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 4, + "topEdgeAnchor": 4, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "BitmapTextStyleState", + "type": "PanelSpriteButton::BitmapTextStyleState", + "HoverColor": "", + "HoverPrefix": "", + "HoverSuffix": "", + "IsHovered": false, + "IdleText": "", + "IdleColor": "" + } + ], + "content": { + "text": "Text", + "opacity": 255, + "scale": 1, + "fontSize": 20, + "tint": "255;255;255", + "bitmapFontResourceName": "", + "textureAtlasResourceName": "", + "align": "center", + "verticalTextAlignment": "center" + } + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "objectName": "Label" + }, + { + "objectName": "BitmapLabel" + }, + { + "objectName": "Idle" + }, + { + "objectName": "Hovered" + }, + { + "objectName": "Pressed" + } + ] + }, + "objectsGroups": [ + { + "name": "Background", + "objects": [ + { + "name": "Idle" + }, + { + "name": "Hovered" + }, + { + "name": "Pressed" + } + ] + }, + { + "name": "Labels", + "objects": [ + { + "name": "Label" + }, + { + "name": "BitmapLabel" + } + ] + } + ], + "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": 1, + "height": 64, + "layer": "", + "name": "Idle", + "persistentUuid": "24882334-eec8-403e-8bf1-70fc928a46e6", + "width": 256, + "x": 0, + "y": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 1, + "height": 64, + "layer": "", + "name": "Label", + "persistentUuid": "3b29c95c-5363-4e25-bf47-eecf13e8a226", + "width": 256, + "x": 0, + "y": 32, + "zOrder": 2, + "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": 2.734375, + "windowMask": false, + "selectedLayer": "", + "gameEditorMode": "instances-editor" + } + }, + { + "areaMaxX": 256, + "areaMaxY": 64, + "areaMaxZ": 64, + "areaMinX": 0, + "areaMinY": 0, + "areaMinZ": 0, + "name": "Stepper", + "objects": [ + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "Label", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 4, + "topEdgeAnchor": 4, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "TextStyleState", + "type": "PanelSpriteButton::TextStyleState", + "ShouldEnableOutlineOnHover": false, + "HoverColor": "", + "ShouldEnableShadowOnHover": false, + "HoverFontSize": 0, + "IsHovered": false, + "IdleFontSize": 0, + "IdleColor": "" + } + ], + "string": "Text", + "font": "RobotoMono-Bold.ttf", + "textAlignment": "center", + "characterSize": 64, + "color": { + "b": 255, + "g": 255, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": false, + "isShadowEnabled": false, + "italic": false, + "outlineColor": "255;255;255", + "outlineThickness": 2, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "0;0;0", + "shadowDistance": 4, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "Text", + "font": "RobotoMono-Bold.ttf", + "textAlignment": "center", + "verticalTextAlignment": "center", + "characterSize": 64, + "lineHeight": 0, + "color": "255;255;255" + } + }, + { + "assetStoreId": "", + "bottomMargin": 56, + "height": 32, + "leftMargin": 56, + "name": "Idle", + "rightMargin": 56, + "texture": "SecondaryButtonIdle.png", + "tiled": false, + "topMargin": 56, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [ + { + "folded": true, + "name": "State", + "type": "string", + "value": "Idle" + } + ], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "ButtonFSM", + "type": "PanelSpriteButton::ButtonFSM", + "ShouldCheckHovering": true + } + ] + }, + { + "assetStoreId": "", + "bottomMargin": 56, + "height": 32, + "leftMargin": 56, + "name": "Hovered", + "rightMargin": 56, + "texture": "SecondaryButtonHovered.png", + "tiled": false, + "topMargin": 56, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "Tween", + "type": "Tween::TweenBehavior" + } + ] + }, + { + "assetStoreId": "", + "bottomMargin": 56, + "height": 32, + "leftMargin": 56, + "name": "Pressed", + "rightMargin": 56, + "texture": "SecondaryButtonPressed.png", + "tiled": false, + "topMargin": 56, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + } + ] + }, + { + "assetStoreId": "", + "name": "BitmapLabel", + "type": "BitmapText::BitmapTextObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 4, + "topEdgeAnchor": 4, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "BitmapTextStyleState", + "type": "PanelSpriteButton::BitmapTextStyleState", + "HoverColor": "", + "HoverPrefix": "", + "HoverSuffix": "", + "IsHovered": false, + "IdleText": "", + "IdleColor": "" + } + ], + "content": { + "text": "Text", + "opacity": 255, + "scale": 1, + "fontSize": 20, + "tint": "255;255;255", + "bitmapFontResourceName": "", + "textureAtlasResourceName": "", + "align": "center", + "verticalTextAlignment": "center" + } + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "objectName": "Label" + }, + { + "objectName": "BitmapLabel" + }, + { + "objectName": "Idle" + }, + { + "objectName": "Hovered" + }, + { + "objectName": "Pressed" + } + ] + }, + "objectsGroups": [ + { + "name": "Background", + "objects": [ + { + "name": "Idle" + }, + { + "name": "Hovered" + }, + { + "name": "Pressed" + } + ] + }, + { + "name": "Labels", + "objects": [ + { + "name": "Label" + }, + { + "name": "BitmapLabel" + } + ] + } + ], + "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": 1, + "height": 64, + "layer": "", + "name": "Idle", + "persistentUuid": "24882334-eec8-403e-8bf1-70fc928a46e6", + "width": 256, + "x": 0, + "y": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 1, + "height": 64, + "layer": "", + "name": "Label", + "persistentUuid": "3b29c95c-5363-4e25-bf47-eecf13e8a226", + "width": 256, + "x": 0, + "y": 32, + "zOrder": 2, + "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": 2.734375, + "windowMask": false, + "selectedLayer": "", + "gameEditorMode": "instances-editor" + } + }, + { + "areaMaxX": 256, + "areaMaxY": 64, + "areaMaxZ": 64, + "areaMinX": 0, + "areaMinY": 0, + "areaMinZ": 0, + "name": "IconGear", + "objects": [ + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "Label", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 4, + "topEdgeAnchor": 4, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "TextStyleState", + "type": "PanelSpriteButton::TextStyleState", + "ShouldEnableOutlineOnHover": false, + "HoverColor": "", + "ShouldEnableShadowOnHover": false, + "HoverFontSize": 0, + "IsHovered": false, + "IdleFontSize": 0, + "IdleColor": "" + } + ], + "string": "Text", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "characterSize": 36, + "color": { + "b": 255, + "g": 255, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": false, + "isShadowEnabled": false, + "italic": false, + "outlineColor": "255;255;255", + "outlineThickness": 2, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "0;0;0", + "shadowDistance": 4, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "Text", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "verticalTextAlignment": "center", + "characterSize": 36, + "lineHeight": 0, + "color": "255;255;255" + } + }, + { + "assetStoreId": "", + "bottomMargin": 0, + "height": 32, + "leftMargin": 0, + "name": "Idle", + "rightMargin": 0, + "texture": "GearButtonIdle.png", + "tiled": false, + "topMargin": 0, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [ + { + "folded": true, + "name": "State", + "type": "string", + "value": "Idle" + } + ], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "ButtonFSM", + "type": "PanelSpriteButton::ButtonFSM", + "ShouldCheckHovering": true + } + ] + }, + { + "assetStoreId": "", + "bottomMargin": 0, + "height": 32, + "leftMargin": 0, + "name": "Hovered", + "rightMargin": 0, + "texture": "GearButtonHovered.png", + "tiled": false, + "topMargin": 0, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "Tween", + "type": "Tween::TweenBehavior" + } + ] + }, + { + "assetStoreId": "", + "bottomMargin": 0, + "height": 32, + "leftMargin": 0, + "name": "Pressed", + "rightMargin": 0, + "texture": "GearButtonPressed.png", + "tiled": false, + "topMargin": 0, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + } + ] + }, + { + "assetStoreId": "", + "name": "BitmapLabel", + "type": "BitmapText::BitmapTextObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 4, + "topEdgeAnchor": 4, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "BitmapTextStyleState", + "type": "PanelSpriteButton::BitmapTextStyleState", + "HoverColor": "", + "HoverPrefix": "", + "HoverSuffix": "", + "IsHovered": false, + "IdleText": "", + "IdleColor": "" + } + ], + "content": { + "text": "Text", + "opacity": 255, + "scale": 1, + "fontSize": 20, + "tint": "255;255;255", + "bitmapFontResourceName": "", + "textureAtlasResourceName": "", + "align": "center", + "verticalTextAlignment": "center" + } + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "objectName": "Label" + }, + { + "objectName": "BitmapLabel" + }, + { + "objectName": "Idle" + }, + { + "objectName": "Hovered" + }, + { + "objectName": "Pressed" + } + ] + }, + "objectsGroups": [ + { + "name": "Background", + "objects": [ + { + "name": "Idle" + }, + { + "name": "Hovered" + }, + { + "name": "Pressed" + } + ] + }, + { + "name": "Labels", + "objects": [ + { + "name": "Label" + }, + { + "name": "BitmapLabel" + } + ] + } + ], + "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": 1, + "height": 64, + "layer": "", + "name": "Idle", + "persistentUuid": "24882334-eec8-403e-8bf1-70fc928a46e6", + "width": 256, + "x": 0, + "y": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 1, + "height": 64, + "layer": "", + "name": "Label", + "persistentUuid": "3b29c95c-5363-4e25-bf47-eecf13e8a226", + "width": 256, + "x": 0, + "y": 32, + "zOrder": 2, + "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": 2.734375, + "windowMask": false, + "selectedLayer": "", + "gameEditorMode": "instances-editor" + } + }, + { + "areaMaxX": 256, + "areaMaxY": 64, + "areaMaxZ": 64, + "areaMinX": 0, + "areaMinY": 0, + "areaMinZ": 0, + "name": "TileFrame", + "objects": [ + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "Label", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 4, + "topEdgeAnchor": 4, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "TextStyleState", + "type": "PanelSpriteButton::TextStyleState", + "ShouldEnableOutlineOnHover": false, + "HoverColor": "", + "ShouldEnableShadowOnHover": false, + "HoverFontSize": 0, + "IsHovered": false, + "IdleFontSize": 0, + "IdleColor": "" + } + ], + "string": "Text", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "characterSize": 36, + "color": { + "b": 255, + "g": 255, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": false, + "isShadowEnabled": false, + "italic": false, + "outlineColor": "255;255;255", + "outlineThickness": 2, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "0;0;0", + "shadowDistance": 4, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "Text", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "verticalTextAlignment": "center", + "characterSize": 36, + "lineHeight": 0, + "color": "255;255;255" + } + }, + { + "assetStoreId": "", + "bottomMargin": 28, + "height": 32, + "leftMargin": 28, + "name": "Idle", + "rightMargin": 28, + "texture": "TileIdle.png", + "tiled": false, + "topMargin": 28, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [ + { + "folded": true, + "name": "State", + "type": "string", + "value": "Idle" + } + ], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "ButtonFSM", + "type": "PanelSpriteButton::ButtonFSM", + "ShouldCheckHovering": true + } + ] + }, + { + "assetStoreId": "", + "bottomMargin": 28, + "height": 32, + "leftMargin": 28, + "name": "Hovered", + "rightMargin": 28, + "texture": "TileHovered.png", + "tiled": false, + "topMargin": 28, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "Tween", + "type": "Tween::TweenBehavior" + } + ] + }, + { + "assetStoreId": "", + "bottomMargin": 28, + "height": 32, + "leftMargin": 28, + "name": "Pressed", + "rightMargin": 28, + "texture": "TilePressed.png", + "tiled": false, + "topMargin": 28, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + } + ] + }, + { + "assetStoreId": "", + "name": "BitmapLabel", + "type": "BitmapText::BitmapTextObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 4, + "topEdgeAnchor": 4, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "useLegacyBottomAndRightAnchors": false + }, + { + "name": "BitmapTextStyleState", + "type": "PanelSpriteButton::BitmapTextStyleState", + "HoverColor": "", + "HoverPrefix": "", + "HoverSuffix": "", + "IsHovered": false, + "IdleText": "", + "IdleColor": "" + } + ], + "content": { + "text": "Text", + "opacity": 255, + "scale": 1, + "fontSize": 20, + "tint": "255;255;255", + "bitmapFontResourceName": "", + "textureAtlasResourceName": "", + "align": "center", + "verticalTextAlignment": "center" + } + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "objectName": "Label" + }, + { + "objectName": "BitmapLabel" + }, + { + "objectName": "Idle" + }, + { + "objectName": "Hovered" + }, + { + "objectName": "Pressed" + } + ] + }, + "objectsGroups": [ + { + "name": "Background", + "objects": [ + { + "name": "Idle" + }, + { + "name": "Hovered" + }, + { + "name": "Pressed" + } + ] + }, + { + "name": "Labels", + "objects": [ + { + "name": "Label" + }, + { + "name": "BitmapLabel" + } + ] + } + ], + "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": 1, + "height": 64, + "layer": "", + "name": "Idle", + "persistentUuid": "24882334-eec8-403e-8bf1-70fc928a46e6", + "width": 256, + "x": 0, + "y": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 1, + "height": 64, + "layer": "", + "name": "Label", + "persistentUuid": "3b29c95c-5363-4e25-bf47-eecf13e8a226", + "width": 256, + "x": 0, + "y": 32, + "zOrder": 2, + "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": 2.734375, + "windowMask": false, + "selectedLayer": "", + "gameEditorMode": "instances-editor" + } + } + ] + } + ] + }, + { + "author": "", + "category": "User interface", + "dimension": "", + "extensionNamespace": "", + "fullName": "Air Hockey UI", + "gdevelopVersion": "", + "helpPath": "", + "iconUrl": "", + "name": "AirHockeyUI", + "previewIconUrl": "", + "shortDescription": "Scoreboard, announcement and result menu of Air Hockey.", + "version": "1.3.1", + "description": "Custom objects for the Air Hockey interface. The scene talks to them only through their actions and conditions, never to their children.", + "tags": [], + "authorIds": [], + "dependencies": [], + "globalVariables": [], + "sceneVariables": [], + "eventsFunctions": [], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT" + }, + "eventsBasedBehaviors": [], + "eventsBasedObjects": [ + { + "areaMaxX": 900, + "areaMaxY": 150, + "areaMaxZ": 64, + "areaMinX": 0, + "areaMinY": 0, + "areaMinZ": 0, + "defaultName": "UI_Scoreboard", + "description": "Match scoreboard: two team flags and codes, the score and the period clock. Drive it with Set teams, Set score and Set clock.", + "fullName": "Scoreboard", + "helpPath": "", + "iconUrl": "", + "isUsingLegacyInstancesRenderer": false, + "name": "UI_Scoreboard", + "previewIconUrl": "", + "objects": [ + { + "adaptCollisionMaskAutomatically": true, + "assetStoreId": "", + "name": "Frame", + "type": "Sprite", + "updateIfNotVisible": false, + "variables": [], + "effects": [], + "behaviors": [], + "animations": [ + { + "name": "Idle", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "Scoreboard.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + } + ] + }, + { + "adaptCollisionMaskAutomatically": true, + "assetStoreId": "", + "name": "LeftFlag", + "type": "Sprite", + "updateIfNotVisible": false, + "variables": [], + "effects": [], + "behaviors": [], + "animations": [ + { + "name": "France", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagFrance.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "USA", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagUSA.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "Belgium", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagBelgium.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "Spain", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagSpain.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "Canada", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagCanada.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "Germany", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagGermany.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + } + ] + }, + { + "adaptCollisionMaskAutomatically": true, + "assetStoreId": "", + "name": "RightFlag", + "type": "Sprite", + "updateIfNotVisible": false, + "variables": [], + "effects": [], + "behaviors": [], + "animations": [ + { + "name": "Canada", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagCanada.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "USA", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagUSA.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "Belgium", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagBelgium.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "France", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagFrance.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "Spain", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagSpain.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "Germany", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagGermany.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + } + ] + }, + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "LeftName", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [], + "string": "FRA", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "characterSize": 52, + "color": { + "b": 255, + "g": 255, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": false, + "isShadowEnabled": true, + "italic": false, + "outlineColor": "255;255;255", + "outlineThickness": 2, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "10;20;60", + "shadowDistance": 3, + "shadowOpacity": 160, + "smoothed": true, + "underlined": false, + "text": "FRA", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "verticalTextAlignment": "center", + "characterSize": 52, + "lineHeight": 0, + "color": "255;255;255" + } + }, + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "RightName", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [], + "string": "CAN", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "characterSize": 52, + "color": { + "b": 255, + "g": 255, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": false, + "isShadowEnabled": true, + "italic": false, + "outlineColor": "255;255;255", + "outlineThickness": 2, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "10;20;60", + "shadowDistance": 3, + "shadowOpacity": 160, + "smoothed": true, + "underlined": false, + "text": "CAN", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "verticalTextAlignment": "center", + "characterSize": 52, + "lineHeight": 0, + "color": "255;255;255" + } + }, + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "Score", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [], + "string": "0 - 0", + "font": "RobotoMono-Bold.ttf", + "textAlignment": "center", + "characterSize": 64, + "color": { + "b": 255, + "g": 255, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": false, + "isShadowEnabled": false, + "italic": false, + "outlineColor": "255;255;255", + "outlineThickness": 2, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "0;0;0", + "shadowDistance": 4, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "0 - 0", + "font": "RobotoMono-Bold.ttf", + "textAlignment": "center", + "verticalTextAlignment": "center", + "characterSize": 64, + "lineHeight": 0, + "color": "255;255;255" + } + }, + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "Period", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [], + "string": "FIRST TO 5 0:00", + "font": "RobotoMono-Bold.ttf", + "textAlignment": "center", + "characterSize": 22, + "color": { + "b": 255, + "g": 255, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": false, + "isShadowEnabled": false, + "italic": false, + "outlineColor": "255;255;255", + "outlineThickness": 2, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "0;0;0", + "shadowDistance": 4, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "FIRST TO 5 0:00", + "font": "RobotoMono-Bold.ttf", + "textAlignment": "center", + "verticalTextAlignment": "center", + "characterSize": 22, + "lineHeight": 0, + "color": "255;255;255" + } + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "objectName": "Frame" + }, + { + "objectName": "LeftFlag" + }, + { + "objectName": "RightFlag" + }, + { + "objectName": "LeftName" + }, + { + "objectName": "RightName" + }, + { + "objectName": "Score" + }, + { + "objectName": "Period" + } + ] + }, + "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": false, + "height": 0, + "keepRatio": true, + "layer": "", + "name": "Frame", + "persistentUuid": "975ba439-ebd0-4a99-a8e7-7e375a4d8db0", + "width": 0, + "x": 0, + "y": 0, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 54, + "keepRatio": true, + "layer": "", + "name": "LeftFlag", + "persistentUuid": "b8b216fd-266e-4fab-b0a9-fc71806498d2", + "width": 96, + "x": 35, + "y": 46, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 54, + "keepRatio": true, + "layer": "", + "name": "RightFlag", + "persistentUuid": "1297a976-e307-42e8-9d4a-e411812d7c83", + "width": 96, + "x": 769, + "y": 46, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 76, + "keepRatio": true, + "layer": "", + "name": "LeftName", + "persistentUuid": "3583d8d3-4964-40a8-b528-7901b06c466d", + "width": 180, + "x": 135, + "y": 73, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 76, + "keepRatio": true, + "layer": "", + "name": "RightName", + "persistentUuid": "f250b1ff-88f2-4ed3-bae4-26a8a7a386a2", + "width": 180, + "x": 585, + "y": 73, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 80, + "keepRatio": true, + "layer": "", + "name": "Score", + "persistentUuid": "92e45b49-5e9e-4de8-be62-3c426fcb2347", + "width": 260, + "x": 320, + "y": 52, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 34, + "keepRatio": true, + "layer": "", + "name": "Period", + "persistentUuid": "db500763-fe53-447d-a081-36de6f3cab39", + "width": 260, + "x": 320, + "y": 110, + "zOrder": 0, + "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": 0.7777777777777778, + "windowMask": false, + "selectedLayer": "", + "gameEditorMode": "instances-editor" + }, + "eventsFunctions": [ + { + "description": "Show the flag and code of each team (country names match the flag animations, e.g. USA, Belgium).", + "fullName": "Set teams", + "functionType": "Action", + "name": "SetTeams", + "sentence": "Show _PARAM1_ (_PARAM2_) on the left and _PARAM3_ (_PARAM4_) on the right of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "AnimatableCapability::AnimatableBehavior::SetName" + }, + "parameters": [ + "LeftFlag", + "Animation", + "=", + "LeftCountry" + ] + }, + { + "type": { + "value": "AnimatableCapability::AnimatableBehavior::SetName" + }, + "parameters": [ + "RightFlag", + "Animation", + "=", + "RightCountry" + ] + }, + { + "type": { + "value": "TextContainerCapability::TextContainerBehavior::SetValue" + }, + "parameters": [ + "LeftName", + "Text", + "=", + "LeftCode" + ] + }, + { + "type": { + "value": "TextContainerCapability::TextContainerBehavior::SetValue" + }, + "parameters": [ + "RightName", + "Text", + "=", + "RightCode" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_Scoreboard", + "type": "object" + }, + { + "description": "Left country (flag animation name)", + "name": "LeftCountry", + "type": "string" + }, + { + "description": "Left team code (e.g. BEL)", + "name": "LeftCode", + "type": "string" + }, + { + "description": "Right country (flag animation name)", + "name": "RightCountry", + "type": "string" + }, + { + "description": "Right team code (e.g. USA)", + "name": "RightCode", + "type": "string" + } + ], + "objectGroups": [] + }, + { + "description": "Show the score of both teams.", + "fullName": "Set score", + "functionType": "Action", + "name": "SetScore", + "sentence": "Set the score of _PARAM0_ to _PARAM1_ - _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "TextContainerCapability::TextContainerBehavior::SetValue" + }, + "parameters": [ + "Score", + "Text", + "=", + "ToString(LeftScore) + \" - \" + ToString(RightScore)" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_Scoreboard", + "type": "object" + }, + { + "description": "Left team score", + "name": "LeftScore", + "type": "number" + }, + { + "description": "Right team score", + "name": "RightScore", + "type": "number" + } + ], + "objectGroups": [] + }, + { + "description": "Show the period label and the remaining time (m:ss).", + "fullName": "Set clock", + "functionType": "Action", + "name": "SetClock", + "sentence": "Show _PARAM1_ with _PARAM2_ seconds left on _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Leading zero for the seconds: the last two digits of 100 + seconds.", + "comment2": "Period child uses a monospaced font so the clock does not shift sideways." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "WholeSeconds", + "=", + "ceil(max(0, SecondsLeft))" + ] + }, + { + "type": { + "value": "TextContainerCapability::TextContainerBehavior::SetValue" + }, + "parameters": [ + "Period", + "Text", + "=", + "PeriodLabel + \" \" + ToString(floor(WholeSeconds / 60)) + \":\" + SubStr(ToString(100 + mod(WholeSeconds, 60)), 1, 2)" + ] + } + ], + "variables": [ + { + "name": "WholeSeconds", + "type": "number", + "value": 0 + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_Scoreboard", + "type": "object" + }, + { + "description": "Period label (e.g. 1ST PERIOD)", + "name": "PeriodLabel", + "type": "string" + }, + { + "description": "Remaining seconds", + "name": "SecondsLeft", + "type": "number" + } + ], + "objectGroups": [] + }, + { + "description": "Intro animation of the scoreboard: at 0 the left team (flag + name) is off to the left, the right team off to the right and the frame, score and clock are transparent; at 1 everything is in place.", + "fullName": "Set the intro slide progress", + "functionType": "Action", + "name": "SetIntroSlide", + "sentence": "Set the intro slide of _PARAM0_ to _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "// Slide the two teams in from the sides and fade in the centre of the scoreboard.", + "// Children base X positions are remembered the first time (variant layout = final layout).", + "const progress = Math.max(0, Math.min(1, eventsFunctionContext.getArgument(\"Progress\")));", + "const eased = 1 - Math.pow(1 - progress, 3);", + "const slideDistance = (1 - eased) * 1400;", + "const fadeOpacity = 255 * eased;", + "for (const scoreboard of objects) {", + " const children = scoreboard.getChildrenContainer();", + " const moveChildren = (childName, direction) => {", + " for (const child of children.getObjects(childName)) {", + " if (child.__introBaseX === undefined) child.__introBaseX = child.getX();", + " child.setX(child.__introBaseX + direction * slideDistance);", + " }", + " };", + " moveChildren(\"LeftFlag\", -1);", + " moveChildren(\"LeftName\", -1);", + " moveChildren(\"RightFlag\", 1);", + " moveChildren(\"RightName\", 1);", + " for (const childName of [\"Frame\", \"Score\", \"Period\"]) {", + " for (const child of children.getObjects(childName)) {", + " if (child.setOpacity) child.setOpacity(fadeOpacity);", + " }", + " }", + "}" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_Scoreboard", + "type": "object" + }, + { + "description": "Progress, from 0 (teams off screen) to 1 (scoreboard formed)", + "name": "Progress", + "type": "expression" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "SetTeams" + }, + { + "functionName": "SetScore" + }, + { + "functionName": "SetClock" + }, + { + "functionName": "SetIntroSlide" + } + ] + }, + "propertyDescriptors": [], + "propertiesFolderStructure": { + "folderName": "__ROOT" + }, + "variants": [] + }, + { + "areaMaxX": 1200, + "areaMaxY": 200, + "areaMaxZ": 64, + "areaMinX": 0, + "areaMinY": 0, + "areaMinZ": 0, + "defaultName": "UI_Announcement", + "description": "Big centred message (GOAL!, 1ST PERIOD...). Show message / Hide message; condition Is showing.", + "fullName": "Announcement", + "helpPath": "", + "iconUrl": "", + "isUsingLegacyInstancesRenderer": false, + "name": "UI_Announcement", + "previewIconUrl": "", + "objects": [ + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "Label", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [], + "string": "GOAL!", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "characterSize": 140, + "color": { + "b": 255, + "g": 255, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": true, + "isShadowEnabled": true, + "italic": false, + "outlineColor": "30;40;110", + "outlineThickness": 8, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "10;20;60", + "shadowDistance": 3, + "shadowOpacity": 160, + "smoothed": true, + "underlined": false, + "text": "GOAL!", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "verticalTextAlignment": "center", + "characterSize": 140, + "lineHeight": 0, + "color": "255;255;255" + } + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "objectName": "Label" + } + ] + }, + "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, + "height": 200, + "keepRatio": true, + "layer": "", + "name": "Label", + "persistentUuid": "ffe13c64-7489-4b4b-aafb-93bbbf469384", + "width": 1200, + "x": 0, + "y": 100, + "zOrder": 0, + "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": 0.5833333333333334, + "windowMask": false, + "selectedLayer": "", + "gameEditorMode": "instances-editor" + }, + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "onCreated", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Hide" + }, + "parameters": [ + "Label" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_Announcement", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Show a big centred message.", + "fullName": "Show message", + "functionType": "Action", + "name": "ShowMessage", + "sentence": "Show _PARAM1_ on _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "TextContainerCapability::TextContainerBehavior::SetValue" + }, + "parameters": [ + "Label", + "Text", + "=", + "Message" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "Label", + "" + ] + }, + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "IsShowing", + "True", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_Announcement", + "type": "object" + }, + { + "description": "Message", + "name": "Message", + "type": "string" + } + ], + "objectGroups": [] + }, + { + "description": "Hide the message.", + "fullName": "Hide message", + "functionType": "Action", + "name": "HideMessage", + "sentence": "Hide the message of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Hide" + }, + "parameters": [ + "Label" + ] + }, + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "IsShowing", + "False", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_Announcement", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Check if a message is shown.", + "fullName": "Is showing", + "functionType": "Condition", + "name": "IsShowing", + "sentence": "_PARAM0_ shows a message", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsShowing", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_Announcement", + "type": "object" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "onCreated" + }, + { + "functionName": "ShowMessage" + }, + { + "functionName": "HideMessage" + }, + { + "functionName": "IsShowing" + } + ] + }, + "propertyDescriptors": [ + { + "value": "false", + "type": "Boolean", + "label": "Showing", + "hidden": true, + "name": "IsShowing" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "propertyName": "IsShowing" + } + ] + }, + "variants": [] + }, + { + "areaMaxX": 700, + "areaMaxY": 460, + "areaMaxZ": 64, + "areaMinX": 0, + "areaMinY": 0, + "areaMinZ": 0, + "defaultName": "UI_ResultMenu", + "description": "End-of-match panel with a title, the final score and a Play again button. Open / Close; conditions Is open and Is replay clicked (only true while open).", + "fullName": "Result menu", + "helpPath": "", + "iconUrl": "", + "isUsingLegacyInstancesRenderer": false, + "name": "UI_ResultMenu", + "previewIconUrl": "", + "objects": [ + { + "adaptCollisionMaskAutomatically": true, + "assetStoreId": "", + "name": "Panel", + "type": "Sprite", + "updateIfNotVisible": false, + "variables": [], + "effects": [], + "behaviors": [], + "animations": [ + { + "name": "Idle", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "ResultPanel.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + } + ] + }, + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "Title", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [], + "string": "YOU WIN!", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "characterSize": 90, + "color": { + "b": 255, + "g": 255, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": true, + "isShadowEnabled": true, + "italic": false, + "outlineColor": "30;40;110", + "outlineThickness": 6, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "10;20;60", + "shadowDistance": 3, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "YOU WIN!", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "verticalTextAlignment": "center", + "characterSize": 90, + "lineHeight": 0, + "color": "255;255;255" + } + }, + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "FinalScore", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [], + "string": "USA 3 - 1 BEL", + "font": "RobotoMono-Bold.ttf", + "textAlignment": "center", + "characterSize": 50, + "color": { + "b": 255, + "g": 255, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": false, + "isShadowEnabled": false, + "italic": false, + "outlineColor": "255;255;255", + "outlineThickness": 2, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "0;0;0", + "shadowDistance": 4, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "USA 3 - 1 BEL", + "font": "RobotoMono-Bold.ttf", + "textAlignment": "center", + "verticalTextAlignment": "center", + "characterSize": 50, + "lineHeight": 0, + "color": "255;255;255" + } + }, + { + "assetStoreId": "", + "name": "ReplayButton", + "type": "PanelSpriteButton::PanelSpriteButton", + "variant": "Primary", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "LabelText": "PLAY AGAIN" + } + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "objectName": "Panel" + }, + { + "objectName": "Title" + }, + { + "objectName": "FinalScore" + }, + { + "objectName": "ReplayButton" + } + ] + }, + "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": false, + "height": 0, + "keepRatio": true, + "layer": "", + "name": "Panel", + "persistentUuid": "12731dc5-0edb-4265-b063-ed202f4b2acb", + "width": 0, + "x": 0, + "y": 0, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 110, + "keepRatio": true, + "layer": "", + "name": "Title", + "persistentUuid": "2b30c602-b370-4da8-aea2-a1d002c3efea", + "width": 700, + "x": 0, + "y": 95, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 70, + "keepRatio": true, + "layer": "", + "name": "FinalScore", + "persistentUuid": "82cfb63e-6cd5-41a2-9231-ff7a4329434c", + "width": 700, + "x": 0, + "y": 200, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 110, + "keepRatio": true, + "layer": "", + "name": "ReplayButton", + "persistentUuid": "4fa854cc-232f-4153-b28b-49272d0d1de9", + "width": 420, + "x": 140, + "y": 290, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + } + ], + "editionSettings": {}, + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "onCreated", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Hide" + }, + "parameters": [ + "Panel" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "Title" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "FinalScore" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "ReplayButton" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "ReplayButton", + "no", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_ResultMenu", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Show the result menu with a title and the final score line.", + "fullName": "Open", + "functionType": "Action", + "name": "Open", + "sentence": "Open _PARAM0_ with title _PARAM1_ and score _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "TextContainerCapability::TextContainerBehavior::SetValue" + }, + "parameters": [ + "Title", + "Text", + "=", + "TitleText" + ] + }, + { + "type": { + "value": "TextContainerCapability::TextContainerBehavior::SetValue" + }, + "parameters": [ + "FinalScore", + "Text", + "=", + "ScoreLine" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "Panel", + "" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "Title", + "" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "FinalScore", + "" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "ReplayButton", + "" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "ReplayButton", + "yes", + "" + ] + }, + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "IsOpen", + "True", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_ResultMenu", + "type": "object" + }, + { + "description": "Title (e.g. VICTORY!)", + "name": "TitleText", + "type": "string" + }, + { + "description": "Final score line", + "name": "ScoreLine", + "type": "string" + } + ], + "objectGroups": [] + }, + { + "description": "Hide the result menu; its button stops responding.", + "fullName": "Close", + "functionType": "Action", + "name": "Close", + "sentence": "Close _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Hide" + }, + "parameters": [ + "Panel" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "Title" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "FinalScore" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "ReplayButton" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "ReplayButton", + "no", + "" + ] + }, + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "IsOpen", + "False", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_ResultMenu", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Check if the result menu is open.", + "fullName": "Is open", + "functionType": "Condition", + "name": "IsOpen", + "sentence": "_PARAM0_ is open", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsOpen", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_ResultMenu", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Check if Play again was just clicked while the menu is open.", + "fullName": "Is replay clicked", + "functionType": "Condition", + "name": "IsReplayClicked", + "sentence": "Play again of _PARAM0_ is clicked", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsOpen", + "True", + "" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::IsClicked" + }, + "parameters": [ + "ReplayButton", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_ResultMenu", + "type": "object" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "onCreated" + }, + { + "functionName": "Close" + }, + { + "functionName": "IsOpen" + }, + { + "functionName": "IsReplayClicked" + }, + { + "functionName": "Open" + } + ] + }, + "propertyDescriptors": [ + { + "value": "false", + "type": "Boolean", + "label": "Open", + "hidden": true, + "name": "IsOpen" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "propertyName": "IsOpen" + } + ] + }, + "variants": [] + }, + { + "areaMaxX": 1920, + "areaMaxY": 1080, + "areaMaxZ": 64, + "areaMinX": 0, + "areaMinY": 0, + "areaMinZ": 0, + "defaultName": "UI_OptionsModal", + "description": "Full-screen options window: master volume and mallet sensitivity (- / + buttons), a button to the promo window, a close button. Call Open(volume, sensitivity), read Volume() / Sensitivity(), test IsOpen / IsPromoClicked. Values are per object instance.", + "fullName": "Options modal", + "helpPath": "", + "iconUrl": "", + "isUsingLegacyInstancesRenderer": false, + "name": "UI_OptionsModal", + "previewIconUrl": "", + "objects": [ + { + "assetStoreId": "", + "bottomMargin": 0, + "height": 32, + "leftMargin": 0, + "name": "Scrim", + "persistentUuid": "97bd343a-c390-4e04-864b-70ba07a485a3", + "rightMargin": 0, + "texture": "ModalScrim.png", + "tiled": false, + "topMargin": 0, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [], + "effects": [], + "behaviors": [] + }, + { + "assetStoreId": "", + "bottomMargin": 60, + "height": 32, + "leftMargin": 60, + "name": "Panel", + "rightMargin": 60, + "texture": "ModalPanel.png", + "tiled": false, + "topMargin": 60, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [], + "effects": [], + "behaviors": [] + }, + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "Title", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [], + "string": "OPTIONS", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "characterSize": 80, + "color": { + "b": 255, + "g": 255, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": true, + "isShadowEnabled": false, + "italic": false, + "outlineColor": "30;40;110", + "outlineThickness": 7, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "0;0;0", + "shadowDistance": 4, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "OPTIONS", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "verticalTextAlignment": "top", + "characterSize": 80, + "lineHeight": 0, + "color": "255;255;255" + } + }, + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "VolumeLabel", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [], + "string": "SOUND", + "font": "Coiny-Regular.ttf", + "textAlignment": "left", + "characterSize": 44, + "color": { + "b": 255, + "g": 255, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": false, + "isShadowEnabled": false, + "italic": false, + "outlineColor": "255;255;255", + "outlineThickness": 2, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "0;0;0", + "shadowDistance": 4, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "SOUND", + "font": "Coiny-Regular.ttf", + "textAlignment": "left", + "verticalTextAlignment": "top", + "characterSize": 44, + "lineHeight": 0, + "color": "255;255;255" + } + }, + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "SensitivityLabel", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [], + "string": "MALLET SPEED", + "font": "Coiny-Regular.ttf", + "textAlignment": "left", + "characterSize": 44, + "color": { + "b": 255, + "g": 255, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": false, + "isShadowEnabled": false, + "italic": false, + "outlineColor": "255;255;255", + "outlineThickness": 2, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "0;0;0", + "shadowDistance": 4, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "MALLET SPEED", + "font": "Coiny-Regular.ttf", + "textAlignment": "left", + "verticalTextAlignment": "top", + "characterSize": 44, + "lineHeight": 0, + "color": "255;255;255" + } + }, + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "VolumeValue", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [], + "string": "80%", + "font": "RobotoMono-Bold.ttf", + "textAlignment": "center", + "characterSize": 50, + "color": { + "b": 80, + "g": 210, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": false, + "isShadowEnabled": false, + "italic": false, + "outlineColor": "255;255;255", + "outlineThickness": 2, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "0;0;0", + "shadowDistance": 4, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "80%", + "font": "RobotoMono-Bold.ttf", + "textAlignment": "center", + "verticalTextAlignment": "top", + "characterSize": 50, + "lineHeight": 0, + "color": "255;210;80" + } + }, + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "SensitivityValue", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [], + "string": "8", + "font": "RobotoMono-Bold.ttf", + "textAlignment": "center", + "characterSize": 50, + "color": { + "b": 80, + "g": 210, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": false, + "isShadowEnabled": false, + "italic": false, + "outlineColor": "255;255;255", + "outlineThickness": 2, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "0;0;0", + "shadowDistance": 4, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "8", + "font": "RobotoMono-Bold.ttf", + "textAlignment": "center", + "verticalTextAlignment": "top", + "characterSize": 50, + "lineHeight": 0, + "color": "255;210;80" + } + }, + { + "assetStoreId": "", + "name": "VolumeDownButton", + "type": "PanelSpriteButton::PanelSpriteButton", + "variant": "Stepper", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "LabelText": "-" + } + }, + { + "assetStoreId": "", + "name": "VolumeUpButton", + "type": "PanelSpriteButton::PanelSpriteButton", + "variant": "Stepper", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "LabelText": "+" + } + }, + { + "assetStoreId": "", + "name": "SensitivityDownButton", + "type": "PanelSpriteButton::PanelSpriteButton", + "variant": "Stepper", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "LabelText": "-" + } + }, + { + "assetStoreId": "", + "name": "SensitivityUpButton", + "type": "PanelSpriteButton::PanelSpriteButton", + "variant": "Stepper", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "LabelText": "+" + } + }, + { + "assetStoreId": "", + "name": "CloseButton", + "type": "PanelSpriteButton::PanelSpriteButton", + "variant": "Close", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "LabelText": "X" + } + }, + { + "assetStoreId": "", + "name": "BackButton", + "type": "PanelSpriteButton::PanelSpriteButton", + "variant": "Secondary", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "LabelText": "BACK" + } + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "objectName": "Scrim" + }, + { + "objectName": "Panel" + }, + { + "objectName": "Title" + }, + { + "objectName": "VolumeLabel" + }, + { + "objectName": "SensitivityLabel" + }, + { + "objectName": "VolumeValue" + }, + { + "objectName": "SensitivityValue" + }, + { + "objectName": "VolumeDownButton" + }, + { + "objectName": "VolumeUpButton" + }, + { + "objectName": "SensitivityDownButton" + }, + { + "objectName": "SensitivityUpButton" + }, + { + "objectName": "CloseButton" + }, + { + "objectName": "BackButton" + } + ] + }, + "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, + "height": 3080, + "keepRatio": true, + "layer": "", + "name": "Scrim", + "persistentUuid": "45aa683b-f66a-4dd0-b235-a4992b1c82da", + "width": 5920, + "x": -2000, + "y": -1000, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 605, + "keepRatio": true, + "layer": "", + "name": "Panel", + "persistentUuid": "d89b9db3-921f-491a-b158-6744d98de1ca", + "width": 800, + "x": 560, + "y": 270, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 0, + "keepRatio": true, + "layer": "", + "name": "Title", + "persistentUuid": "6bcfe6d8-5e9b-4610-a1e2-685f95ea741f", + "width": 800, + "x": 560, + "y": 305, + "zOrder": 2, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 90, + "keepRatio": true, + "layer": "", + "name": "CloseButton", + "persistentUuid": "909a2eb4-59f2-4969-b9a7-f1363d544203", + "width": 90, + "x": 1250, + "y": 290, + "zOrder": 3, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "", + "name": "VolumeLabel", + "persistentUuid": "0ca12811-b48c-49c2-9735-de55fca61727", + "width": 0, + "x": 605, + "y": 455, + "zOrder": 2, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 90, + "keepRatio": true, + "layer": "", + "name": "VolumeDownButton", + "persistentUuid": "9cc57c00-9931-42f2-a6b7-78c5a8287289", + "width": 90, + "x": 985, + "y": 440, + "zOrder": 3, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 0, + "keepRatio": true, + "layer": "", + "name": "VolumeValue", + "persistentUuid": "d870ab58-7524-42cb-a2d2-0d062893f0df", + "width": 140, + "x": 1080, + "y": 455, + "zOrder": 2, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 90, + "keepRatio": true, + "layer": "", + "name": "VolumeUpButton", + "persistentUuid": "bb267e28-50a6-430b-970a-dd38463ee6da", + "width": 90, + "x": 1225, + "y": 440, + "zOrder": 3, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "", + "name": "SensitivityLabel", + "persistentUuid": "92721bd0-481a-4f13-a15f-923cb30675c9", + "width": 0, + "x": 605, + "y": 590, + "zOrder": 2, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 90, + "keepRatio": true, + "layer": "", + "name": "SensitivityDownButton", + "persistentUuid": "3c236e6c-2ad6-4e3b-aaf4-d1861264fb26", + "width": 90, + "x": 985, + "y": 575, + "zOrder": 3, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 0, + "keepRatio": true, + "layer": "", + "name": "SensitivityValue", + "persistentUuid": "1e253549-fda3-41ed-95f0-fd72f4bef099", + "width": 140, + "x": 1080, + "y": 590, + "zOrder": 2, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 90, + "keepRatio": true, + "layer": "", + "name": "SensitivityUpButton", + "persistentUuid": "9a226939-5ae5-40be-9a58-3122ac3921ca", + "width": 90, + "x": 1225, + "y": 575, + "zOrder": 3, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 90, + "keepRatio": true, + "layer": "", + "name": "BackButton", + "persistentUuid": "f2f9c0a7-9a9f-4a90-a9f4-75330231a298", + "width": 320, + "x": 800, + "y": 710, + "zOrder": 3, + "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": 0.3645833333333333, + "windowMask": false, + "selectedLayer": "", + "gameEditorMode": "instances-editor" + }, + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "onCreated", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "The window starts closed, without its BACK button (only the match shows it). Centred texts get a fixed width.", + "comment2": "Wrapping widths match the instance widths placed in the variant. SetBackButtonVisible(no) shrinks the panel by the BACK row." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "TextObject::SetWrapping" + }, + "parameters": [ + "Title", + "yes" + ] + }, + { + "type": { + "value": "TextObject::WrappingWidth" + }, + "parameters": [ + "Title", + "=", + "800" + ] + }, + { + "type": { + "value": "TextObject::SetWrapping" + }, + "parameters": [ + "VolumeValue", + "yes" + ] + }, + { + "type": { + "value": "TextObject::WrappingWidth" + }, + "parameters": [ + "VolumeValue", + "=", + "140" + ] + }, + { + "type": { + "value": "TextObject::SetWrapping" + }, + "parameters": [ + "SensitivityValue", + "yes" + ] + }, + { + "type": { + "value": "TextObject::WrappingWidth" + }, + "parameters": [ + "SensitivityValue", + "=", + "140" + ] + }, + { + "type": { + "value": "AirHockeyUI::UI_OptionsModal::Close" + }, + "parameters": [ + "Object", + "" + ] + }, + { + "type": { + "value": "AirHockeyUI::UI_OptionsModal::SetBackButtonVisible" + }, + "parameters": [ + "Object", + "no", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_OptionsModal", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "doStepPostEvents", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Runs after the scene events: the scene applies a change the next frame.", + "comment2": "OptionsMenu reads Volume() / Sensitivity() and compares them to Settings." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsOpen", + "True", + "" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::IsClicked" + }, + "parameters": [ + "VolumeDownButton", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Volume", + "=", + "max(0, Volume - 10)" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::IsClicked" + }, + "parameters": [ + "VolumeUpButton", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Volume", + "=", + "min(100, Volume + 10)" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::IsClicked" + }, + "parameters": [ + "SensitivityDownButton", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Sensitivity", + "=", + "max(1, Sensitivity - 1)" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::IsClicked" + }, + "parameters": [ + "SensitivityUpButton", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Sensitivity", + "=", + "min(10, Sensitivity + 1)" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "TextContainerCapability::TextContainerBehavior::SetValue" + }, + "parameters": [ + "VolumeValue", + "Text", + "=", + "ToString(Volume) + \"%\"" + ] + }, + { + "type": { + "value": "TextContainerCapability::TextContainerBehavior::SetValue" + }, + "parameters": [ + "SensitivityValue", + "Text", + "=", + "ToString(Sensitivity)" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::IsClicked" + }, + "parameters": [ + "CloseButton", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "AirHockeyUI::UI_OptionsModal::Close" + }, + "parameters": [ + "Object", + "" + ] + } + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_OptionsModal", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Show the options window with the current settings.", + "fullName": "Open the options", + "functionType": "Action", + "name": "Open", + "sentence": "Open the options of _PARAM0_ (volume _PARAM1_, sensitivity _PARAM2_)", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Volume", + "=", + "clamp(round(StartVolume), 0, 100)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Sensitivity", + "=", + "clamp(round(StartSensitivity), 1, 10)" + ] + }, + { + "type": { + "value": "TextContainerCapability::TextContainerBehavior::SetValue" + }, + "parameters": [ + "VolumeValue", + "Text", + "=", + "ToString(Volume) + \"%\"" + ] + }, + { + "type": { + "value": "TextContainerCapability::TextContainerBehavior::SetValue" + }, + "parameters": [ + "SensitivityValue", + "Text", + "=", + "ToString(Sensitivity)" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "Scrim", + "" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "Panel", + "" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "Title", + "" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "VolumeLabel", + "" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "VolumeValue", + "" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "SensitivityLabel", + "" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "SensitivityValue", + "" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "VolumeDownButton", + "" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "VolumeUpButton", + "" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "SensitivityDownButton", + "" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "SensitivityUpButton", + "" + ] + }, + { + "type": { + "value": "Show" + }, + "parameters": [ + "CloseButton", + "" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "VolumeDownButton", + "yes", + "" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "VolumeUpButton", + "yes", + "" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "SensitivityDownButton", + "yes", + "" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "SensitivityUpButton", + "yes", + "" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "CloseButton", + "yes", + "" + ] + }, + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "IsOpen", + "True", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsBackButtonVisible", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "Show" + }, + "parameters": [ + "BackButton", + "" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "BackButton", + "yes", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_OptionsModal", + "type": "object" + }, + { + "description": "Volume (0-100)", + "name": "StartVolume", + "type": "expression" + }, + { + "description": "Mallet sensitivity (1-10)", + "name": "StartSensitivity", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Hide the options window.", + "fullName": "Close the options", + "functionType": "Action", + "name": "Close", + "sentence": "Close the options of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Hidden buttons can still be clicked: switch them off too.", + "comment2": "Buttons deactivated (Activate no), never moved away. IsOpen property = single source of the open state." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Hide" + }, + "parameters": [ + "Scrim" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "Panel" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "Title" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "VolumeLabel" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "VolumeValue" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "SensitivityLabel" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "SensitivityValue" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "VolumeDownButton" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "VolumeUpButton" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "SensitivityDownButton" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "SensitivityUpButton" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "CloseButton" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "VolumeDownButton", + "no", + "" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "VolumeUpButton", + "no", + "" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "SensitivityDownButton", + "no", + "" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "SensitivityUpButton", + "no", + "" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "CloseButton", + "no", + "" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "BackButton" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "BackButton", + "no", + "" + ] + }, + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "IsOpen", + "False", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_OptionsModal", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Check if the options window is open.", + "fullName": "Options open", + "functionType": "Condition", + "name": "IsOpen", + "sentence": "_PARAM0_ is open", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsOpen", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_OptionsModal", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Volume chosen in the window (0-100).", + "fullName": "Volume", + "functionType": "Expression", + "name": "Volume", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Volume" + ] + } + ] + } + ], + "expressionType": { + "type": "number" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_OptionsModal", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Mallet sensitivity chosen in the window (1-10).", + "fullName": "Mallet sensitivity", + "functionType": "Expression", + "name": "Sensitivity", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Sensitivity" + ] + } + ] + } + ], + "expressionType": { + "type": "number" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_OptionsModal", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Show the BACK button (leave the match for the menu) in the window, the panel growing to hold it, or hide it.", + "fullName": "Show or hide the BACK button", + "functionType": "Action", + "name": "SetBackButtonVisible", + "sentence": "Show the BACK button of _PARAM0_: _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "The panel grows by one row when the BACK button is shown and shrinks back when it is hidden, so the menu window has no empty row.", + "comment2": "Row height read from the variant layout: bottom of SensitivityUpButton to bottom of BackButton. IsBackButtonVisible guards the resize (repeated calls change nothing); default true = panel as laid out in the variant." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "BackRowHeight", + "=", + "BackButton.Y() + BackButton.Height() - SensitivityUpButton.Y() - SensitivityUpButton.Height()" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Visible", + "True", + "" + ] + }, + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsBackButtonVisible", + "False", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "IsBackButtonVisible", + "True", + "" + ] + }, + { + "type": { + "value": "ResizableCapability::ResizableBehavior::SetHeight" + }, + "parameters": [ + "Panel", + "Resizable", + "+", + "BackRowHeight" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Visible", + "False", + "" + ] + }, + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsBackButtonVisible", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "IsBackButtonVisible", + "False", + "" + ] + }, + { + "type": { + "value": "ResizableCapability::ResizableBehavior::SetHeight" + }, + "parameters": [ + "Panel", + "Resizable", + "-", + "BackRowHeight" + ] + } + ] + } + ], + "variables": [ + { + "name": "BackRowHeight", + "type": "number", + "value": 0 + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsOpen", + "True", + "" + ] + }, + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsBackButtonVisible", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "Show" + }, + "parameters": [ + "BackButton", + "" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "BackButton", + "yes", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [], + "actions": [ + { + "type": { + "value": "Hide" + }, + "parameters": [ + "BackButton" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "BackButton", + "no", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_OptionsModal", + "type": "object" + }, + { + "description": "Show the BACK button", + "name": "Visible", + "type": "yesorno" + } + ], + "objectGroups": [] + }, + { + "description": "Check if the BACK button of the open window was clicked.", + "fullName": "BACK button clicked", + "functionType": "Condition", + "name": "IsBackClicked", + "sentence": "The BACK button of _PARAM0_ is clicked", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsOpen", + "True", + "" + ] + }, + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::IsClicked" + }, + "parameters": [ + "BackButton", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_OptionsModal", + "type": "object" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "onCreated" + }, + { + "functionName": "doStepPostEvents" + }, + { + "functionName": "Open" + }, + { + "functionName": "Close" + }, + { + "functionName": "IsOpen" + }, + { + "functionName": "Volume" + }, + { + "functionName": "Sensitivity" + }, + { + "functionName": "SetBackButtonVisible" + }, + { + "functionName": "IsBackClicked" + } + ] + }, + "propertyDescriptors": [ + { + "value": "false", + "type": "Boolean", + "label": "Open", + "hidden": true, + "name": "IsOpen" + }, + { + "value": "80", + "type": "Number", + "label": "Volume (0-100)", + "hidden": true, + "name": "Volume" + }, + { + "value": "8", + "type": "Number", + "label": "Mallet sensitivity (1-10)", + "hidden": true, + "name": "Sensitivity" + }, + { + "value": "true", + "type": "Boolean", + "label": "BACK button shown (panel sized for it)", + "hidden": true, + "name": "IsBackButtonVisible" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "propertyName": "IsOpen" + }, + { + "propertyName": "Volume" + }, + { + "propertyName": "Sensitivity" + }, + { + "propertyName": "IsBackButtonVisible" + } + ] + }, + "variants": [] + }, + { + "areaMaxX": 240, + "areaMaxY": 170, + "areaMaxZ": 64, + "areaMinX": 0, + "areaMinY": 0, + "areaMinZ": 0, + "defaultName": "UI_CountryTile", + "description": "Clickable flag tile of the team select roster: flag, country code, and a yellow (player) or red (opponent) highlight. SetCountry(country, code, index), SetHighlight(\"Player\"|\"Opponent\"|\"None\"), condition IsClicked, expressions Country(), Index().", + "fullName": "Country tile", + "helpPath": "", + "iconUrl": "", + "isUsingLegacyInstancesRenderer": false, + "name": "UI_CountryTile", + "previewIconUrl": "", + "objects": [ + { + "adaptCollisionMaskAutomatically": true, + "assetStoreId": "", + "name": "Flag", + "type": "Sprite", + "updateIfNotVisible": false, + "variables": [], + "effects": [], + "behaviors": [], + "animations": [ + { + "name": "USA", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagUSA.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "Belgium", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagBelgium.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "France", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagFrance.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "Spain", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagSpain.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "Canada", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagCanada.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + }, + { + "name": "Germany", + "useMultipleDirections": false, + "directions": [ + { + "looping": true, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "FlagGermany.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [] + } + ] + } + ] + } + ] + }, + { + "assetStoreId": "", + "bold": false, + "italic": false, + "name": "Code", + "smoothed": true, + "type": "TextObject::Text", + "underlined": false, + "variables": [], + "effects": [], + "behaviors": [], + "string": "USA", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "characterSize": 32, + "color": { + "b": 255, + "g": 255, + "r": 255 + }, + "content": { + "bold": false, + "isOutlineEnabled": false, + "isShadowEnabled": false, + "italic": false, + "outlineColor": "255;255;255", + "outlineThickness": 2, + "shadowAngle": 90, + "shadowBlurRadius": 2, + "shadowColor": "0;0;0", + "shadowDistance": 4, + "shadowOpacity": 127, + "smoothed": true, + "underlined": false, + "text": "USA", + "font": "Coiny-Regular.ttf", + "textAlignment": "center", + "verticalTextAlignment": "top", + "characterSize": 32, + "lineHeight": 0, + "color": "255;255;255" + } + }, + { + "assetStoreId": "", + "bottomMargin": 28, + "height": 32, + "leftMargin": 28, + "name": "SelectedFrame", + "rightMargin": 28, + "texture": "TileSelected.png", + "tiled": false, + "topMargin": 28, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + } + ] + }, + { + "assetStoreId": "", + "bottomMargin": 28, + "height": 32, + "leftMargin": 28, + "name": "OpponentFrame", + "rightMargin": 28, + "texture": "TileOpponent.png", + "tiled": false, + "topMargin": 28, + "type": "PanelSpriteObject::PanelSprite", + "width": 32, + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + } + ] + }, + { + "assetStoreId": "", + "name": "Button", + "type": "PanelSpriteButton::PanelSpriteButton", + "variant": "TileFrame", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Anchor", + "type": "AnchorBehavior::AnchorBehavior", + "bottomEdgeAnchor": 2, + "leftEdgeAnchor": 1, + "relativeToOriginalWindowSize": true, + "rightEdgeAnchor": 2, + "topEdgeAnchor": 1, + "useLegacyBottomAndRightAnchors": false + } + ], + "content": { + "LabelText": "" + } + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "objectName": "Flag" + }, + { + "objectName": "Code" + }, + { + "objectName": "SelectedFrame" + }, + { + "objectName": "OpponentFrame" + }, + { + "objectName": "Button" + } + ] + }, + "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, + "height": 104, + "keepRatio": true, + "layer": "", + "name": "Flag", + "persistentUuid": "fc232c37-617a-4f96-a8fd-89877c5e5e91", + "width": 196, + "x": 22, + "y": 14, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 0, + "keepRatio": true, + "layer": "", + "name": "Code", + "persistentUuid": "25922779-7a49-4f88-9493-5dfadd4578cf", + "width": 240, + "x": 0, + "y": 122, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 170, + "keepRatio": true, + "layer": "", + "name": "SelectedFrame", + "persistentUuid": "5795f259-75b7-454e-aadf-8972f6209641", + "width": 240, + "x": 0, + "y": 0, + "zOrder": 2, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 170, + "keepRatio": true, + "layer": "", + "name": "OpponentFrame", + "persistentUuid": "3faf8567-a085-4aac-bde5-991cd3943cf0", + "width": 240, + "x": 0, + "y": 0, + "zOrder": 3, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 170, + "keepRatio": true, + "layer": "", + "name": "Button", + "persistentUuid": "2be274a5-e01b-419b-9d39-de347499b22a", + "width": 240, + "x": 0, + "y": 0, + "zOrder": 4, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + } + ], + "editionSettings": {}, + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "onCreated", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 46, + "g": 37, + "r": 37, + "textB": 140, + "textG": 136, + "textR": 136 + }, + "comment": "Wrapping gives the centred code text a box as wide as the tile (240 px), so it stays centred under the flag.", + "comment2": "Code child is center-aligned; without wrapping its box shrinks to the text and the alignment has no effect." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "TextObject::SetWrapping" + }, + "parameters": [ + "Code", + "yes" + ] + }, + { + "type": { + "value": "TextObject::WrappingWidth" + }, + "parameters": [ + "Code", + "=", + "240" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "SelectedFrame" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "OpponentFrame" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_CountryTile", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Show a country on the tile.", + "fullName": "Set the country", + "functionType": "Action", + "name": "SetCountry", + "sentence": "Show _PARAM1_ (_PARAM2_, index _PARAM3_) on _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Country", + "=", + "CountryName" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Index", + "=", + "CountryIndex" + ] + }, + { + "type": { + "value": "AnimatableCapability::AnimatableBehavior::SetName" + }, + "parameters": [ + "Flag", + "Animation", + "=", + "CountryName" + ] + }, + { + "type": { + "value": "TextContainerCapability::TextContainerBehavior::SetValue" + }, + "parameters": [ + "Code", + "Text", + "=", + "CountryCode" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_CountryTile", + "type": "object" + }, + { + "description": "Country (flag animation name)", + "name": "CountryName", + "type": "string" + }, + { + "description": "Three-letter code shown under the flag", + "name": "CountryCode", + "type": "string" + }, + { + "description": "Index in the country list", + "name": "CountryIndex", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Frame the tile: Player (yellow), Opponent (red) or None.", + "fullName": "Highlight", + "functionType": "Action", + "name": "SetHighlight", + "sentence": "Highlight _PARAM0_ as _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Hide" + }, + "parameters": [ + "SelectedFrame" + ] + }, + { + "type": { + "value": "Hide" + }, + "parameters": [ + "OpponentFrame" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareStrings" + }, + "parameters": [ + "HighlightKind", + "=", + "\"Player\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "Show" + }, + "parameters": [ + "SelectedFrame", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareStrings" + }, + "parameters": [ + "HighlightKind", + "=", + "\"Opponent\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "Show" + }, + "parameters": [ + "OpponentFrame", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_CountryTile", + "type": "object" + }, + { + "description": "Player, Opponent or None", + "name": "HighlightKind", + "type": "string" + } + ], + "objectGroups": [] + }, + { + "description": "Switch the tile button on or off.", + "fullName": "Clickable", + "functionType": "Action", + "name": "SetClickable", + "sentence": "Make _PARAM0_ clickable: _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "ShouldBeClickable", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "Button", + "yes", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Else", + "conditions": [], + "actions": [ + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::Activate" + }, + "parameters": [ + "Button", + "no", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_CountryTile", + "type": "object" + }, + { + "description": "Clickable", + "name": "ShouldBeClickable", + "type": "yesorno" + } + ], + "objectGroups": [] + }, + { + "description": "Check if the tile was clicked.", + "fullName": "Tile clicked", + "functionType": "Condition", + "name": "IsClicked", + "sentence": "_PARAM0_ is clicked", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "PanelSpriteButton::PanelSpriteButton::IsClicked" + }, + "parameters": [ + "Button", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_CountryTile", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Country shown on the tile.", + "fullName": "Country", + "functionType": "StringExpression", + "name": "Country", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnString" + }, + "parameters": [ + "Country" + ] + } + ] + } + ], + "expressionType": { + "type": "string" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_CountryTile", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Index of the country in the list.", + "fullName": "Index", + "functionType": "Expression", + "name": "Index", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Index" + ] + } + ] + } + ], + "expressionType": { + "type": "number" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "AirHockeyUI::UI_CountryTile", + "type": "object" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "onCreated" + }, + { + "functionName": "SetCountry" + }, + { + "functionName": "SetHighlight" + }, + { + "functionName": "SetClickable" + }, + { + "functionName": "IsClicked" + }, + { + "functionName": "Country" + }, + { + "functionName": "Index" + } + ] + }, + "propertyDescriptors": [ + { + "value": "USA", + "type": "String", + "label": "Country", + "hidden": true, + "name": "Country" + }, + { + "value": "0", + "type": "Number", + "label": "Index in the country list", + "hidden": true, + "name": "Index" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "propertyName": "Country" + }, + { + "propertyName": "Index" + } + ] + }, + "variants": [] + } + ] + }, + { + "author": "", + "category": "Visual effect", + "dimension": "3D", + "extensionNamespace": "", + "fullName": "3D particle emitter", + "gdevelopVersion": ">=5.5.222", + "helpPath": "", + "iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0ibWRpLWZpcmUiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMTcuNjYgMTEuMkMxNy40MyAxMC45IDE3LjE1IDEwLjY0IDE2Ljg5IDEwLjM4QzE2LjIyIDkuNzggMTUuNDYgOS4zNSAxNC44MiA4LjcyQzEzLjMzIDcuMjYgMTMgNC44NSAxMy45NSAzQzEzIDMuMjMgMTIuMTcgMy43NSAxMS40NiA0LjMyQzguODcgNi40IDcuODUgMTAuMDcgOS4wNyAxMy4yMkM5LjExIDEzLjMyIDkuMTUgMTMuNDIgOS4xNSAxMy41NUM5LjE1IDEzLjc3IDkgMTMuOTcgOC44IDE0LjA1QzguNTcgMTQuMTUgOC4zMyAxNC4wOSA4LjE0IDEzLjkzQzguMDggMTMuODggOC4wNCAxMy44MyA4IDEzLjc2QzYuODcgMTIuMzMgNi42OSAxMC4yOCA3LjQ1IDguNjRDNS43OCAxMCA0Ljg3IDEyLjMgNSAxNC40N0M1LjA2IDE0Ljk3IDUuMTIgMTUuNDcgNS4yOSAxNS45N0M1LjQzIDE2LjU3IDUuNyAxNy4xNyA2IDE3LjdDNy4wOCAxOS40MyA4Ljk1IDIwLjY3IDEwLjk2IDIwLjkyQzEzLjEgMjEuMTkgMTUuMzkgMjAuOCAxNy4wMyAxOS4zMkMxOC44NiAxNy42NiAxOS41IDE1IDE4LjU2IDEyLjcyTDE4LjQzIDEyLjQ2QzE4LjIyIDEyIDE3LjY2IDExLjIgMTcuNjYgMTEuMk0xNC41IDE3LjVDMTQuMjIgMTcuNzQgMTMuNzYgMTggMTMuNCAxOC4xQzEyLjI4IDE4LjUgMTEuMTYgMTcuOTQgMTAuNSAxNy4yOEMxMS42OSAxNyAxMi40IDE2LjEyIDEyLjYxIDE1LjIzQzEyLjc4IDE0LjQzIDEyLjQ2IDEzLjc3IDEyLjMzIDEzQzEyLjIxIDEyLjI2IDEyLjIzIDExLjYzIDEyLjUgMTAuOTRDMTIuNjkgMTEuMzIgMTIuODkgMTEuNyAxMy4xMyAxMkMxMy45IDEzIDE1LjExIDEzLjQ0IDE1LjM3IDE0LjhDMTUuNDEgMTQuOTQgMTUuNDMgMTUuMDggMTUuNDMgMTUuMjNDMTUuNDYgMTYuMDUgMTUuMSAxNi45NSAxNC41IDE3LjVIMTQuNVoiIC8+PC9zdmc+", + "name": "ParticleEmitter3D", + "previewIconUrl": "https://asset-resources.gdevelop.io/public-resources/Icons/f2e5a34bf465f781866677762d385d6c8e9e8d203383f2df9a3b7e0fad6a2cb5_fire.svg", + "shortDescription": "Display a large number of particles in 3D to create visual effects in a 3D game.", + "version": "3.1.1", + "description": [ + "3D particle emitters let you create and display many small particles to simulate visual effects in your game — like fire, explosions, smoke, or dust.", + "", + "The parameters of the object can be configured in multiple different ways to create a specific desired effect. GDevelop will give a set of a pre-configured 3D particle emitters that you should try first.", + "", + "Use these 3D particle emitters in 3D games. For 2D games or particles that appear on a game's 2D user interface, use the 2D particle emitter object instead." + ], + "origin": { + "identifier": "ParticleEmitter3D", + "name": "gdevelop-extension-store" + }, + "tags": [ + "3d", + "particle", + "explosion", + "fire", + "smoke", + "splash", + "light" + ], + "authorIds": [ + "IWykYNRvhCZBN3vEgKEbBPOR3Oc2" + ], + "changelog": [ + { + "version": "3.0.0", + "breaking": "- the object rotates the other way around X axis." + }, + { + "version": "2.0.0", + "breaking": "- Object properties for position and rotation have been removed. They must be set with the instance editor or the action." + }, + { + "version": "1.0.0", + "breaking": "- Particles were 3 times too small." + } + ], + "dependencies": [], + "globalVariables": [], + "sceneVariables": [], + "eventsFunctions": [ + { + "description": "Define helper classes JavaScript code.", + "fullName": "Define helper classes", + "functionType": "Action", + "name": "DefineHelperClasses", + "private": true, + "sentence": "Define helper classes JavaScript code", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "if (gdjs.__particleEmmiter3DExtension) {", + " return;", + "}", + "", + "const game = runtimeScene.getGame();", + "", + "class ParticleEmitter3DRenderer extends gdjs.CustomRuntimeObject3DRenderer {", + " constructor(", + " object,", + " instanceContainer,", + " parent", + " ) {", + " super(object, instanceContainer, parent);", + " }", + "", + " _updateThreeGroup() {", + " const threeObject3D = this.get3DRendererObject();", + "", + " threeObject3D.rotation.set(", + " gdjs.toRad(this._object.getRotationX()),", + " gdjs.toRad(this._object.getRotationY()),", + " gdjs.toRad(this._object.angle)", + " );", + "", + " threeObject3D.position.set(", + " this._object.getX(),", + " this._object.getY(),", + " this._object.getZ()", + " );", + "", + " // Force the scale to 1 because the particle emitter doesn't really has a size.", + " threeObject3D.scale.set(", + " this._object.isFlippedX() ? -1 : 1,", + " this._object.isFlippedY() ? -1 : 1,", + " this._object.isFlippedZ() ? -1 : 1", + " );", + "", + " threeObject3D.visible = !this._object.hidden;", + "", + " this._isContainerDirty = true;", + " }", + "}", + "", + "const coneLength = 64;", + "", + "class ParticleEmitterHelper extends THREE.Object3D {", + " /** @type {gdjs.CustomRuntimeObject3D} */", + " object;", + " /** @type {THREE.LineSegments} */", + " cone;", + " /** @type {THREE.LineSegments} */", + " centerLine;", + " /** @type {THREE.Mesh} */", + " originBox;", + "", + "\t/**", + " * @param gdjs.CustomRuntimeObject3D object", + "\t */", + " constructor(object) {", + " super();", + " this.object = object;", + " this.type = 'ParticleEmitterHelper';", + "", + " const coneGeometry = new THREE.BufferGeometry();", + " const conePositions = [", + " 0, 0, 0, 0, 0, 1,", + " 0, 0, 0, 1, 0, 1,", + " 0, 0, 0, - 1, 0, 1,", + " 0, 0, 0, 0, 1, 1,", + " 0, 0, 0, 0, - 1, 1", + " ];", + " for (let i = 0, j = 1, l = 32; i < l; i++ , j++) {", + " const p1 = (i / l) * Math.PI * 2;", + " const p2 = (j / l) * Math.PI * 2;", + " conePositions.push(", + " Math.cos(p1), Math.sin(p1), 1,", + " Math.cos(p2), Math.sin(p2), 1", + " );", + " }", + " coneGeometry.setAttribute('position', new THREE.Float32BufferAttribute(conePositions, 3));", + " this.cone = new THREE.LineSegments(", + " coneGeometry,", + " new THREE.LineBasicMaterial({ fog: false, toneMapped: false })", + " );", + " this.add(this.cone);", + " const centerLineGeometry = new THREE.BufferGeometry();", + " centerLineGeometry.setAttribute('position', new THREE.Float32BufferAttribute([", + " 0, 0, 0, 0, 0, coneLength", + " ], 3));", + " this.centerLine = new THREE.LineSegments(", + " centerLineGeometry,", + " new THREE.LineBasicMaterial({ fog: false, toneMapped: false })", + " );", + " this.add(this.centerLine);", + "", + " this.originBox = new THREE.Mesh(", + " new THREE.BoxGeometry(16, 16, 16),", + " new THREE.MeshBasicMaterial({ fog: false, toneMapped: false })", + " );", + " this.add(this.originBox);", + " this.update();", + "", + " this.originBox.gdjsRuntimeObject = object;", + " }", + "", + " dispose() {", + " this.cone.geometry.dispose();", + " this.cone.material.dispose();", + " this.centerLine.geometry.dispose();", + " this.centerLine.material.dispose();", + " this.originBox.geometry.dispose();", + " this.originBox.material.dispose();", + " }", + "", + " update() {", + " const coneWidth = coneLength * Math.sin(gdjs.toRad(this.object._getSpayConeAngle()));", + " const coneHeight = coneLength * Math.cos(gdjs.toRad(this.object._getSpayConeAngle()));", + " this.cone.scale.set(coneWidth, coneWidth, coneHeight);", + " const startColor = gdjs.rgbOrHexStringToNumber(this.object._getStartColor())", + " const endColor = gdjs.rgbOrHexStringToNumber(this.object._getEndColor());", + " this.cone.material.color.set(endColor);", + " this.centerLine.material.color.set(startColor);", + " this.originBox.material.color.set(startColor);", + " }", + "}", + "", + "/**", + " * @param {string} colorString", + " * @param {THREE.Vector4} threeColor", + " */", + "const setThreeColor = (colorString, threeColor = new THREE.Vector4()) => {", + " const integerColor = gdjs.rgbOrHexToRGBColor(colorString);", + " threeColor.x = integerColor[0] / 255;", + " threeColor.y = integerColor[1] / 255;", + " threeColor.z = integerColor[2] / 255;", + "};", + "", + "/**", + " * @param {string} integerOpacity", + " * @param {THREE.Vector4} threeColor", + " */", + "const setThreeOpacity = (integerOpacity, threeColor = new THREE.Vector4()) => {", + " threeColor.w = integerOpacity / 255;", + "};", + "", + "class ParticleEmitterAdapter {", + " /**", + " * @param inverseWorldScale {number}", + " * @param particleSystem {ParticleSystem}", + " * @param colorOverLife {ColorOverLife}", + " * @param sizeOverLife {SizeOverLife}", + " * @param applyForce {ApplyForce}", + " * @param applyForce {ApplyForce}", + " * @param widthOverLength {WidthOverLength}", + " */", + " constructor(inverseWorldScale, particleSystem, colorOverLife, sizeOverLife, applyForce, widthOverLength) {", + " this.inverseWorldScale = inverseWorldScale;", + " this.particleSystem = particleSystem;", + " this.colorOverLife = colorOverLife;", + " this.sizeOverLife = sizeOverLife;", + " this.applyForce = applyForce;", + " this.widthOverLength = widthOverLength;", + " }", + "", + " /**", + " * @param renderMode {'Billboard' | 'Trail'}", + " */", + " setRenderMode(renderMode) {", + " switch (renderMode) {", + " case \"BillBoard\":", + " this.particleSystem.renderMode = RenderMode.BillBoard;", + " break;", + " case \"Trail\":", + " this.particleSystem.renderMode = RenderMode.Trail;", + " this.particleSystem.rendererEmitterSettings.startLength = new IntervalValue(30, 30);", + " break;", + " }", + " }", + "", + " /**", + " * @param startLengthMin {number}", + " */", + " setTrailStartLengthMin(startLengthMin) {", + " const startLength = this.particleSystem.rendererEmitterSettings.startLength;", + " if (!startLength) {", + " return;", + " }", + " startLength.a = startLengthMin * this.inverseWorldScale;", + " }", + "", + " /**", + " * @param startLengthMax {number}", + " */", + " setTrailStartLengthMax(startLengthMax) {", + " const startLength = this.particleSystem.rendererEmitterSettings.startLength;", + " if (!startLength) {", + " return;", + " }", + " startLength.b = startLengthMax * this.inverseWorldScale;", + " }", + "", + " /**", + " * @param followLocalOrigin {boolean}", + " */", + " setTrailFollowingLocalOrigin(followLocalOrigin) {", + " this.particleSystem.rendererEmitterSettings.followLocalOrigin = followLocalOrigin;", + " }", + "", + " /**", + " * @param trailEndWidthRatio {number}", + " */", + " setTrailEndWidthRatio(trailEndWidthRatio) {", + " // Check this comment in the lib code:", + " // We added a multiplication with size because it's more convenient for the extension.", + "", + " /** @type Bezier */", + " const bezier = this.widthOverLength.width.functions[0][0];", + " bezier.p[0] = 1;", + " bezier.p[1] = gdjs.evtTools.common.lerp(1, trailEndWidthRatio, 1 / 3);", + " bezier.p[2] = gdjs.evtTools.common.lerp(1, trailEndWidthRatio, 2 / 3);", + " bezier.p[3] = trailEndWidthRatio;", + " }", + "", + "", + " /**", + " * @param startColor {string}", + " */", + " setStartColor(startColor) {", + " setThreeColor(startColor, this.colorOverLife.color.color.keys[0][0]);", + " }", + "", + " /**", + " * @param endColor {string}", + " */", + " setEndColor(endColor) {", + " setThreeColor(endColor, this.colorOverLife.color.color.keys[1][0]);", + " }", + "", + " /**", + " * @param startOpacity {number}", + " */", + " setStartOpacity(startOpacity) {", + " this.colorOverLife.color.alpha.keys[0][0] = startOpacity / 255;", + " }", + "", + " /**", + " * @param endOpacity {number}", + " */", + " setEndOpacity(endOpacity) {", + " this.colorOverLife.color.alpha.keys[1][0] = endOpacity / 255;", + " }", + "", + " /**", + " * @param flow {number}", + " */", + " setFlow(flow) {", + " this.particleSystem.emissionOverTime.value = flow;", + " }", + "", + " /**", + " * @param startMinSize {number}", + " */", + " setStartMinSize(startMinSize) {", + " this.particleSystem.startSize.a = startMinSize;", + " }", + "", + " /**", + " * @param startMaxSize {number}", + " */", + " setStartMaxSize(startMaxSize) {", + " this.particleSystem.startSize.b = startMaxSize;", + " }", + "", + " /**", + " * @param endScale {number}", + " */", + " setEndScale(endScale) {", + " /** @type Bezier */", + " const bezier = this.sizeOverLife.size.functions[0][0];", + " bezier.p[0] = 1;", + " bezier.p[1] = gdjs.evtTools.common.lerp(1, endScale, 1 / 3);", + " bezier.p[2] = gdjs.evtTools.common.lerp(1, endScale, 2 / 3);", + " bezier.p[3] = endScale;", + " }", + "", + " /**", + " * @param startSpeedMin {number}", + " */", + " setStartSpeedMin(startSpeedMin) {", + " this.particleSystem.startSpeed.a = startSpeedMin * this.inverseWorldScale;", + " }", + "", + " /**", + " * @param startSpeedMax {number}", + " */", + " setStartSpeedMax(startSpeedMax) {", + " this.particleSystem.startSpeed.b = startSpeedMax * this.inverseWorldScale;", + " }", + "", + " /**", + " * @param lifespanMin {number}", + " */", + " setLifespanMin(lifespanMin) {", + " this.particleSystem.startLife.a = lifespanMin;", + " }", + "", + " /**", + " * @param lifespanMax {number}", + " */", + " setLifespanMax(lifespanMax) {", + " this.particleSystem.startLife.b = lifespanMax;", + " }", + "", + " /**", + " * @param duration {number}", + " */", + " setDuration(duration) {", + " this.particleSystem.duration = duration || Number.POSITIVE_INFINITY;", + " }", + "", + " /**", + " * @param areParticlesRelative {boolean}", + " */", + " setParticlesRelative(areParticlesRelative) {", + " this.particleSystem.worldSpace = !areParticlesRelative;", + " }", + "", + " /**", + " * @param sprayConeAngle {number}", + " */", + " setSprayConeAngle(sprayConeAngle) {", + " if (0 < sprayConeAngle && sprayConeAngle <= 180) {", + " if (!this.particleSystem.emitterShape.angle) {", + " this.particleSystem.emitterShape = new ConeEmitter({ radius: 0.1, angle: Math.PI / 8 });", + " }", + " this.particleSystem.emitterShape.angle = sprayConeAngle * Math.PI / 180;", + " }", + " else {", + " if (this.particleSystem.emitterShape.angle) {", + " this.particleSystem.emitterShape = new PointEmitter();", + " }", + " }", + " }", + "", + " /**", + " * @param blending {string}", + " */", + " setBlending(blendingString) {", + " const blending =", + " blendingString === \"Additive\" ? THREE.AdditiveBlending :", + " blendingString === \"Normal\" ? THREE.NormalBlending :", + " blendingString === \"Subtractive\" ? THREE.SubtractiveBlending :", + " blendingString === \"Multiply\" ? THREE.MultiplyBlending :", + " blendingString === \"None\" ? THREE.NoBlending :", + " THREE.AdditiveBlending;", + " // TODO This doesn't work.", + " this.particleSystem.blending = blending;", + " }", + "", + " /**", + " * @param gravity {number}", + " */", + " setGravity(gravity) {", + " this.applyForce.magnitude.value = gravity * this.inverseWorldScale;", + " }", + "", + " /**", + " * @param gravityTop {string}", + " */", + " setGravityTop(gravityTop) {", + " // TODO Make gravity absolute even when \"relative\" is enabled. ", + " switch (gravityTop) {", + " case \"Z+\":", + " this.applyForce.direction.set(0, 0, -1);", + " break;", + "", + " case \"Y-\":", + " this.applyForce.direction.set(0, 1, 0);", + " break;", + " }", + " }", + "", + " setImage(resourceName) {", + " const texture = game.getImageManager().getThreeTexture(resourceName);", + " this.particleSystem.texture = texture;", + " }", + "}", + "", + "", + "", + "/**", + " * three.quarks v0.11.2 build Mon Jan 22 2024", + " * https://github.com/Alchemist0823/three.quarks#readme", + " * Copyright 2024 Alchemist0823 , MIT", + " */", + "", + "// The migration to addUpdateRange was backported without updating the library", + "// because GDevelop still uses Three.js 0.160.0.", + "", + "class ParticleEmitter extends THREE.Object3D {", + " constructor(system) {", + " super();", + " this.type = 'ParticleEmitter';", + " this.system = system;", + " }", + " clone() {", + " const system = this.system.clone();", + " system.emitter.copy(this, true);", + " return system.emitter;", + " }", + " dispose() { }", + " extractFromCache(cache) {", + " const values = [];", + " for (const key in cache) {", + " const data = cache[key];", + " delete data.metadata;", + " values.push(data);", + " }", + " return values;", + " }", + " toJSON(meta, options = {}) {", + " const isRootObject = meta === undefined || typeof meta === 'string';", + " const output = {};", + " if (isRootObject) {", + " meta = {", + " geometries: {},", + " materials: {},", + " textures: {},", + " images: {},", + " shapes: {},", + " skeletons: {},", + " animations: {},", + " nodes: {},", + " };", + " output.metadata = {", + " version: 4.5,", + " type: 'Object',", + " generator: 'Object3D.toJSON',", + " };", + " }", + " const object = {};", + " object.uuid = this.uuid;", + " object.type = this.type;", + " if (this.name !== '')", + " object.name = this.name;", + " if (this.castShadow === true)", + " object.castShadow = true;", + " if (this.receiveShadow === true)", + " object.receiveShadow = true;", + " if (this.visible === false)", + " object.visible = false;", + " if (this.frustumCulled === false)", + " object.frustumCulled = false;", + " if (this.renderOrder !== 0)", + " object.renderOrder = this.renderOrder;", + " if (JSON.stringify(this.userData) !== '{}')", + " object.userData = this.userData;", + " object.layers = this.layers.mask;", + " object.matrix = this.matrix.toArray();", + " if (this.matrixAutoUpdate === false)", + " object.matrixAutoUpdate = false;", + " if (this.system !== null)", + " object.ps = this.system.toJSON(meta, options);", + " if (this.children.length > 0) {", + " object.children = [];", + " for (let i = 0; i < this.children.length; i++) {", + " if (this.children[i].type !== 'ParticleSystemPreview') {", + " object.children.push(this.children[i].toJSON(meta).object);", + " }", + " }", + " }", + " if (isRootObject) {", + " const geometries = this.extractFromCache(meta.geometries);", + " const materials = this.extractFromCache(meta.materials);", + " const textures = this.extractFromCache(meta.textures);", + " const images = this.extractFromCache(meta.images);", + " if (geometries.length > 0)", + " output.geometries = geometries;", + " if (materials.length > 0)", + " output.materials = materials;", + " if (textures.length > 0)", + " output.textures = textures;", + " if (images.length > 0)", + " output.images = images;", + " }", + " output.object = object;", + " return output;", + " }", + "}", + "", + "class LinkedListNode {", + " constructor(data) {", + " this.data = data;", + " this.next = null;", + " this.prev = null;", + " }", + " hasPrev() {", + " return this.prev !== null;", + " }", + " hasNext() {", + " return this.next !== null;", + " }", + "}", + "class LinkedList {", + " constructor() {", + " this.length = 0;", + " this.head = this.tail = null;", + " }", + " isEmpty() {", + " return this.head === null;", + " }", + " clear() {", + " this.length = 0;", + " this.head = this.tail = null;", + " }", + " front() {", + " if (this.head === null)", + " return null;", + " return this.head.data;", + " }", + " back() {", + " if (this.tail === null)", + " return null;", + " return this.tail.data;", + " }", + " dequeue() {", + " if (this.head) {", + " const value = this.head.data;", + " this.head = this.head.next;", + " if (!this.head) {", + " this.tail = null;", + " }", + " else {", + " this.head.prev = null;", + " }", + " this.length--;", + " return value;", + " }", + " return undefined;", + " }", + " pop() {", + " if (this.tail) {", + " const value = this.tail.data;", + " this.tail = this.tail.prev;", + " if (!this.tail) {", + " this.head = null;", + " }", + " else {", + " this.tail.next = null;", + " }", + " this.length--;", + " return value;", + " }", + " return undefined;", + " }", + " queue(data) {", + " const node = new LinkedListNode(data);", + " if (!this.tail) {", + " this.tail = node;", + " }", + " if (this.head) {", + " this.head.prev = node;", + " node.next = this.head;", + " }", + " this.head = node;", + " this.length++;", + " }", + " push(data) {", + " const node = new LinkedListNode(data);", + " if (!this.head) {", + " this.head = node;", + " }", + " if (this.tail) {", + " this.tail.next = node;", + " node.prev = this.tail;", + " }", + " this.tail = node;", + " this.length++;", + " }", + " insertBefore(node, data) {", + " const newNode = new LinkedListNode(data);", + " newNode.next = node;", + " newNode.prev = node.prev;", + " if (newNode.prev !== null) {", + " newNode.prev.next = newNode;", + " }", + " newNode.next.prev = newNode;", + " if (node == this.head) {", + " this.head = newNode;", + " }", + " this.length++;", + " }", + " remove(data) {", + " if (this.head === null || this.tail === null) {", + " return;", + " }", + " let tempNode = this.head;", + " if (data === this.head.data) {", + " this.head = this.head.next;", + " }", + " if (data === this.tail.data) {", + " this.tail = this.tail.prev;", + " }", + " while (tempNode.next !== null && tempNode.data !== data) {", + " tempNode = tempNode.next;", + " }", + " if (tempNode.data === data) {", + " if (tempNode.prev !== null)", + " tempNode.prev.next = tempNode.next;", + " if (tempNode.next !== null)", + " tempNode.next.prev = tempNode.prev;", + " this.length--;", + " }", + " }", + " *values() {", + " let current = this.head;", + " while (current !== null) {", + " yield current.data;", + " current = current.next;", + " }", + " }", + "}", + "", + "class NodeParticle {", + " constructor() {", + " this.position = new THREE.Vector3();", + " this.velocity = new THREE.Vector3();", + " this.age = 0;", + " this.life = 1;", + " this.size = 1;", + " this.rotation = 0;", + " this.color = new THREE.Vector4(1, 1, 1, 1);", + " this.uvTile = 0;", + " }", + " get died() {", + " return this.age >= this.life;", + " }", + " reset() {", + " this.position.set(0, 0, 0);", + " this.velocity.set(0, 0, 0);", + " this.age = 0;", + " this.life = 1;", + " this.size = 1;", + " this.rotation = 0;", + " this.color.set(1, 1, 1, 1);", + " this.uvTile = 0;", + " }", + "}", + "class SpriteParticle {", + " constructor() {", + " this.startSpeed = 0;", + " this.startColor = new THREE.Vector4();", + " this.startSize = 1;", + " this.position = new THREE.Vector3();", + " this.velocity = new THREE.Vector3();", + " this.age = 0;", + " this.life = 1;", + " this.size = 1;", + " this.speedModifier = 1;", + " this.rotation = 0;", + " this.color = new THREE.Vector4();", + " this.uvTile = 0;", + " }", + " get died() {", + " return this.age >= this.life;", + " }", + "}", + "class RecordState {", + " constructor(position, size, color) {", + " this.position = position;", + " this.size = size;", + " this.color = color;", + " }", + "}", + "class TrailParticle {", + " constructor() {", + " this.startSpeed = 0;", + " this.startColor = new THREE.Vector4();", + " this.startSize = 1;", + " this.position = new THREE.Vector3();", + " this.velocity = new THREE.Vector3();", + " this.age = 0;", + " this.life = 1;", + " this.size = 1;", + " this.length = 100;", + " this.speedModifier = 1;", + " this.color = new THREE.Vector4();", + " this.previous = new LinkedList();", + " this.uvTile = 0;", + " }", + " update() {", + " if (this.age <= this.life) {", + " this.previous.push(new RecordState(this.position.clone(), this.size, this.color.clone()));", + " }", + " else {", + " if (this.previous.length > 0) {", + " this.previous.dequeue();", + " }", + " }", + " while (this.previous.length > this.length) {", + " this.previous.dequeue();", + " }", + " }", + " get died() {", + " return this.age >= this.life;", + " }", + " reset() {", + " this.previous.clear();", + " }", + "}", + "", + "class Bezier {", + " constructor(p1, p2, p3, p4) {", + " this.p = [p1, p2, p3, p4];", + " }", + " genValue(t) {", + " const t2 = t * t;", + " const t3 = t * t * t;", + " const mt = 1 - t;", + " const mt2 = mt * mt;", + " const mt3 = mt2 * mt;", + " return this.p[0] * mt3 + this.p[1] * mt2 * t * 3 + this.p[2] * mt * t2 * 3 + this.p[3] * t3;", + " }", + " derivativeCoefficients(points) {", + " const dpoints = [];", + " for (let p = points, c = p.length - 1; c > 0; c--) {", + " const list = [];", + " for (let j = 0; j < c; j++) {", + " const dpt = c * (p[j + 1] - p[j]);", + " list.push(dpt);", + " }", + " dpoints.push(list);", + " p = list;", + " }", + " return dpoints;", + " }", + " getSlope(t) {", + " const p = this.derivativeCoefficients(this.p)[0];", + " const mt = 1 - t;", + " const a = mt * mt;", + " const b = mt * t * 2;", + " const c = t * t;", + " return a * p[0] + b * p[1] + c * p[2];", + " }", + " controlCurve(d0, d1) {", + " this.p[1] = d0 / 3 + this.p[0];", + " this.p[2] = this.p[3] - d1 / 3;", + " }", + " hull(t) {", + " let p = this.p;", + " let _p = [], pt, idx = 0, i = 0, l = 0;", + " const q = [];", + " q[idx++] = p[0];", + " q[idx++] = p[1];", + " q[idx++] = p[2];", + " q[idx++] = p[3];", + " while (p.length > 1) {", + " _p = [];", + " for (i = 0, l = p.length - 1; i < l; i++) {", + " pt = t * p[i] + (1 - t) * p[i + 1];", + " q[idx++] = pt;", + " _p.push(pt);", + " }", + " p = _p;", + " }", + " return q;", + " }", + " split(t) {", + " const q = this.hull(t);", + " const result = {", + " left: new Bezier(q[0], q[4], q[7], q[9]),", + " right: new Bezier(q[9], q[8], q[6], q[3]),", + " span: q", + " };", + " return result;", + " }", + " clone() {", + " return new Bezier(this.p[0], this.p[1], this.p[2], this.p[3]);", + " }", + " toJSON() {", + " return {", + " p0: this.p[0],", + " p1: this.p[1],", + " p2: this.p[2],", + " p3: this.p[3],", + " };", + " }", + " static fromJSON(json) {", + " return new Bezier(json.p0, json.p1, json.p2, json.p3);", + " }", + "}", + "", + "const ColorToJSON = (color) => {", + " return { r: color.x, g: color.y, b: color.z, a: color.w };", + "};", + "const JSONToColor = (json) => {", + " return new THREE.Vector4(json.r, json.g, json.b, json.a);", + "};", + "const JSONToValue = (json, type) => {", + " switch (type) {", + " case 'Vector3':", + " return new THREE.Vector3(json.x, json.y, json.z);", + " case 'Vector4':", + " return new THREE.Vector4(json.x, json.y, json.z, json.w);", + " case 'Color':", + " return new THREE.Vector3(json.r, json.g, json.b);", + " case 'Number':", + " return json;", + " default:", + " return json;", + " }", + "};", + "const ValueToJSON = (value, type) => {", + " switch (type) {", + " case 'Vector3':", + " return { x: value.x, y: value.y, z: value.z };", + " case 'Vector4':", + " return { x: value.x, y: value.y, z: value.z, w: value.w };", + " case 'Color':", + " return { r: value.x, g: value.y, b: value.z };", + " case 'Number':", + " return value;", + " default:", + " return value;", + " }", + "};", + "", + "class RandomColor {", + " constructor(a, b) {", + " this.a = a;", + " this.b = b;", + " this.type = \"value\";", + " }", + " genColor(color) {", + " const rand = Math.random();", + " return color.copy(this.a).lerp(this.b, rand);", + " }", + " toJSON() {", + " return {", + " type: \"RandomColor\",", + " a: ColorToJSON(this.a),", + " b: ColorToJSON(this.b),", + " };", + " }", + " static fromJSON(json) {", + " return new RandomColor(JSONToColor(json.a), JSONToColor(json.b));", + " }", + " clone() {", + " return new RandomColor(this.a.clone(), this.b.clone());", + " }", + "}", + "", + "class ColorRange {", + " constructor(a, b) {", + " this.a = a;", + " this.b = b;", + " this.type = 'value';", + " }", + " genColor(color, t) {", + " return color.copy(this.a).lerp(this.b, Math.random());", + " }", + " toJSON() {", + " return {", + " type: 'ColorRange',", + " a: ColorToJSON(this.a),", + " b: ColorToJSON(this.b),", + " };", + " }", + " static fromJSON(json) {", + " return new ColorRange(JSONToColor(json.a), JSONToColor(json.b));", + " }", + " clone() {", + " return new ColorRange(this.a.clone(), this.b.clone());", + " }", + "}", + "", + "class ContinuousLinearFunction {", + " constructor(keys, subType) {", + " this.subType = subType;", + " this.type = 'function';", + " this.keys = keys;", + " }", + " findKey(t) {", + " let mid = 0;", + " let left = 0, right = this.keys.length - 1;", + " while (left + 1 < right) {", + " mid = Math.floor((left + right) / 2);", + " if (t < this.getStartX(mid))", + " right = mid - 1;", + " else if (t > this.getEndX(mid))", + " left = mid + 1;", + " else", + " return mid;", + " }", + " for (let i = left; i <= right; i++) {", + " if (t >= this.getStartX(i) && t <= this.getEndX(i))", + " return i;", + " }", + " return -1;", + " }", + " getStartX(index) {", + " return this.keys[index][1];", + " }", + " getEndX(index) {", + " if (index + 1 < this.keys.length)", + " return this.keys[index + 1][1];", + " return 1;", + " }", + " genValue(value, t) {", + " const index = this.findKey(t);", + " if (this.subType === 'Number') {", + " if (index === -1) {", + " return this.keys[0][0];", + " }", + " else if (index + 1 >= this.keys.length) {", + " return this.keys[this.keys.length - 1][0];", + " }", + " return ((this.keys[index + 1][0] - this.keys[index][0]) *", + " ((t - this.getStartX(index)) / (this.getEndX(index) - this.getStartX(index))) +", + " this.keys[index][0]);", + " }", + " else {", + " if (index === -1) {", + " return value.copy(this.keys[0][0]);", + " }", + " if (index + 1 >= this.keys.length) {", + " return value.copy(this.keys[this.keys.length - 1][0]);", + " }", + " return value", + " .copy(this.keys[index][0])", + " .lerp(this.keys[index + 1][0], (t - this.getStartX(index)) / (this.getEndX(index) - this.getStartX(index)));", + " }", + " }", + " toJSON() {", + " this.keys[0][0].constructor.name;", + " return {", + " type: 'CLinearFunction',", + " subType: this.subType,", + " keys: this.keys.map(([color, pos]) => ({ value: ValueToJSON(color, this.subType), pos: pos })),", + " };", + " }", + " static fromJSON(json) {", + " return new ContinuousLinearFunction(json.keys.map((pair) => [JSONToValue(pair.value, json.subType), pair.pos]), json.subType);", + " }", + " clone() {", + " if (this.subType === 'Number') {", + " return new ContinuousLinearFunction(this.keys.map(([value, pos]) => [value, pos]), this.subType);", + " }", + " else {", + " return new ContinuousLinearFunction(this.keys.map(([value, pos]) => [value.clone(), pos]), this.subType);", + " }", + " }", + "}", + "", + "const tempVec3 = new THREE.Vector3();", + "class Gradient {", + " constructor(color = [", + " [new THREE.Vector3(0, 0, 0), 0],", + " [new THREE.Vector3(1, 1, 1), 0],", + " ], alpha = [", + " [1, 0],", + " [1, 1],", + " ]) {", + " this.type = 'function';", + " this.color = new ContinuousLinearFunction(color, 'Color');", + " this.alpha = new ContinuousLinearFunction(alpha, 'Number');", + " }", + " genColor(color, t) {", + " this.color.genValue(tempVec3, t);", + " return color.set(tempVec3.x, tempVec3.y, tempVec3.z, this.alpha.genValue(1, t));", + " }", + " toJSON() {", + " return {", + " type: 'Gradient',", + " color: this.color.toJSON(),", + " alpha: this.alpha.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " if (json.functions) {", + " const keys = json.functions.map((func) => [ColorRange.fromJSON(func.function).a, func.start]);", + " if (json.functions.length > 0) {", + " keys.push([ColorRange.fromJSON(json.functions[json.functions.length - 1].function).b, 1]);", + " }", + " return new Gradient(keys.map((key) => [new THREE.Vector3(key[0].x, key[0].y, key[0].z), key[1]]), keys.map((key) => [key[0].w, key[1]]));", + " }", + " else {", + " const gradient = new Gradient();", + " gradient.alpha = ContinuousLinearFunction.fromJSON(json.alpha);", + " gradient.color = ContinuousLinearFunction.fromJSON(json.color);", + " return gradient;", + " }", + " }", + " clone() {", + " const gradient = new Gradient();", + " gradient.alpha = this.alpha.clone();", + " gradient.color = this.color.clone();", + " return gradient;", + " }", + "}", + "", + "const tempColor = new THREE.Vector4();", + "class RandomColorBetweenGradient {", + " constructor(gradient1, gradient2) {", + " this.type = 'memorizedFunction';", + " this.gradient1 = gradient1;", + " this.gradient2 = gradient2;", + " }", + " startGen(memory) {", + " memory.rand = Math.random();", + " }", + " genColor(color, t, memory) {", + " this.gradient1.genColor(color, t);", + " this.gradient2.genColor(tempColor, t);", + " if (memory && memory.rand) {", + " color.lerp(tempColor, memory.rand);", + " }", + " else {", + " color.lerp(tempColor, Math.random());", + " }", + " return color;", + " }", + " toJSON() {", + " return {", + " type: 'RandomColorBetweenGradient',", + " gradient1: this.gradient1.toJSON(),", + " gradient2: this.gradient2.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new RandomColorBetweenGradient(Gradient.fromJSON(json.gradient1), Gradient.fromJSON(json.gradient2));", + " }", + " clone() {", + " return new RandomColorBetweenGradient(this.gradient1.clone(), this.gradient2.clone());", + " }", + "}", + "", + "class ConstantColor {", + " constructor(color) {", + " this.color = color;", + " this.type = 'value';", + " }", + " genColor(color) {", + " return color.copy(this.color);", + " }", + " toJSON() {", + " return {", + " type: 'ConstantColor',", + " color: ColorToJSON(this.color),", + " };", + " }", + " static fromJSON(json) {", + " return new ConstantColor(JSONToColor(json.color));", + " }", + " clone() {", + " return new ConstantColor(this.color.clone());", + " }", + "}", + "function ColorGeneratorFromJSON(json) {", + " switch (json.type) {", + " case 'ConstantColor':", + " return ConstantColor.fromJSON(json);", + " case 'ColorRange':", + " return ColorRange.fromJSON(json);", + " case 'RandomColor':", + " return RandomColor.fromJSON(json);", + " case 'Gradient':", + " return Gradient.fromJSON(json);", + " case 'RandomColorBetweenGradient':", + " return RandomColorBetweenGradient.fromJSON(json);", + " default:", + " return new ConstantColor(new THREE.Vector4(1, 1, 1, 1));", + " }", + "}", + "", + "class ConstantValue {", + " constructor(value) {", + " this.value = value;", + " this.type = 'value';", + " }", + " genValue() {", + " return this.value;", + " }", + " toJSON() {", + " return {", + " type: \"ConstantValue\",", + " value: this.value", + " };", + " }", + " static fromJSON(json) {", + " return new ConstantValue(json.value);", + " }", + " clone() {", + " return new ConstantValue(this.value);", + " }", + "}", + "", + "class IntervalValue {", + " constructor(a, b) {", + " this.a = a;", + " this.b = b;", + " this.type = 'value';", + " }", + " genValue() {", + " return THREE.MathUtils.lerp(this.a, this.b, Math.random());", + " }", + " toJSON() {", + " return {", + " type: 'IntervalValue',", + " a: this.a,", + " b: this.b,", + " };", + " }", + " static fromJSON(json) {", + " return new IntervalValue(json.a, json.b);", + " }", + " clone() {", + " return new IntervalValue(this.a, this.b);", + " }", + "}", + "", + "class PiecewiseFunction {", + " constructor() {", + " this.functions = new Array();", + " }", + " findFunction(t) {", + " let mid = 0;", + " let left = 0, right = this.functions.length - 1;", + " while (left + 1 < right) {", + " mid = Math.floor((left + right) / 2);", + " if (t < this.getStartX(mid))", + " right = mid - 1;", + " else if (t > this.getEndX(mid))", + " left = mid + 1;", + " else", + " return mid;", + " }", + " for (let i = left; i <= right; i++) {", + " if (t >= this.functions[i][1] && t <= this.getEndX(i))", + " return i;", + " }", + " return -1;", + " }", + " getStartX(index) {", + " return this.functions[index][1];", + " }", + " setStartX(index, x) {", + " if (index > 0)", + " this.functions[index][1] = x;", + " }", + " getEndX(index) {", + " if (index + 1 < this.functions.length)", + " return this.functions[index + 1][1];", + " return 1;", + " }", + " setEndX(index, x) {", + " if (index + 1 < this.functions.length)", + " this.functions[index + 1][1] = x;", + " }", + " insertFunction(t, func) {", + " const index = this.findFunction(t);", + " this.functions.splice(index + 1, 0, [func, t]);", + " }", + " removeFunction(index) {", + " return this.functions.splice(index, 1)[0][0];", + " }", + " getFunction(index) {", + " return this.functions[index][0];", + " }", + " setFunction(index, func) {", + " this.functions[index][0] = func;", + " }", + " get numOfFunctions() {", + " return this.functions.length;", + " }", + "}", + "", + "class PiecewiseBezier extends PiecewiseFunction {", + " constructor(curves = [[new Bezier(0, 1.0 / 3, 1.0 / 3 * 2, 1), 0]]) {", + " super();", + " this.type = \"function\";", + " this.functions = curves;", + " }", + " genValue(t = 0) {", + " const index = this.findFunction(t);", + " if (index === -1) {", + " return 0;", + " }", + " return this.functions[index][0].genValue((t - this.getStartX(index)) / (this.getEndX(index) - this.getStartX(index)));", + " }", + " toSVG(length, segments) {", + " if (segments < 1)", + " return \"\";", + " let result = [\"M\", 0, this.functions[0][0].p[0]].join(\" \");", + " for (let i = 1.0 / segments; i <= 1; i += 1.0 / segments) {", + " result = [result, \"L\", i * length, this.genValue(i)].join(\" \");", + " }", + " return result;", + " }", + " toJSON() {", + " return {", + " type: \"PiecewiseBezier\",", + " functions: this.functions.map(([bezier, start]) => ({ function: bezier.toJSON(), start: start })),", + " };", + " }", + " static fromJSON(json) {", + " return new PiecewiseBezier(json.functions.map((piecewiseFunction) => ([Bezier.fromJSON(piecewiseFunction.function), piecewiseFunction.start])));", + " }", + " clone() {", + " return new PiecewiseBezier(this.functions.map(([bezier, start]) => ([bezier.clone(), start])));", + " }", + "}", + "", + "function ValueGeneratorFromJSON(json) {", + " switch (json.type) {", + " case 'ConstantValue':", + " return ConstantValue.fromJSON(json);", + " case 'IntervalValue':", + " return IntervalValue.fromJSON(json);", + " case 'PiecewiseBezier':", + " return PiecewiseBezier.fromJSON(json);", + " default:", + " return new ConstantValue(0);", + " }", + "}", + "", + "class RandomQuatGenerator {", + " constructor() {", + " this.type = \"rotation\";", + " }", + " genValue(quat, t) {", + " let x, y, z, u, v, w;", + " do {", + " x = Math.random() * 2 - 1;", + " y = Math.random() * 2 - 1;", + " z = x * x + y * y;", + " } while (z > 1);", + " do {", + " u = Math.random() * 2 - 1;", + " v = Math.random() * 2 - 1;", + " w = u * u + v * v;", + " } while (w > 1);", + " const s = Math.sqrt((1 - z) / w);", + " quat.set(x, y, s * u, s * v);", + " return quat;", + " }", + " toJSON() {", + " return {", + " type: \"RandomQuat\"", + " };", + " }", + " static fromJSON(json) {", + " return new RandomQuatGenerator();", + " }", + " clone() {", + " return new RandomQuatGenerator();", + " }", + "}", + "", + "class AxisAngleGenerator {", + " constructor(axis, angle) {", + " this.axis = axis;", + " this.angle = angle;", + " this.type = 'rotation';", + " }", + " genValue(quat, t) {", + " return quat.setFromAxisAngle(this.axis, this.angle.genValue(t));", + " }", + " toJSON() {", + " return {", + " type: 'AxisAngle',", + " axis: { x: this.axis.x, y: this.axis.y, z: this.axis.z },", + " angle: this.angle.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new AxisAngleGenerator(new THREE.Vector3(json.axis.x, json.axis.y, json.axis.z), ValueGeneratorFromJSON(json.angle));", + " }", + " clone() {", + " return new AxisAngleGenerator(this.axis.clone(), this.angle.clone());", + " }", + "}", + "", + "class EulerGenerator {", + " constructor(angleX, angleY, angleZ, eulerOrder) {", + " this.angleX = angleX;", + " this.angleY = angleY;", + " this.angleZ = angleZ;", + " this.type = 'rotation';", + " this.eular = new THREE.Euler(0, 0, 0, eulerOrder);", + " }", + " genValue(quat, t) {", + " this.eular.set(this.angleX.genValue(t), this.angleY.genValue(t), this.angleZ.genValue(t));", + " return quat.setFromEuler(this.eular);", + " }", + " toJSON() {", + " return {", + " type: 'Euler',", + " angleX: this.angleX.toJSON(),", + " angleY: this.angleY.toJSON(),", + " angleZ: this.angleZ.toJSON(),", + " eulerOrder: this.eular.order,", + " };", + " }", + " static fromJSON(json) {", + " return new EulerGenerator(ValueGeneratorFromJSON(json.angleX), ValueGeneratorFromJSON(json.angleY), ValueGeneratorFromJSON(json.angleZ), json.eulerOrder);", + " }", + " clone() {", + " return new EulerGenerator(this.angleX, this.angleY, this.angleZ, this.eular.order);", + " }", + "}", + "", + "function RotationGeneratorFromJSON(json) {", + " switch (json.type) {", + " case 'AxisAngle':", + " return AxisAngleGenerator.fromJSON(json);", + " case 'Euler':", + " return EulerGenerator.fromJSON(json);", + " case 'RandomQuat':", + " return RandomQuatGenerator.fromJSON(json);", + " default:", + " return new RandomQuatGenerator();", + " }", + "}", + "", + "function GeneratorFromJSON(json) {", + " switch (json.type) {", + " case 'ConstantValue':", + " case 'IntervalValue':", + " case 'PiecewiseBezier':", + " return ValueGeneratorFromJSON(json);", + " case 'AxisAngle':", + " case 'RandomQuat':", + " case 'Euler':", + " return RotationGeneratorFromJSON(json);", + " default:", + " return new ConstantValue(0);", + " }", + "}", + "", + "class ColorOverLife {", + " constructor(color) {", + " this.color = color;", + " this.type = 'ColorOverLife';", + " }", + " initialize(particle) {", + " if (this.color.type === 'memorizedFunction') {", + " particle.colorOverLifeMemory = {};", + " this.color.startGen(particle.colorOverLifeMemory);", + " }", + " }", + " update(particle, delta) {", + " if (this.color.type === 'memorizedFunction') {", + " this.color.genColor(particle.color, particle.age / particle.life, particle.colorOverLifeMemory);", + " }", + " else {", + " this.color.genColor(particle.color, particle.age / particle.life);", + " }", + " particle.color.x *= particle.startColor.x;", + " particle.color.y *= particle.startColor.y;", + " particle.color.z *= particle.startColor.z;", + " particle.color.w *= particle.startColor.w;", + " }", + " frameUpdate(delta) { }", + " toJSON() {", + " return {", + " type: this.type,", + " color: this.color.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new ColorOverLife(ColorGeneratorFromJSON(json.color));", + " }", + " clone() {", + " return new ColorOverLife(this.color.clone());", + " }", + " reset() { }", + "}", + "", + "class RotationOverLife {", + " constructor(angularVelocity) {", + " this.angularVelocity = angularVelocity;", + " this.type = 'RotationOverLife';", + " this.dynamic = !(angularVelocity instanceof ConstantValue || angularVelocity instanceof IntervalValue);", + " }", + " initialize(particle) {", + " this.dynamic = !(this.angularVelocity instanceof ConstantValue || this.angularVelocity instanceof IntervalValue);", + " if (!this.dynamic && typeof particle.rotation === 'number') {", + " particle.angularVelocity = this.angularVelocity.genValue();", + " }", + " }", + " update(particle, delta) {", + " if (!this.dynamic) {", + " if (typeof particle.rotation === 'number') {", + " particle.rotation += delta * particle.angularVelocity;", + " }", + " }", + " else {", + " if (typeof particle.rotation === 'number') {", + " particle.rotation +=", + " delta * this.angularVelocity.genValue(particle.age / particle.life);", + " }", + " }", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " angularVelocity: this.angularVelocity.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new RotationOverLife(ValueGeneratorFromJSON(json.angularVelocity));", + " }", + " frameUpdate(delta) { }", + " clone() {", + " return new RotationOverLife(this.angularVelocity.clone());", + " }", + " reset() { }", + "}", + "", + "const IdentityQuaternion = new THREE.Quaternion();", + "class Rotation3DOverLife {", + " constructor(angularVelocity) {", + " this.angularVelocity = angularVelocity;", + " this.type = 'Rotation3DOverLife';", + " this.tempQuat = new THREE.Quaternion();", + " this.dynamic = !(angularVelocity instanceof RandomQuatGenerator);", + " }", + " initialize(particle) {", + " this.dynamic = !(this.angularVelocity instanceof RandomQuatGenerator);", + " if (particle.rotation instanceof THREE.Quaternion) {", + " particle.angularVelocity = new THREE.Quaternion();", + " this.angularVelocity.genValue(particle.angularVelocity);", + " }", + " }", + " update(particle, delta) {", + " if (particle.rotation instanceof THREE.Quaternion) {", + " if (!this.dynamic) {", + " this.tempQuat.slerpQuaternions(IdentityQuaternion, particle.angularVelocity, delta);", + " particle.rotation.multiply(this.tempQuat);", + " }", + " else {", + " this.angularVelocity.genValue(this.tempQuat, particle.age / particle.life);", + " this.tempQuat.slerpQuaternions(IdentityQuaternion, this.tempQuat, delta);", + " particle.rotation.multiply(this.tempQuat);", + " }", + " }", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " angularVelocity: this.angularVelocity.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new Rotation3DOverLife(RotationGeneratorFromJSON(json.angularVelocity));", + " }", + " frameUpdate(delta) { }", + " clone() {", + " return new Rotation3DOverLife(this.angularVelocity.clone());", + " }", + " reset() { }", + "}", + "", + "class ForceOverLife {", + " initialize(particle) { }", + " constructor(x, y, z) {", + " this.x = x;", + " this.y = y;", + " this.z = z;", + " this.type = 'ForceOverLife';", + " this._temp = new THREE.Vector3();", + " }", + " update(particle, delta) {", + " this._temp.set(this.x.genValue(particle.age / particle.life), this.y.genValue(particle.age / particle.life), this.z.genValue(particle.age / particle.life));", + " particle.velocity.addScaledVector(this._temp, delta);", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " x: this.x.toJSON(),", + " y: this.y.toJSON(),", + " z: this.z.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new ForceOverLife(ValueGeneratorFromJSON(json.x), ValueGeneratorFromJSON(json.y), ValueGeneratorFromJSON(json.z));", + " }", + " frameUpdate(delta) { }", + " clone() {", + " return new ForceOverLife(this.x.clone(), this.y.clone(), this.z.clone());", + " }", + " reset() { }", + "}", + "", + "class SizeOverLife {", + " initialize(particle) {", + " }", + " constructor(size) {", + " this.size = size;", + " this.type = 'SizeOverLife';", + " }", + " update(particle) {", + " particle.size = particle.startSize * this.size.genValue(particle.age / particle.life);", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " size: this.size.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new SizeOverLife(ValueGeneratorFromJSON(json.size));", + " }", + " frameUpdate(delta) {", + " }", + " clone() {", + " return new SizeOverLife(this.size.clone());", + " }", + " reset() {", + " }", + "}", + "", + "class SpeedOverLife {", + " initialize(particle) {", + " }", + " constructor(speed) {", + " this.speed = speed;", + " this.type = 'SpeedOverLife';", + " }", + " update(particle) {", + " particle.speedModifier = this.speed.genValue(particle.age / particle.life);", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " speed: this.speed.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new SpeedOverLife(ValueGeneratorFromJSON(json.speed));", + " }", + " frameUpdate(delta) {", + " }", + " clone() {", + " return new SpeedOverLife(this.speed.clone());", + " }", + " reset() {", + " }", + "}", + "", + "class FrameOverLife {", + " constructor(frame) {", + " this.frame = frame;", + " this.type = 'FrameOverLife';", + " }", + " initialize(particle) {", + " if (!(this.frame instanceof PiecewiseBezier)) {", + " particle.uvTile = Math.floor(this.frame.genValue(0) + 0.001);", + " }", + " }", + " update(particle, delta) {", + " if (this.frame instanceof PiecewiseBezier) {", + " particle.uvTile = Math.floor(this.frame.genValue(particle.age / particle.life) + 0.001);", + " }", + " }", + " frameUpdate(delta) { }", + " toJSON() {", + " return {", + " type: this.type,", + " frame: this.frame.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new FrameOverLife(ValueGeneratorFromJSON(json.frame));", + " }", + " clone() {", + " return new FrameOverLife(this.frame.clone());", + " }", + " reset() { }", + "}", + "", + "new THREE.Vector3(0, 0, 1);", + "class OrbitOverLife {", + " constructor(orbitSpeed, axis = new THREE.Vector3(0, 1, 0)) {", + " this.orbitSpeed = orbitSpeed;", + " this.axis = axis;", + " this.type = 'OrbitOverLife';", + " this.temp = new THREE.Vector3();", + " this.rotation = new THREE.Quaternion();", + " this.line = new THREE.Line3();", + " }", + " initialize(particle) {", + " }", + " update(particle, delta) {", + " this.line.set(new THREE.Vector3(0, 0, 0), this.axis);", + " this.line.closestPointToPoint(particle.position, false, this.temp);", + " this.rotation.setFromAxisAngle(this.axis, this.orbitSpeed.genValue(particle.age / particle.life) * delta);", + " particle.position.sub(this.temp);", + " particle.position.applyQuaternion(this.rotation);", + " particle.position.add(this.temp);", + " }", + " frameUpdate(delta) {", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " orbitSpeed: this.orbitSpeed.toJSON(),", + " axis: [this.axis.x, this.axis.y, this.axis.z],", + " };", + " }", + " static fromJSON(json) {", + " return new OrbitOverLife(ValueGeneratorFromJSON(json.orbitSpeed), json.axis ? new THREE.Vector3(json.axis[0], json.axis[1], json.axis[2]) : undefined);", + " }", + " clone() {", + " return new OrbitOverLife(this.orbitSpeed.clone());", + " }", + " reset() {", + " }", + "}", + "", + "class WidthOverLength {", + " initialize(particle) {", + " }", + " constructor(width) {", + " this.width = width;", + " this.type = 'WidthOverLength';", + " }", + " update(particle) {", + " if (particle instanceof TrailParticle) {", + " const iter = particle.previous.values();", + " for (let i = 0; i < particle.previous.length; i++) {", + " const cur = iter.next();", + " // We added a multiplication with size because it's more convenient for the extension.", + " cur.value.size = this.width.genValue((particle.previous.length - i) / particle.length) * particle.size;", + " }", + " }", + " }", + " frameUpdate(delta) {", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " width: this.width.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new WidthOverLength(ValueGeneratorFromJSON(json.width));", + " }", + " clone() {", + " return new WidthOverLength(this.width.clone());", + " }", + " reset() {", + " }", + "}", + "", + "class ApplyForce {", + " constructor(direction, magnitude) {", + " this.direction = direction;", + " this.magnitude = magnitude;", + " this.type = 'ApplyForce';", + " this.magnitudeValue = this.magnitude.genValue();", + " }", + " initialize(particle) {", + " }", + " update(particle, delta) {", + " particle.velocity.addScaledVector(this.direction, this.magnitudeValue * delta);", + " }", + " frameUpdate(delta) {", + " this.magnitudeValue = this.magnitude.genValue();", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " direction: [this.direction.x, this.direction.y, this.direction.z],", + " magnitude: this.magnitude.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " var _a;", + " return new ApplyForce(new THREE.Vector3(json.direction[0], json.direction[1], json.direction[2]), ValueGeneratorFromJSON((_a = json.magnitude) !== null && _a !== void 0 ? _a : json.force));", + " }", + " clone() {", + " return new ApplyForce(this.direction.clone(), this.magnitude.clone());", + " }", + " reset() {", + " }", + "}", + "", + "class GravityForce {", + " constructor(center, magnitude) {", + " this.center = center;", + " this.magnitude = magnitude;", + " this.type = 'GravityForce';", + " this.temp = new THREE.Vector3();", + " }", + " initialize(particle) {", + " }", + " update(particle, delta) {", + " this.temp.copy(this.center).sub(particle.position).normalize();", + " particle.velocity.addScaledVector(this.temp, this.magnitude / particle.position.distanceToSquared(this.center) * delta);", + " }", + " frameUpdate(delta) {", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " center: [this.center.x, this.center.y, this.center.z],", + " magnitude: this.magnitude,", + " };", + " }", + " static fromJSON(json) {", + " return new GravityForce(new THREE.Vector3(json.center[0], json.center[1], json.center[2]), json.magnitude);", + " }", + " clone() {", + " return new GravityForce(this.center.clone(), this.magnitude);", + " }", + " reset() {", + " }", + "}", + "", + "new THREE.Vector3(0, 0, 1);", + "class ChangeEmitDirection {", + " constructor(angle) {", + " this.angle = angle;", + " this.type = 'ChangeEmitDirection';", + " this._temp = new THREE.Vector3();", + " this._q = new THREE.Quaternion();", + " }", + " initialize(particle) {", + " const len = particle.velocity.length();", + " if (len == 0)", + " return;", + " particle.velocity.normalize();", + " if (particle.velocity.x === 0 && particle.velocity.y === 0) {", + " this._temp.set(0, particle.velocity.z, 0);", + " }", + " else {", + " this._temp.set(-particle.velocity.y, particle.velocity.x, 0);", + " }", + " this._q.setFromAxisAngle(this._temp.normalize(), this.angle.genValue());", + " this._temp.copy(particle.velocity);", + " particle.velocity.applyQuaternion(this._q);", + " this._q.setFromAxisAngle(this._temp, Math.random() * Math.PI * 2);", + " particle.velocity.applyQuaternion(this._q);", + " particle.velocity.setLength(len);", + " }", + " update(particle, delta) {", + " }", + " frameUpdate(delta) {", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " angle: this.angle.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new ChangeEmitDirection(ValueGeneratorFromJSON(json.angle));", + " }", + " clone() {", + " return new ChangeEmitDirection(this.angle);", + " }", + " reset() {", + " }", + "}", + "", + "const VECTOR_ONE = new THREE.Vector3(1, 1, 1);", + "const VECTOR_Z = new THREE.Vector3(0, 0, 1);", + "let SubParticleEmitMode = void 0;", + "(function (SubParticleEmitMode) {", + " SubParticleEmitMode[SubParticleEmitMode[\"Death\"] = 0] = \"Death\";", + " SubParticleEmitMode[SubParticleEmitMode[\"Birth\"] = 1] = \"Birth\";", + " SubParticleEmitMode[SubParticleEmitMode[\"Frame\"] = 2] = \"Frame\";", + "})(SubParticleEmitMode || (SubParticleEmitMode = {}));", + "class EmitSubParticleSystem {", + " constructor(particleSystem, useVelocityAsBasis, subParticleSystem, mode = SubParticleEmitMode.Frame, emitProbability = 1) {", + " this.particleSystem = particleSystem;", + " this.useVelocityAsBasis = useVelocityAsBasis;", + " this.subParticleSystem = subParticleSystem;", + " this.mode = mode;", + " this.emitProbability = emitProbability;", + " this.type = 'EmitSubParticleSystem';", + " this.q_ = new THREE.Quaternion();", + " this.v_ = new THREE.Vector3();", + " this.v2_ = new THREE.Vector3();", + " this.subEmissions = new Array();", + " if (this.subParticleSystem && this.subParticleSystem.system) {", + " this.subParticleSystem.system.onlyUsedByOther = true;", + " }", + " }", + " initialize(particle) {", + " }", + " update(particle, delta) {", + " if (this.mode === SubParticleEmitMode.Frame) {", + " this.emit(particle, delta);", + " }", + " else if (this.mode === SubParticleEmitMode.Birth && particle.age === 0) {", + " this.emit(particle, delta);", + " }", + " else if (this.mode === SubParticleEmitMode.Death && particle.age + delta >= particle.life) {", + " this.emit(particle, delta);", + " }", + " }", + " emit(particle, delta) {", + " if (!this.subParticleSystem)", + " return;", + " if (Math.random() > this.emitProbability) {", + " return;", + " }", + " const m = new THREE.Matrix4();", + " this.setMatrixFromParticle(m, particle);", + " this.subEmissions.push({", + " burstIndex: 0,", + " burstWaveIndex: 0,", + " time: 0,", + " waitEmiting: 0,", + " matrix: m,", + " travelDistance: 0,", + " particle: particle,", + " });", + " }", + " frameUpdate(delta) {", + " if (!this.subParticleSystem)", + " return;", + " for (let i = 0; i < this.subEmissions.length; i++) {", + " if (this.subEmissions[i].time >= this.subParticleSystem.system.duration) {", + " this.subEmissions[i] = this.subEmissions[this.subEmissions.length - 1];", + " this.subEmissions.length = this.subEmissions.length - 1;", + " i--;", + " }", + " else {", + " let subEmissionState = this.subEmissions[i];", + " if (subEmissionState.particle && subEmissionState.particle.age < subEmissionState.particle.life) {", + " this.setMatrixFromParticle(subEmissionState.matrix, subEmissionState.particle);", + " }", + " else {", + " subEmissionState.particle = undefined;", + " }", + " this.subParticleSystem.system.emit(delta, subEmissionState, subEmissionState.matrix);", + " }", + " }", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " subParticleSystem: this.subParticleSystem ? this.subParticleSystem.uuid : '',", + " useVelocityAsBasis: this.useVelocityAsBasis,", + " mode: this.mode,", + " emitProbability: this.emitProbability,", + " };", + " }", + " static fromJSON(json, particleSystem) {", + " return new EmitSubParticleSystem(particleSystem, json.useVelocityAsBasis, json.subParticleSystem, json.mode, json.emitProbability);", + " }", + " clone() {", + " return new EmitSubParticleSystem(this.particleSystem, this.useVelocityAsBasis, this.subParticleSystem, this.mode, this.emitProbability);", + " }", + " reset() { }", + " setMatrixFromParticle(m, particle) {", + " let rotation;", + " if (particle.rotation === undefined || this.useVelocityAsBasis) {", + " if (particle.velocity.x === 0 &&", + " particle.velocity.y === 0 &&", + " (particle.velocity.z === 1 || particle.velocity.z === 0)) {", + " m.set(1, 0, 0, particle.position.x, 0, 1, 0, particle.position.y, 0, 0, 1, particle.position.z, 0, 0, 0, 1);", + " }", + " else {", + " this.v_.copy(VECTOR_Z).cross(particle.velocity);", + " this.v2_.copy(particle.velocity).cross(this.v_);", + " const len = this.v_.length();", + " const len2 = this.v2_.length();", + " m.set(this.v_.x / len, this.v2_.x / len2, particle.velocity.x, particle.position.x, this.v_.y / len, this.v2_.y / len2, particle.velocity.y, particle.position.y, this.v_.z / len, this.v2_.z / len2, particle.velocity.z, particle.position.z, 0, 0, 0, 1);", + " }", + " }", + " else {", + " if (particle.rotation instanceof THREE.Quaternion) {", + " rotation = particle.rotation;", + " }", + " else {", + " this.q_.setFromAxisAngle(VECTOR_Z, particle.rotation);", + " rotation = this.q_;", + " }", + " m.compose(particle.position, rotation, VECTOR_ONE);", + " }", + " if (!this.particleSystem.worldSpace) {", + " m.multiplyMatrices(this.particleSystem.emitter.matrixWorld, m);", + " }", + " }", + "}", + "", + "const F2 = 0.5 * (Math.sqrt(3.0) - 1.0);", + "const G2 = (3.0 - Math.sqrt(3.0)) / 6.0;", + "const F3 = 1.0 / 3.0;", + "const G3 = 1.0 / 6.0;", + "const F4 = (Math.sqrt(5.0) - 1.0) / 4.0;", + "const G4 = (5.0 - Math.sqrt(5.0)) / 20.0;", + "const grad3 = new Float32Array([1, 1, 0,", + " -1, 1, 0,", + " 1, -1, 0,", + " -1, -1, 0,", + " 1, 0, 1,", + " -1, 0, 1,", + " 1, 0, -1,", + " -1, 0, -1,", + " 0, 1, 1,", + " 0, -1, 1,", + " 0, 1, -1,", + " 0, -1, -1]);", + "const grad4 = new Float32Array([0, 1, 1, 1, 0, 1, 1, -1, 0, 1, -1, 1, 0, 1, -1, -1,", + " 0, -1, 1, 1, 0, -1, 1, -1, 0, -1, -1, 1, 0, -1, -1, -1,", + " 1, 0, 1, 1, 1, 0, 1, -1, 1, 0, -1, 1, 1, 0, -1, -1,", + " -1, 0, 1, 1, -1, 0, 1, -1, -1, 0, -1, 1, -1, 0, -1, -1,", + " 1, 1, 0, 1, 1, 1, 0, -1, 1, -1, 0, 1, 1, -1, 0, -1,", + " -1, 1, 0, 1, -1, 1, 0, -1, -1, -1, 0, 1, -1, -1, 0, -1,", + " 1, 1, 1, 0, 1, 1, -1, 0, 1, -1, 1, 0, 1, -1, -1, 0,", + " -1, 1, 1, 0, -1, 1, -1, 0, -1, -1, 1, 0, -1, -1, -1, 0]);", + "class SimplexNoise {", + " constructor(randomOrSeed = Math.random) {", + " const random = typeof randomOrSeed == 'function' ? randomOrSeed : alea(randomOrSeed);", + " this.p = buildPermutationTable(random);", + " this.perm = new Uint8Array(512);", + " this.permMod12 = new Uint8Array(512);", + " for (let i = 0; i < 512; i++) {", + " this.perm[i] = this.p[i & 255];", + " this.permMod12[i] = this.perm[i] % 12;", + " }", + " }", + " noise2D(x, y) {", + " const permMod12 = this.permMod12;", + " const perm = this.perm;", + " let n0 = 0;", + " let n1 = 0;", + " let n2 = 0;", + " const s = (x + y) * F2;", + " const i = Math.floor(x + s);", + " const j = Math.floor(y + s);", + " const t = (i + j) * G2;", + " const X0 = i - t;", + " const Y0 = j - t;", + " const x0 = x - X0;", + " const y0 = y - Y0;", + " let i1, j1;", + " if (x0 > y0) {", + " i1 = 1;", + " j1 = 0;", + " }", + " else {", + " i1 = 0;", + " j1 = 1;", + " }", + " const x1 = x0 - i1 + G2;", + " const y1 = y0 - j1 + G2;", + " const x2 = x0 - 1.0 + 2.0 * G2;", + " const y2 = y0 - 1.0 + 2.0 * G2;", + " const ii = i & 255;", + " const jj = j & 255;", + " let t0 = 0.5 - x0 * x0 - y0 * y0;", + " if (t0 >= 0) {", + " const gi0 = permMod12[ii + perm[jj]] * 3;", + " t0 *= t0;", + " n0 = t0 * t0 * (grad3[gi0] * x0 + grad3[gi0 + 1] * y0);", + " }", + " let t1 = 0.5 - x1 * x1 - y1 * y1;", + " if (t1 >= 0) {", + " const gi1 = permMod12[ii + i1 + perm[jj + j1]] * 3;", + " t1 *= t1;", + " n1 = t1 * t1 * (grad3[gi1] * x1 + grad3[gi1 + 1] * y1);", + " }", + " let t2 = 0.5 - x2 * x2 - y2 * y2;", + " if (t2 >= 0) {", + " const gi2 = permMod12[ii + 1 + perm[jj + 1]] * 3;", + " t2 *= t2;", + " n2 = t2 * t2 * (grad3[gi2] * x2 + grad3[gi2 + 1] * y2);", + " }", + " return 70.0 * (n0 + n1 + n2);", + " }", + " noise3D(x, y, z) {", + " const permMod12 = this.permMod12;", + " const perm = this.perm;", + " let n0, n1, n2, n3;", + " const s = (x + y + z) * F3;", + " const i = Math.floor(x + s);", + " const j = Math.floor(y + s);", + " const k = Math.floor(z + s);", + " const t = (i + j + k) * G3;", + " const X0 = i - t;", + " const Y0 = j - t;", + " const Z0 = k - t;", + " const x0 = x - X0;", + " const y0 = y - Y0;", + " const z0 = z - Z0;", + " let i1, j1, k1;", + " let i2, j2, k2;", + " if (x0 >= y0) {", + " if (y0 >= z0) {", + " i1 = 1;", + " j1 = 0;", + " k1 = 0;", + " i2 = 1;", + " j2 = 1;", + " k2 = 0;", + " }", + " else if (x0 >= z0) {", + " i1 = 1;", + " j1 = 0;", + " k1 = 0;", + " i2 = 1;", + " j2 = 0;", + " k2 = 1;", + " }", + " else {", + " i1 = 0;", + " j1 = 0;", + " k1 = 1;", + " i2 = 1;", + " j2 = 0;", + " k2 = 1;", + " }", + " }", + " else {", + " if (y0 < z0) {", + " i1 = 0;", + " j1 = 0;", + " k1 = 1;", + " i2 = 0;", + " j2 = 1;", + " k2 = 1;", + " }", + " else if (x0 < z0) {", + " i1 = 0;", + " j1 = 1;", + " k1 = 0;", + " i2 = 0;", + " j2 = 1;", + " k2 = 1;", + " }", + " else {", + " i1 = 0;", + " j1 = 1;", + " k1 = 0;", + " i2 = 1;", + " j2 = 1;", + " k2 = 0;", + " }", + " }", + " const x1 = x0 - i1 + G3;", + " const y1 = y0 - j1 + G3;", + " const z1 = z0 - k1 + G3;", + " const x2 = x0 - i2 + 2.0 * G3;", + " const y2 = y0 - j2 + 2.0 * G3;", + " const z2 = z0 - k2 + 2.0 * G3;", + " const x3 = x0 - 1.0 + 3.0 * G3;", + " const y3 = y0 - 1.0 + 3.0 * G3;", + " const z3 = z0 - 1.0 + 3.0 * G3;", + " const ii = i & 255;", + " const jj = j & 255;", + " const kk = k & 255;", + " let t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0;", + " if (t0 < 0)", + " n0 = 0.0;", + " else {", + " const gi0 = permMod12[ii + perm[jj + perm[kk]]] * 3;", + " t0 *= t0;", + " n0 = t0 * t0 * (grad3[gi0] * x0 + grad3[gi0 + 1] * y0 + grad3[gi0 + 2] * z0);", + " }", + " let t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1;", + " if (t1 < 0)", + " n1 = 0.0;", + " else {", + " const gi1 = permMod12[ii + i1 + perm[jj + j1 + perm[kk + k1]]] * 3;", + " t1 *= t1;", + " n1 = t1 * t1 * (grad3[gi1] * x1 + grad3[gi1 + 1] * y1 + grad3[gi1 + 2] * z1);", + " }", + " let t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2;", + " if (t2 < 0)", + " n2 = 0.0;", + " else {", + " const gi2 = permMod12[ii + i2 + perm[jj + j2 + perm[kk + k2]]] * 3;", + " t2 *= t2;", + " n2 = t2 * t2 * (grad3[gi2] * x2 + grad3[gi2 + 1] * y2 + grad3[gi2 + 2] * z2);", + " }", + " let t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3;", + " if (t3 < 0)", + " n3 = 0.0;", + " else {", + " const gi3 = permMod12[ii + 1 + perm[jj + 1 + perm[kk + 1]]] * 3;", + " t3 *= t3;", + " n3 = t3 * t3 * (grad3[gi3] * x3 + grad3[gi3 + 1] * y3 + grad3[gi3 + 2] * z3);", + " }", + " return 32.0 * (n0 + n1 + n2 + n3);", + " }", + " noise4D(x, y, z, w) {", + " const perm = this.perm;", + " let n0, n1, n2, n3, n4;", + " const s = (x + y + z + w) * F4;", + " const i = Math.floor(x + s);", + " const j = Math.floor(y + s);", + " const k = Math.floor(z + s);", + " const l = Math.floor(w + s);", + " const t = (i + j + k + l) * G4;", + " const X0 = i - t;", + " const Y0 = j - t;", + " const Z0 = k - t;", + " const W0 = l - t;", + " const x0 = x - X0;", + " const y0 = y - Y0;", + " const z0 = z - Z0;", + " const w0 = w - W0;", + " let rankx = 0;", + " let ranky = 0;", + " let rankz = 0;", + " let rankw = 0;", + " if (x0 > y0)", + " rankx++;", + " else", + " ranky++;", + " if (x0 > z0)", + " rankx++;", + " else", + " rankz++;", + " if (x0 > w0)", + " rankx++;", + " else", + " rankw++;", + " if (y0 > z0)", + " ranky++;", + " else", + " rankz++;", + " if (y0 > w0)", + " ranky++;", + " else", + " rankw++;", + " if (z0 > w0)", + " rankz++;", + " else", + " rankw++;", + " const i1 = rankx >= 3 ? 1 : 0;", + " const j1 = ranky >= 3 ? 1 : 0;", + " const k1 = rankz >= 3 ? 1 : 0;", + " const l1 = rankw >= 3 ? 1 : 0;", + " const i2 = rankx >= 2 ? 1 : 0;", + " const j2 = ranky >= 2 ? 1 : 0;", + " const k2 = rankz >= 2 ? 1 : 0;", + " const l2 = rankw >= 2 ? 1 : 0;", + " const i3 = rankx >= 1 ? 1 : 0;", + " const j3 = ranky >= 1 ? 1 : 0;", + " const k3 = rankz >= 1 ? 1 : 0;", + " const l3 = rankw >= 1 ? 1 : 0;", + " const x1 = x0 - i1 + G4;", + " const y1 = y0 - j1 + G4;", + " const z1 = z0 - k1 + G4;", + " const w1 = w0 - l1 + G4;", + " const x2 = x0 - i2 + 2.0 * G4;", + " const y2 = y0 - j2 + 2.0 * G4;", + " const z2 = z0 - k2 + 2.0 * G4;", + " const w2 = w0 - l2 + 2.0 * G4;", + " const x3 = x0 - i3 + 3.0 * G4;", + " const y3 = y0 - j3 + 3.0 * G4;", + " const z3 = z0 - k3 + 3.0 * G4;", + " const w3 = w0 - l3 + 3.0 * G4;", + " const x4 = x0 - 1.0 + 4.0 * G4;", + " const y4 = y0 - 1.0 + 4.0 * G4;", + " const z4 = z0 - 1.0 + 4.0 * G4;", + " const w4 = w0 - 1.0 + 4.0 * G4;", + " const ii = i & 255;", + " const jj = j & 255;", + " const kk = k & 255;", + " const ll = l & 255;", + " let t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0;", + " if (t0 < 0)", + " n0 = 0.0;", + " else {", + " const gi0 = (perm[ii + perm[jj + perm[kk + perm[ll]]]] % 32) * 4;", + " t0 *= t0;", + " n0 = t0 * t0 * (grad4[gi0] * x0 + grad4[gi0 + 1] * y0 + grad4[gi0 + 2] * z0 + grad4[gi0 + 3] * w0);", + " }", + " let t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1;", + " if (t1 < 0)", + " n1 = 0.0;", + " else {", + " const gi1 = (perm[ii + i1 + perm[jj + j1 + perm[kk + k1 + perm[ll + l1]]]] % 32) * 4;", + " t1 *= t1;", + " n1 = t1 * t1 * (grad4[gi1] * x1 + grad4[gi1 + 1] * y1 + grad4[gi1 + 2] * z1 + grad4[gi1 + 3] * w1);", + " }", + " let t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2;", + " if (t2 < 0)", + " n2 = 0.0;", + " else {", + " const gi2 = (perm[ii + i2 + perm[jj + j2 + perm[kk + k2 + perm[ll + l2]]]] % 32) * 4;", + " t2 *= t2;", + " n2 = t2 * t2 * (grad4[gi2] * x2 + grad4[gi2 + 1] * y2 + grad4[gi2 + 2] * z2 + grad4[gi2 + 3] * w2);", + " }", + " let t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3;", + " if (t3 < 0)", + " n3 = 0.0;", + " else {", + " const gi3 = (perm[ii + i3 + perm[jj + j3 + perm[kk + k3 + perm[ll + l3]]]] % 32) * 4;", + " t3 *= t3;", + " n3 = t3 * t3 * (grad4[gi3] * x3 + grad4[gi3 + 1] * y3 + grad4[gi3 + 2] * z3 + grad4[gi3 + 3] * w3);", + " }", + " let t4 = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4;", + " if (t4 < 0)", + " n4 = 0.0;", + " else {", + " const gi4 = (perm[ii + 1 + perm[jj + 1 + perm[kk + 1 + perm[ll + 1]]]] % 32) * 4;", + " t4 *= t4;", + " n4 = t4 * t4 * (grad4[gi4] * x4 + grad4[gi4 + 1] * y4 + grad4[gi4 + 2] * z4 + grad4[gi4 + 3] * w4);", + " }", + " return 27.0 * (n0 + n1 + n2 + n3 + n4);", + " }", + "}", + "function buildPermutationTable(random) {", + " const p = new Uint8Array(256);", + " for (let i = 0; i < 256; i++) {", + " p[i] = i;", + " }", + " for (let i = 0; i < 255; i++) {", + " const r = i + ~~(random() * (256 - i));", + " const aux = p[i];", + " p[i] = p[r];", + " p[r] = aux;", + " }", + " return p;", + "}", + "function alea(seed) {", + " let s0 = 0;", + " let s1 = 0;", + " let s2 = 0;", + " let c = 1;", + " const mash = masher();", + " s0 = mash(' ');", + " s1 = mash(' ');", + " s2 = mash(' ');", + " s0 -= mash(seed);", + " if (s0 < 0) {", + " s0 += 1;", + " }", + " s1 -= mash(seed);", + " if (s1 < 0) {", + " s1 += 1;", + " }", + " s2 -= mash(seed);", + " if (s2 < 0) {", + " s2 += 1;", + " }", + " return function () {", + " const t = 2091639 * s0 + c * 2.3283064365386963e-10;", + " s0 = s1;", + " s1 = s2;", + " return s2 = t - (c = t | 0);", + " };", + "}", + "function masher() {", + " let n = 0xefc8249d;", + " return function (data) {", + " data = data.toString();", + " for (let i = 0; i < data.length; i++) {", + " n += data.charCodeAt(i);", + " let h = 0.02519603282416938 * n;", + " n = h >>> 0;", + " h -= n;", + " h *= n;", + " n = h >>> 0;", + " h -= n;", + " n += h * 0x100000000;", + " }", + " return (n >>> 0) * 2.3283064365386963e-10;", + " };", + "}", + "", + "class TurbulenceField {", + " constructor(scale, octaves, velocityMultiplier, timeScale) {", + " this.scale = scale;", + " this.octaves = octaves;", + " this.velocityMultiplier = velocityMultiplier;", + " this.timeScale = timeScale;", + " this.type = 'TurbulenceField';", + " this.generator = new SimplexNoise();", + " this.timeOffset = new THREE.Vector3();", + " this.temp = new THREE.Vector3();", + " this.temp2 = new THREE.Vector3();", + " this.timeOffset.x = Math.random() / this.scale.x * this.timeScale.x;", + " this.timeOffset.y = Math.random() / this.scale.y * this.timeScale.y;", + " this.timeOffset.z = Math.random() / this.scale.z * this.timeScale.z;", + " }", + " initialize(particle) {", + " }", + " update(particle, delta) {", + " const x = particle.position.x / this.scale.x;", + " const y = particle.position.y / this.scale.y;", + " const z = particle.position.z / this.scale.z;", + " this.temp.set(0, 0, 0);", + " let lvl = 1;", + " for (let i = 0; i < this.octaves; i++) {", + " this.temp2.set(this.generator.noise4D(x * lvl, y * lvl, z * lvl, this.timeOffset.x * lvl) / lvl, this.generator.noise4D(x * lvl, y * lvl, z * lvl, this.timeOffset.y * lvl) / lvl, this.generator.noise4D(x * lvl, y * lvl, z * lvl, this.timeOffset.z * lvl) / lvl);", + " this.temp.add(this.temp2);", + " lvl *= 2;", + " }", + " this.temp.multiply(this.velocityMultiplier);", + " particle.velocity.addScaledVector(this.temp, delta);", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " scale: [this.scale.x, this.scale.y, this.scale.z],", + " octaves: this.octaves,", + " velocityMultiplier: [this.velocityMultiplier.x, this.velocityMultiplier.y, this.velocityMultiplier.z],", + " timeScale: [this.timeScale.x, this.timeScale.y, this.timeScale.z],", + " };", + " }", + " frameUpdate(delta) {", + " this.timeOffset.x += delta * this.timeScale.x;", + " this.timeOffset.y += delta * this.timeScale.y;", + " this.timeOffset.z += delta * this.timeScale.z;", + " }", + " static fromJSON(json) {", + " return new TurbulenceField(new THREE.Vector3(json.scale[0], json.scale[1], json.scale[2]), json.octaves, new THREE.Vector3(json.velocityMultiplier[0], json.velocityMultiplier[1], json.velocityMultiplier[2]), new THREE.Vector3(json.timeScale[0], json.timeScale[1], json.timeScale[2]));", + " }", + " clone() {", + " return new TurbulenceField(this.scale.clone(), this.octaves, this.velocityMultiplier.clone(), this.timeScale.clone());", + " }", + " reset() {", + " }", + "}", + "", + "function randomInt(a, b) {", + " return Math.floor(Math.random() * (b - a)) + a;", + "}", + "", + "const generators = [];", + "const tempV$2 = new THREE.Vector3();", + "const tempQ$2 = new THREE.Quaternion();", + "class Noise {", + " constructor(frequency, power, positionAmount = new ConstantValue(1), rotationAmount = new ConstantValue(0)) {", + " this.frequency = frequency;", + " this.power = power;", + " this.positionAmount = positionAmount;", + " this.rotationAmount = rotationAmount;", + " this.type = 'Noise';", + " this.duration = 0;", + " if (generators.length === 0) {", + " for (let i = 0; i < 100; i++) {", + " generators.push(new SimplexNoise());", + " }", + " }", + " }", + " initialize(particle) {", + " particle.lastPosNoise = new THREE.Vector3();", + " if (typeof particle.rotation === 'number') {", + " particle.lastRotNoise = 0;", + " }", + " else {", + " particle.lastRotNoise = new THREE.Quaternion();", + " }", + " particle.generatorIndex = [randomInt(0, 100), randomInt(0, 100), randomInt(0, 100), randomInt(0, 100)];", + " }", + " update(particle, _) {", + " let frequency = this.frequency.genValue(particle.age / particle.life);", + " let power = this.power.genValue(particle.age / particle.life);", + " let positionAmount = this.positionAmount.genValue(particle.age / particle.life);", + " let rotationAmount = this.rotationAmount.genValue(particle.age / particle.life);", + " if (positionAmount > 0 && particle.lastPosNoise !== undefined) {", + " particle.position.sub(particle.lastPosNoise);", + " tempV$2.set(generators[particle.generatorIndex[0]].noise2D(0, particle.age * frequency) *", + " power *", + " positionAmount, generators[particle.generatorIndex[1]].noise2D(0, particle.age * frequency) *", + " power *", + " positionAmount, generators[particle.generatorIndex[2]].noise2D(0, particle.age * frequency) *", + " power *", + " positionAmount);", + " particle.position.add(tempV$2);", + " particle.lastPosNoise.copy(tempV$2);", + " }", + " if (rotationAmount > 0 && particle.lastRotNoise !== undefined) {", + " if (typeof particle.rotation === 'number') {", + " particle.rotation -= particle.lastRotNoise;", + " particle.rotation +=", + " generators[particle.generatorIndex[3]].noise2D(0, particle.age * frequency) *", + " Math.PI *", + " power *", + " rotationAmount;", + " }", + " else {", + " particle.lastRotNoise.invert();", + " particle.rotation.multiply(particle.lastRotNoise);", + " tempQ$2", + " .set(generators[particle.generatorIndex[0]].noise2D(0, particle.age * frequency) *", + " power *", + " rotationAmount, generators[particle.generatorIndex[1]].noise2D(0, particle.age * frequency) *", + " power *", + " rotationAmount, generators[particle.generatorIndex[2]].noise2D(0, particle.age * frequency) *", + " power *", + " rotationAmount, generators[particle.generatorIndex[3]].noise2D(0, particle.age * frequency) *", + " power *", + " rotationAmount)", + " .normalize();", + " particle.rotation.multiply(tempQ$2);", + " particle.lastRotNoise.copy(tempQ$2);", + " }", + " }", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " frequency: this.frequency.toJSON(),", + " power: this.power.toJSON(),", + " positionAmount: this.positionAmount.toJSON(),", + " rotationAmount: this.rotationAmount.toJSON(),", + " };", + " }", + " frameUpdate(delta) {", + " this.duration += delta;", + " }", + " static fromJSON(json) {", + " return new Noise(ValueGeneratorFromJSON(json.frequency), ValueGeneratorFromJSON(json.power), ValueGeneratorFromJSON(json.positionAmount), ValueGeneratorFromJSON(json.rotationAmount));", + " }", + " clone() {", + " return new Noise(this.frequency.clone(), this.power.clone(), this.positionAmount.clone(), this.rotationAmount.clone());", + " }", + " reset() { }", + "}", + "", + "class TextureSequencer {", + " constructor(scaleX = 0, scaleY = 0, position = new THREE.Vector3()) {", + " this.scaleX = scaleX;", + " this.scaleY = scaleY;", + " this.position = position;", + " this.locations = [];", + " }", + " transform(position, index) {", + " position.x = this.locations[index % this.locations.length].x * this.scaleX + this.position.x;", + " position.y = this.locations[index % this.locations.length].y * this.scaleY + this.position.y;", + " position.z = this.position.z;", + " }", + " static fromJSON(json) {", + " const textureSequencer = new TextureSequencer(json.scaleX, json.scaleY, new THREE.Vector3(json.position[0], json.position[1], json.position[2]));", + " textureSequencer.locations = json.locations.map((loc) => new THREE.Vector2(loc.x, loc.y));", + " return textureSequencer;", + " }", + " clone() {", + " const textureSequencer = new TextureSequencer(this.scaleX, this.scaleY, this.position.clone());", + " textureSequencer.locations = this.locations.map(loc => loc.clone());", + " return textureSequencer;", + " }", + " toJSON() {", + " return {", + " scaleX: this.scaleX,", + " scaleY: this.scaleY,", + " position: this.position,", + " locations: this.locations.map(loc => ({", + " x: loc.x,", + " y: loc.y,", + " }))", + " };", + " }", + " fromImage(img, threshold) {", + " const canvas = document.createElement(\"canvas\");", + " canvas.width = img.width;", + " canvas.height = img.height;", + " const ctx = canvas.getContext(\"2d\");", + " if (!ctx) {", + " return;", + " }", + " ctx.drawImage(img, 0, 0);", + " const data = ctx.getImageData(0, 0, canvas.width, canvas.height, { colorSpace: \"srgb\" });", + " canvas.remove();", + " this.locations.length = 0;", + " for (let i = 0; i < data.height; i++) {", + " for (let j = 0; j < data.width; j++) {", + " if (data.data[(i * data.width + j) * 4 + 3] > threshold) {", + " this.locations.push(new THREE.Vector2(j, data.height - i));", + " }", + " }", + " }", + " }", + "}", + "", + "function SequencerFromJSON(json) {", + " switch (json.type) {", + " case 'TextureSequencer':", + " return TextureSequencer.fromJSON(json);", + " default:", + " return new TextureSequencer();", + " }", + "}", + "", + "class ApplySequences {", + " constructor(delayBetweenParticles) {", + " this.type = 'ApplySequences';", + " this.sequencers = [];", + " this.time = 0;", + " this.index = 0;", + " this.pCount = 0;", + " this.tempV = new THREE.Vector3();", + " this.delay = delayBetweenParticles;", + " }", + " initialize(particle) {", + " particle.id = this.pCount;", + " particle.dst = new THREE.Vector3();", + " particle.begin = new THREE.Vector3();", + " particle.inMotion = false;", + " this.pCount++;", + " }", + " reset() {", + " this.time = 0;", + " this.index = 0;", + " this.pCount = 0;", + " }", + " update(particle, delta) {", + " const sequencer = this.sequencers[this.index];", + " const delay = particle.id * this.delay;", + " if (this.time >= sequencer[0].a + delay && this.time <= sequencer[0].b + delay) {", + " if (!particle.inMotion) {", + " particle.inMotion = true;", + " particle.begin.copy(particle.position);", + " sequencer[1].transform(particle.dst, particle.id);", + " }", + " particle.position.lerpVectors(particle.begin, particle.dst, ApplySequences.BEZIER.genValue((this.time - sequencer[0].a - delay) / (sequencer[0].b - sequencer[0].a)));", + " }", + " else if (this.time > sequencer[0].b + delay) {", + " particle.inMotion = false;", + " }", + " }", + " frameUpdate(delta) {", + " while (this.index + 1 < this.sequencers.length && this.time >= this.sequencers[this.index + 1][0].a) {", + " this.index++;", + " }", + " this.time += delta;", + " }", + " appendSequencer(range, sequencer) {", + " this.sequencers.push([range, sequencer]);", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " delay: this.delay,", + " sequencers: this.sequencers.map(([range, sequencer]) => ({", + " range: range.toJSON(),", + " sequencer: sequencer.toJSON(),", + " })),", + " };", + " }", + " static fromJSON(json) {", + " const seq = new ApplySequences(json.delay);", + " json.sequencers.forEach((sequencerJson) => {", + " seq.sequencers.push([ValueGeneratorFromJSON(sequencerJson.range), SequencerFromJSON(sequencerJson.sequencer)]);", + " });", + " return seq;", + " }", + " clone() {", + " const applySequences = new ApplySequences(this.delay);", + " applySequences.sequencers = this.sequencers.map(seq => [seq[0].clone(), seq[1].clone()]);", + " return applySequences;", + " }", + "}", + "ApplySequences.BEZIER = new Bezier(0, 0, 1, 1);", + "", + "let physicsResolver;", + "function setPhysicsResolver(resolver) {", + " physicsResolver = resolver;", + "}", + "function getPhysicsResolver() {", + " return physicsResolver;", + "}", + "class ApplyCollision {", + " constructor(resolver, bounce) {", + " this.resolver = resolver;", + " this.bounce = bounce;", + " this.type = 'ApplyCollision';", + " this.tempV = new THREE.Vector3();", + " }", + " initialize(particle) {", + " }", + " update(particle, delta) {", + " if (this.resolver.resolve(particle.position, this.tempV)) {", + " particle.velocity.reflect(this.tempV).multiplyScalar(this.bounce);", + " }", + " }", + " frameUpdate(delta) {", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " bounce: this.bounce,", + " };", + " }", + " static fromJSON(json) {", + " return new ApplyCollision(getPhysicsResolver(), json.bounce);", + " }", + " clone() {", + " return new ApplyCollision(this.resolver, this.bounce);", + " }", + " reset() {", + " }", + "}", + "", + "class ColorBySpeed {", + " constructor(color, speedRange) {", + " this.color = color;", + " this.speedRange = speedRange;", + " this.type = 'ColorBySpeed';", + " }", + " initialize(particle) {", + " if (this.color.type === 'memorizedFunction') {", + " particle.colorOverLifeMemory = {};", + " this.color.startGen(particle.colorOverLifeMemory);", + " }", + " }", + " update(particle, delta) {", + " const t = (particle.startSpeed - this.speedRange.a) / (this.speedRange.b - this.speedRange.a);", + " if (this.color.type === 'memorizedFunction') {", + " this.color.genColor(particle.color, t, particle.colorOverLifeMemory);", + " }", + " else {", + " this.color.genColor(particle.color, t);", + " }", + " particle.color.x *= particle.startColor.x;", + " particle.color.y *= particle.startColor.y;", + " particle.color.z *= particle.startColor.z;", + " particle.color.w *= particle.startColor.w;", + " }", + " frameUpdate(delta) { }", + " toJSON() {", + " return {", + " type: this.type,", + " color: this.color.toJSON(),", + " speedRange: this.speedRange.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new ColorBySpeed(ColorGeneratorFromJSON(json.color), IntervalValue.fromJSON(json.speedRange));", + " }", + " clone() {", + " return new ColorBySpeed(this.color.clone(), this.speedRange.clone());", + " }", + " reset() { }", + "}", + "", + "class SizeBySpeed {", + " initialize(particle) { }", + " constructor(size, speedRange) {", + " this.size = size;", + " this.speedRange = speedRange;", + " this.type = 'SizeBySpeed';", + " }", + " update(particle) {", + " const t = (particle.startSpeed - this.speedRange.a) / (this.speedRange.b - this.speedRange.a);", + " particle.size = particle.startSize * this.size.genValue(t);", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " size: this.size.toJSON(),", + " speedRange: this.speedRange.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new SizeBySpeed(ValueGeneratorFromJSON(json.size), IntervalValue.fromJSON(json.speedRange));", + " }", + " frameUpdate(delta) { }", + " clone() {", + " return new SizeBySpeed(this.size.clone(), this.speedRange.clone());", + " }", + " reset() { }", + "}", + "", + "class RotationBySpeed {", + " constructor(angularVelocity, speedRange) {", + " this.angularVelocity = angularVelocity;", + " this.speedRange = speedRange;", + " this.type = 'RotationBySpeed';", + " this.tempQuat = new THREE.Quaternion();", + " }", + " initialize(particle) { }", + " update(particle, delta) {", + " const t = (particle.startSpeed - this.speedRange.a) / (this.speedRange.b - this.speedRange.a);", + " particle.rotation += delta * this.angularVelocity.genValue(t);", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " angularVelocity: this.angularVelocity.toJSON(),", + " speedRange: this.speedRange.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new RotationBySpeed(ValueGeneratorFromJSON(json.angularVelocity), IntervalValue.fromJSON(json.speedRange));", + " }", + " frameUpdate(delta) { }", + " clone() {", + " return new RotationBySpeed(this.angularVelocity.clone(), this.speedRange.clone());", + " }", + " reset() { }", + "}", + "", + "class LimitSpeedOverLife {", + " initialize(particle) { }", + " constructor(speed, dampen) {", + " this.speed = speed;", + " this.dampen = dampen;", + " this.type = 'LimitSpeedOverLife';", + " }", + " update(particle, delta) {", + " let speed = particle.velocity.length();", + " let limit = this.speed.genValue(particle.age / particle.life);", + " if (speed > limit) {", + " const percent = (speed - limit) / speed;", + " particle.velocity.multiplyScalar(1 - percent * this.dampen * delta * 20);", + " }", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " speed: this.speed.toJSON(),", + " dampen: this.dampen,", + " };", + " }", + " static fromJSON(json) {", + " return new LimitSpeedOverLife(ValueGeneratorFromJSON(json.speed), json.dampen);", + " }", + " frameUpdate(delta) { }", + " clone() {", + " return new LimitSpeedOverLife(this.speed.clone(), this.dampen);", + " }", + " reset() { }", + "}", + "", + "const BehaviorTypes = {", + " ApplyForce: {", + " type: 'ApplyForce',", + " constructor: ApplyForce,", + " params: [", + " ['direction', 'vec3'],", + " ['magnitude', 'value'],", + " ],", + " loadJSON: ApplyForce.fromJSON,", + " },", + " Noise: {", + " type: 'Noise',", + " constructor: Noise,", + " params: [", + " ['frequency', 'value'],", + " ['power', 'value'],", + " ['positionAmount', 'value'],", + " ['rotationAmount', 'value'],", + " ],", + " loadJSON: Noise.fromJSON,", + " },", + " TurbulenceField: {", + " type: 'TurbulenceField',", + " constructor: TurbulenceField,", + " params: [", + " ['scale', 'vec3'],", + " ['octaves', 'number'],", + " ['velocityMultiplier', 'vec3'],", + " ['timeScale', 'vec3'],", + " ],", + " loadJSON: TurbulenceField.fromJSON,", + " },", + " GravityForce: {", + " type: 'GravityForce',", + " constructor: GravityForce,", + " params: [", + " ['center', 'vec3'],", + " ['magnitude', 'number'],", + " ],", + " loadJSON: GravityForce.fromJSON,", + " },", + " ColorOverLife: {", + " type: 'ColorOverLife',", + " constructor: ColorOverLife,", + " params: [['color', 'colorFunc']],", + " loadJSON: ColorOverLife.fromJSON,", + " },", + " RotationOverLife: {", + " type: 'RotationOverLife',", + " constructor: RotationOverLife,", + " params: [['angularVelocity', 'valueFunc']],", + " loadJSON: RotationOverLife.fromJSON,", + " },", + " Rotation3DOverLife: {", + " type: 'Rotation3DOverLife',", + " constructor: Rotation3DOverLife,", + " params: [['angularVelocity', 'rotationFunc']],", + " loadJSON: Rotation3DOverLife.fromJSON,", + " },", + " SizeOverLife: {", + " type: 'SizeOverLife',", + " constructor: SizeOverLife,", + " params: [['size', 'valueFunc']],", + " loadJSON: SizeOverLife.fromJSON,", + " },", + " ColorBySpeed: {", + " type: 'ColorBySpeed',", + " constructor: ColorBySpeed,", + " params: [", + " ['color', 'colorFunc'],", + " ['speedRange', 'range'],", + " ],", + " loadJSON: ColorBySpeed.fromJSON,", + " },", + " RotationBySpeed: {", + " type: 'RotationBySpeed',", + " constructor: RotationBySpeed,", + " params: [", + " ['angularVelocity', 'valueFunc'],", + " ['speedRange', 'range'],", + " ],", + " loadJSON: RotationBySpeed.fromJSON,", + " },", + " SizeBySpeed: {", + " type: 'SizeBySpeed',", + " constructor: SizeBySpeed,", + " params: [", + " ['size', 'valueFunc'],", + " ['speedRange', 'range'],", + " ],", + " loadJSON: SizeBySpeed.fromJSON,", + " },", + " SpeedOverLife: {", + " type: 'SpeedOverLife',", + " constructor: SpeedOverLife,", + " params: [['speed', 'valueFunc']],", + " loadJSON: SpeedOverLife.fromJSON,", + " },", + " FrameOverLife: {", + " type: 'FrameOverLife',", + " constructor: FrameOverLife,", + " params: [['frame', 'valueFunc']],", + " loadJSON: FrameOverLife.fromJSON,", + " },", + " ForceOverLife: {", + " type: 'ForceOverLife',", + " constructor: ForceOverLife,", + " params: [", + " ['x', 'valueFunc'],", + " ['y', 'valueFunc'],", + " ['z', 'valueFunc'],", + " ],", + " loadJSON: ForceOverLife.fromJSON,", + " },", + " OrbitOverLife: {", + " type: 'OrbitOverLife',", + " constructor: OrbitOverLife,", + " params: [", + " ['orbitSpeed', 'valueFunc'],", + " ['axis', 'vec3'],", + " ],", + " loadJSON: OrbitOverLife.fromJSON,", + " },", + " WidthOverLength: {", + " type: 'WidthOverLength',", + " constructor: WidthOverLength,", + " params: [['width', 'valueFunc']],", + " loadJSON: WidthOverLength.fromJSON,", + " },", + " ChangeEmitDirection: {", + " type: 'ChangeEmitDirection',", + " constructor: ChangeEmitDirection,", + " params: [['angle', 'value']],", + " loadJSON: ChangeEmitDirection.fromJSON,", + " },", + " EmitSubParticleSystem: {", + " type: 'EmitSubParticleSystem',", + " constructor: EmitSubParticleSystem,", + " params: [", + " ['particleSystem', 'self'],", + " ['useVelocityAsBasis', 'boolean'],", + " ['subParticleSystem', 'particleSystem'],", + " ['mode', 'number'],", + " ['emitProbability', 'number'],", + " ],", + " loadJSON: EmitSubParticleSystem.fromJSON,", + " },", + " LimitSpeedOverLife: {", + " type: 'LimitSpeedOverLife',", + " constructor: LimitSpeedOverLife,", + " params: [", + " ['speed', 'valueFunc'],", + " ['dampen', 'number'],", + " ],", + " loadJSON: LimitSpeedOverLife.fromJSON,", + " },", + "};", + "function BehaviorFromJSON(json, particleSystem) {", + " return BehaviorTypes[json.type].loadJSON(json, particleSystem);", + "}", + "", + "let EmitterMode = void 0;", + "(function (EmitterMode) {", + " EmitterMode[EmitterMode[\"Random\"] = 0] = \"Random\";", + " EmitterMode[EmitterMode[\"Loop\"] = 1] = \"Loop\";", + " EmitterMode[EmitterMode[\"PingPong\"] = 2] = \"PingPong\";", + " EmitterMode[EmitterMode[\"Burst\"] = 3] = \"Burst\";", + "})(EmitterMode || (EmitterMode = {}));", + "function getValueFromEmitterMode(mode, currentValue, spread) {", + " let u;", + " if (EmitterMode.Random === mode) {", + " currentValue = Math.random();", + " }", + " if (spread > 0) {", + " u = Math.floor(currentValue / spread) * spread;", + " }", + " else {", + " u = currentValue;", + " }", + " switch (mode) {", + " case EmitterMode.Loop:", + " u = u % 1;", + " break;", + " case EmitterMode.PingPong:", + " u = Math.abs((u % 2) - 1);", + " break;", + " }", + " return u;", + "}", + "", + "class ConeEmitter {", + " constructor(parameters = {}) {", + " var _a, _b, _c, _d, _e, _f, _g;", + " this.type = 'cone';", + " this.currentValue = 0;", + " this.radius = (_a = parameters.radius) !== null && _a !== void 0 ? _a : 10;", + " this.arc = (_b = parameters.arc) !== null && _b !== void 0 ? _b : 2.0 * Math.PI;", + " this.thickness = (_c = parameters.thickness) !== null && _c !== void 0 ? _c : 1;", + " this.angle = (_d = parameters.angle) !== null && _d !== void 0 ? _d : Math.PI / 6;", + " this.mode = (_e = parameters.mode) !== null && _e !== void 0 ? _e : EmitterMode.Random;", + " this.spread = (_f = parameters.spread) !== null && _f !== void 0 ? _f : 0;", + " this.speed = (_g = parameters.speed) !== null && _g !== void 0 ? _g : new ConstantValue(1);", + " }", + " update(system, delta) {", + " if (EmitterMode.Random != this.mode) {", + " this.currentValue += this.speed.genValue(system.emissionState.time / system.duration) * delta;", + " }", + " }", + " initialize(p) {", + " const u = getValueFromEmitterMode(this.mode, this.currentValue, this.spread);", + " const rand = THREE.MathUtils.lerp(1 - this.thickness, 1, Math.random());", + " const theta = u * this.arc;", + " const r = Math.sqrt(rand);", + " const sinTheta = Math.sin(theta);", + " const cosTheta = Math.cos(theta);", + " p.position.x = r * cosTheta;", + " p.position.y = r * sinTheta;", + " p.position.z = 0;", + " const angle = this.angle * r;", + " p.velocity.set(0, 0, Math.cos(angle)).addScaledVector(p.position, Math.sin(angle)).multiplyScalar(p.startSpeed);", + " p.position.multiplyScalar(this.radius);", + " }", + " toJSON() {", + " return {", + " type: 'cone',", + " radius: this.radius,", + " arc: this.arc,", + " thickness: this.thickness,", + " angle: this.angle,", + " mode: this.mode,", + " spread: this.spread,", + " speed: this.speed.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new ConeEmitter({", + " radius: json.radius,", + " arc: json.arc,", + " thickness: json.thickness,", + " angle: json.angle,", + " mode: json.mode,", + " speed: json.speed ? ValueGeneratorFromJSON(json.speed) : undefined,", + " spread: json.spread,", + " });", + " }", + " clone() {", + " return new ConeEmitter({", + " radius: this.radius,", + " arc: this.arc,", + " thickness: this.thickness,", + " angle: this.angle,", + " mode: this.mode,", + " speed: this.speed.clone(),", + " spread: this.spread,", + " });", + " }", + "}", + "", + "class CircleEmitter {", + " constructor(parameters = {}) {", + " var _a, _b, _c, _d, _e, _f;", + " this.type = 'circle';", + " this.currentValue = 0;", + " this.radius = (_a = parameters.radius) !== null && _a !== void 0 ? _a : 10;", + " this.arc = (_b = parameters.arc) !== null && _b !== void 0 ? _b : 2.0 * Math.PI;", + " this.thickness = (_c = parameters.thickness) !== null && _c !== void 0 ? _c : 1;", + " this.mode = (_d = parameters.mode) !== null && _d !== void 0 ? _d : EmitterMode.Random;", + " this.spread = (_e = parameters.spread) !== null && _e !== void 0 ? _e : 0;", + " this.speed = (_f = parameters.speed) !== null && _f !== void 0 ? _f : new ConstantValue(1);", + " }", + " update(system, delta) {", + " this.currentValue += this.speed.genValue(system.emissionState.time / system.duration) * delta;", + " }", + " initialize(p) {", + " const u = getValueFromEmitterMode(this.mode, this.currentValue, this.spread);", + " const r = THREE.MathUtils.lerp(1 - this.thickness, 1, Math.random());", + " const theta = u * this.arc;", + " p.position.x = Math.cos(theta);", + " p.position.y = Math.sin(theta);", + " p.position.z = 0;", + " p.velocity.copy(p.position).multiplyScalar(p.startSpeed);", + " p.position.multiplyScalar(this.radius * r);", + " }", + " toJSON() {", + " return {", + " type: 'circle',", + " radius: this.radius,", + " arc: this.arc,", + " thickness: this.thickness,", + " mode: this.mode,", + " spread: this.spread,", + " speed: this.speed.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new CircleEmitter({", + " radius: json.radius,", + " arc: json.arc,", + " thickness: json.thickness,", + " mode: json.mode,", + " speed: json.speed ? ValueGeneratorFromJSON(json.speed) : undefined,", + " spread: json.spread,", + " });", + " }", + " clone() {", + " return new CircleEmitter({", + " radius: this.radius,", + " arc: this.arc,", + " thickness: this.thickness,", + " mode: this.mode,", + " speed: this.speed.clone(),", + " spread: this.spread,", + " });", + " }", + "}", + "", + "class DonutEmitter {", + " constructor(parameters = {}) {", + " var _a, _b, _c, _d, _e, _f, _g;", + " this.type = 'donut';", + " this.currentValue = 0;", + " this.radius = (_a = parameters.radius) !== null && _a !== void 0 ? _a : 10;", + " this.arc = (_b = parameters.arc) !== null && _b !== void 0 ? _b : 2.0 * Math.PI;", + " this.thickness = (_c = parameters.thickness) !== null && _c !== void 0 ? _c : 1;", + " this.donutRadius = (_d = parameters.donutRadius) !== null && _d !== void 0 ? _d : this.radius * 0.2;", + " this.mode = (_e = parameters.mode) !== null && _e !== void 0 ? _e : EmitterMode.Random;", + " this.spread = (_f = parameters.spread) !== null && _f !== void 0 ? _f : 0;", + " this.speed = (_g = parameters.speed) !== null && _g !== void 0 ? _g : new ConstantValue(1);", + " }", + " update(system, delta) {", + " if (EmitterMode.Random != this.mode) {", + " this.currentValue += this.speed.genValue(system.emissionState.time / system.duration) * delta;", + " }", + " }", + " initialize(p) {", + " const u = getValueFromEmitterMode(this.mode, this.currentValue, this.spread);", + " const v = Math.random();", + " const rand = THREE.MathUtils.lerp(1 - this.thickness, 1, Math.random());", + " const theta = u * this.arc;", + " const phi = v * Math.PI * 2;", + " const sinTheta = Math.sin(theta);", + " const cosTheta = Math.cos(theta);", + " p.position.x = this.radius * cosTheta;", + " p.position.y = this.radius * sinTheta;", + " p.position.z = 0;", + " p.velocity.z = this.donutRadius * rand * Math.sin(phi);", + " p.velocity.x = this.donutRadius * rand * Math.cos(phi) * cosTheta;", + " p.velocity.y = this.donutRadius * rand * Math.cos(phi) * sinTheta;", + " p.position.add(p.velocity);", + " p.velocity.normalize().multiplyScalar(p.startSpeed);", + " }", + " toJSON() {", + " return {", + " type: 'donut',", + " radius: this.radius,", + " arc: this.arc,", + " thickness: this.thickness,", + " donutRadius: this.donutRadius,", + " mode: this.mode,", + " spread: this.spread,", + " speed: this.speed.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new DonutEmitter({", + " radius: json.radius,", + " arc: json.arc,", + " thickness: json.thickness,", + " donutRadius: json.donutRadius,", + " mode: json.mode,", + " speed: json.speed ? ValueGeneratorFromJSON(json.speed) : undefined,", + " spread: json.spread,", + " });", + " }", + " clone() {", + " return new DonutEmitter({", + " radius: this.radius,", + " arc: this.arc,", + " thickness: this.thickness,", + " donutRadius: this.donutRadius,", + " mode: this.mode,", + " speed: this.speed.clone(),", + " spread: this.spread,", + " });", + " }", + "}", + "", + "class PointEmitter {", + " constructor() {", + " this.type = 'point';", + " }", + " update(system, delta) { }", + " initialize(p) {", + " const u = Math.random();", + " const v = Math.random();", + " const theta = u * Math.PI * 2;", + " const phi = Math.acos(2.0 * v - 1.0);", + " const r = Math.cbrt(Math.random());", + " const sinTheta = Math.sin(theta);", + " const cosTheta = Math.cos(theta);", + " const sinPhi = Math.sin(phi);", + " const cosPhi = Math.cos(phi);", + " p.velocity.x = r * sinPhi * cosTheta;", + " p.velocity.y = r * sinPhi * sinTheta;", + " p.velocity.z = r * cosPhi;", + " p.velocity.multiplyScalar(p.startSpeed);", + " p.position.setScalar(0);", + " }", + " toJSON() {", + " return {", + " type: 'point',", + " };", + " }", + " static fromJSON(json) {", + " return new PointEmitter();", + " }", + " clone() {", + " return new PointEmitter();", + " }", + "}", + "", + "class SphereEmitter {", + " constructor(parameters = {}) {", + " var _a, _b, _c, _d, _e, _f;", + " this.type = 'sphere';", + " this.currentValue = 0;", + " this.radius = (_a = parameters.radius) !== null && _a !== void 0 ? _a : 10;", + " this.arc = (_b = parameters.arc) !== null && _b !== void 0 ? _b : 2.0 * Math.PI;", + " this.thickness = (_c = parameters.thickness) !== null && _c !== void 0 ? _c : 1;", + " this.mode = (_d = parameters.mode) !== null && _d !== void 0 ? _d : EmitterMode.Random;", + " this.spread = (_e = parameters.spread) !== null && _e !== void 0 ? _e : 0;", + " this.speed = (_f = parameters.speed) !== null && _f !== void 0 ? _f : new ConstantValue(1);", + " }", + " update(system, delta) {", + " if (EmitterMode.Random != this.mode) {", + " this.currentValue += this.speed.genValue(system.emissionState.time / system.duration) * delta;", + " }", + " }", + " initialize(p) {", + " const u = getValueFromEmitterMode(this.mode, this.currentValue, this.spread);", + " const v = Math.random();", + " const rand = THREE.MathUtils.lerp(1 - this.thickness, 1, Math.random());", + " const theta = u * this.arc;", + " const phi = Math.acos(2.0 * v - 1.0);", + " const sinTheta = Math.sin(theta);", + " const cosTheta = Math.cos(theta);", + " const sinPhi = Math.sin(phi);", + " const cosPhi = Math.cos(phi);", + " p.position.x = sinPhi * cosTheta;", + " p.position.y = sinPhi * sinTheta;", + " p.position.z = cosPhi;", + " p.velocity.copy(p.position).multiplyScalar(p.startSpeed);", + " p.position.multiplyScalar(this.radius * rand);", + " }", + " toJSON() {", + " return {", + " type: 'sphere',", + " radius: this.radius,", + " arc: this.arc,", + " thickness: this.thickness,", + " mode: this.mode,", + " spread: this.spread,", + " speed: this.speed.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new SphereEmitter({", + " radius: json.radius,", + " arc: json.arc,", + " thickness: json.thickness,", + " mode: json.mode,", + " speed: json.speed ? ValueGeneratorFromJSON(json.speed) : undefined,", + " spread: json.spread,", + " });", + " }", + " clone() {", + " return new SphereEmitter({", + " radius: this.radius,", + " arc: this.arc,", + " thickness: this.thickness,", + " mode: this.mode,", + " speed: this.speed.clone(),", + " spread: this.spread,", + " });", + " }", + "}", + "", + "class HemisphereEmitter {", + " constructor(parameters = {}) {", + " var _a, _b, _c, _d, _e, _f;", + " this.type = 'sphere';", + " this.currentValue = 0;", + " this.radius = (_a = parameters.radius) !== null && _a !== void 0 ? _a : 10;", + " this.arc = (_b = parameters.arc) !== null && _b !== void 0 ? _b : 2.0 * Math.PI;", + " this.thickness = (_c = parameters.thickness) !== null && _c !== void 0 ? _c : 1;", + " this.mode = (_d = parameters.mode) !== null && _d !== void 0 ? _d : EmitterMode.Random;", + " this.spread = (_e = parameters.spread) !== null && _e !== void 0 ? _e : 0;", + " this.speed = (_f = parameters.speed) !== null && _f !== void 0 ? _f : new ConstantValue(1);", + " }", + " update(system, delta) {", + " if (EmitterMode.Random != this.mode) {", + " this.currentValue += this.speed.genValue(system.emissionState.time / system.duration) * delta;", + " }", + " }", + " initialize(p) {", + " const u = getValueFromEmitterMode(this.mode, this.currentValue, this.spread);", + " const v = Math.random();", + " const rand = THREE.MathUtils.lerp(1 - this.thickness, 1, Math.random());", + " const theta = u * this.arc;", + " const phi = Math.acos(v);", + " const sinTheta = Math.sin(theta);", + " const cosTheta = Math.cos(theta);", + " const sinPhi = Math.sin(phi);", + " const cosPhi = Math.cos(phi);", + " p.position.x = sinPhi * cosTheta;", + " p.position.y = sinPhi * sinTheta;", + " p.position.z = cosPhi;", + " p.velocity.copy(p.position).multiplyScalar(p.startSpeed);", + " p.position.multiplyScalar(this.radius * rand);", + " }", + " toJSON() {", + " return {", + " type: 'hemisphere',", + " radius: this.radius,", + " arc: this.arc,", + " thickness: this.thickness,", + " mode: this.mode,", + " spread: this.spread,", + " speed: this.speed.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new HemisphereEmitter({", + " radius: json.radius,", + " arc: json.arc,", + " thickness: json.thickness,", + " mode: json.mode,", + " speed: json.speed ? ValueGeneratorFromJSON(json.speed) : undefined,", + " spread: json.spread,", + " });", + " }", + " clone() {", + " return new HemisphereEmitter({", + " radius: this.radius,", + " arc: this.arc,", + " thickness: this.thickness,", + " mode: this.mode,", + " speed: this.speed.clone(),", + " spread: this.spread,", + " });", + " }", + "}", + "", + "class GridEmitter {", + " constructor(parameters = {}) {", + " var _a, _b, _c, _d;", + " this.type = 'grid';", + " this.width = (_a = parameters.width) !== null && _a !== void 0 ? _a : 1;", + " this.height = (_b = parameters.height) !== null && _b !== void 0 ? _b : 1;", + " this.column = (_c = parameters.column) !== null && _c !== void 0 ? _c : 10;", + " this.row = (_d = parameters.row) !== null && _d !== void 0 ? _d : 10;", + " }", + " initialize(p) {", + " const r = Math.floor(Math.random() * this.row);", + " const c = Math.floor(Math.random() * this.column);", + " p.position.x = (c * this.width) / this.column - this.width / 2;", + " p.position.y = (r * this.height) / this.row - this.height / 2;", + " p.position.z = 0;", + " p.velocity.set(0, 0, p.startSpeed);", + " }", + " toJSON() {", + " return {", + " type: 'grid',", + " width: this.width,", + " height: this.height,", + " column: this.column,", + " row: this.row,", + " };", + " }", + " static fromJSON(json) {", + " return new GridEmitter(json);", + " }", + " clone() {", + " return new GridEmitter({", + " width: this.width,", + " height: this.height,", + " column: this.column,", + " row: this.row,", + " });", + " }", + " update(system, delta) { }", + "}", + "", + "class MeshSurfaceEmitter {", + " get geometry() {", + " return this._geometry;", + " }", + " set geometry(geometry) {", + " this._geometry = geometry;", + " if (geometry === undefined) {", + " return;", + " }", + " if (typeof geometry === 'string') {", + " return;", + " }", + " const tri = new THREE.Triangle();", + " this._triangleIndexToArea.length = 0;", + " let area = 0;", + " if (!geometry.getIndex()) {", + " return;", + " }", + " const array = geometry.getIndex().array;", + " const triCount = array.length / 3;", + " this._triangleIndexToArea.push(0);", + " for (let i = 0; i < triCount; i++) {", + " tri.setFromAttributeAndIndices(geometry.getAttribute('position'), array[i * 3], array[i * 3 + 1], array[i * 3 + 2]);", + " area += tri.getArea();", + " this._triangleIndexToArea.push(area);", + " }", + " geometry.userData.triangleIndexToArea = this._triangleIndexToArea;", + " }", + " constructor(geometry) {", + " this.type = 'mesh_surface';", + " this._triangleIndexToArea = [];", + " this._tempA = new THREE.Vector3();", + " this._tempB = new THREE.Vector3();", + " this._tempC = new THREE.Vector3();", + " if (!geometry) {", + " return;", + " }", + " this.geometry = geometry;", + " }", + " initialize(p) {", + " const geometry = this._geometry;", + " if (!geometry || geometry.getIndex() === null) {", + " p.position.set(0, 0, 0);", + " p.velocity.set(0, 0, 1).multiplyScalar(p.startSpeed);", + " return;", + " }", + " const triCount = this._triangleIndexToArea.length - 1;", + " let left = 0, right = triCount;", + " const target = Math.random() * this._triangleIndexToArea[triCount];", + " while (left + 1 < right) {", + " const mid = Math.floor((left + right) / 2);", + " if (target < this._triangleIndexToArea[mid]) {", + " right = mid;", + " }", + " else {", + " left = mid;", + " }", + " }", + " let u1 = Math.random();", + " let u2 = Math.random();", + " if (u1 + u2 > 1) {", + " u1 = 1 - u1;", + " u2 = 1 - u2;", + " }", + " const index1 = geometry.getIndex().array[left * 3];", + " const index2 = geometry.getIndex().array[left * 3 + 1];", + " const index3 = geometry.getIndex().array[left * 3 + 2];", + " const positionBuffer = geometry.getAttribute('position');", + " this._tempA.fromBufferAttribute(positionBuffer, index1);", + " this._tempB.fromBufferAttribute(positionBuffer, index2);", + " this._tempC.fromBufferAttribute(positionBuffer, index3);", + " this._tempB.sub(this._tempA);", + " this._tempC.sub(this._tempA);", + " this._tempA.addScaledVector(this._tempB, u1).addScaledVector(this._tempC, u2);", + " p.position.copy(this._tempA);", + " this._tempA.copy(this._tempB).cross(this._tempC).normalize();", + " p.velocity.copy(this._tempA).normalize().multiplyScalar(p.startSpeed);", + " }", + " toJSON() {", + " return {", + " type: 'mesh_surface',", + " mesh: this._geometry ? this._geometry.uuid : '',", + " };", + " }", + " static fromJSON(json, meta) {", + " return new MeshSurfaceEmitter(meta.geometries[json.geometry]);", + " }", + " clone() {", + " return new MeshSurfaceEmitter(this._geometry);", + " }", + " update(system, delta) { }", + "}", + "", + "const EmitterShapes = {", + " circle: {", + " type: 'circle',", + " params: [", + " ['radius', 'number'],", + " ['arc', 'radian'],", + " ['thickness', 'number'],", + " ['mode', 'emitterMode'],", + " ['spread', 'number'],", + " ['speed', 'valueFunc'],", + " ],", + " constructor: CircleEmitter,", + " loadJSON: CircleEmitter.fromJSON,", + " },", + " cone: {", + " type: 'cone',", + " params: [", + " ['radius', 'number'],", + " ['arc', 'radian'],", + " ['thickness', 'number'],", + " ['angle', 'radian'],", + " ['mode', 'emitterMode'],", + " ['spread', 'number'],", + " ['speed', 'valueFunc'],", + " ],", + " constructor: ConeEmitter,", + " loadJSON: ConeEmitter.fromJSON,", + " },", + " donut: {", + " type: 'donut',", + " params: [", + " ['radius', 'number'],", + " ['arc', 'radian'],", + " ['thickness', 'number'],", + " ['donutRadius', 'number'],", + " ['mode', 'emitterMode'],", + " ['spread', 'number'],", + " ['speed', 'valueFunc'],", + " ],", + " constructor: DonutEmitter,", + " loadJSON: DonutEmitter.fromJSON,", + " },", + " point: { type: 'point', params: [], constructor: PointEmitter, loadJSON: PointEmitter.fromJSON },", + " sphere: {", + " type: 'sphere',", + " params: [", + " ['radius', 'number'],", + " ['arc', 'radian'],", + " ['thickness', 'number'],", + " ['angle', 'radian'],", + " ['mode', 'emitterMode'],", + " ['spread', 'number'],", + " ['speed', 'valueFunc'],", + " ],", + " constructor: SphereEmitter,", + " loadJSON: SphereEmitter.fromJSON,", + " },", + " hemisphere: {", + " type: 'hemisphere',", + " params: [", + " ['radius', 'number'],", + " ['arc', 'radian'],", + " ['thickness', 'number'],", + " ['angle', 'radian'],", + " ['mode', 'emitterMode'],", + " ['spread', 'number'],", + " ['speed', 'valueFunc'],", + " ],", + " constructor: HemisphereEmitter,", + " loadJSON: HemisphereEmitter.fromJSON,", + " },", + " grid: {", + " type: 'grid',", + " params: [", + " ['width', 'number'],", + " ['height', 'number'],", + " ['rows', 'number'],", + " ['column', 'number'],", + " ],", + " constructor: GridEmitter,", + " loadJSON: GridEmitter.fromJSON,", + " },", + " mesh_surface: {", + " type: 'mesh_surface',", + " params: [['geometry', 'geometry']],", + " constructor: MeshSurfaceEmitter,", + " loadJSON: MeshSurfaceEmitter.fromJSON,", + " },", + "};", + "function EmitterFromJSON(json, meta) {", + " return EmitterShapes[json.type].loadJSON(json, meta);", + "}", + "", + "let RenderMode = void 0;", + "(function (RenderMode) {", + " RenderMode[RenderMode[\"BillBoard\"] = 0] = \"BillBoard\";", + " RenderMode[RenderMode[\"StretchedBillBoard\"] = 1] = \"StretchedBillBoard\";", + " RenderMode[RenderMode[\"Mesh\"] = 2] = \"Mesh\";", + " RenderMode[RenderMode[\"Trail\"] = 3] = \"Trail\";", + " RenderMode[RenderMode[\"HorizontalBillBoard\"] = 4] = \"HorizontalBillBoard\";", + " RenderMode[RenderMode[\"VerticalBillBoard\"] = 5] = \"VerticalBillBoard\";", + "})(RenderMode || (RenderMode = {}));", + "class VFXBatch extends THREE.Mesh {", + " constructor(settings) {", + " super();", + " this.type = 'VFXBatch';", + " this.maxParticles = 1000;", + " this.systems = new Set();", + " const layers = new THREE.Layers();", + " layers.mask = settings.layers.mask;", + " const newMat = settings.material.clone();", + " newMat.defines = {};", + " Object.assign(newMat.defines, settings.material.defines);", + " this.settings = {", + " instancingGeometry: settings.instancingGeometry,", + " renderMode: settings.renderMode,", + " renderOrder: settings.renderOrder,", + " material: newMat,", + " uTileCount: settings.uTileCount,", + " vTileCount: settings.vTileCount,", + " layers: layers,", + " };", + " this.frustumCulled = false;", + " this.renderOrder = this.settings.renderOrder;", + " }", + " addSystem(system) {", + " this.systems.add(system);", + " }", + " removeSystem(system) {", + " this.systems.delete(system);", + " }", + "}", + "", + "const UP = new THREE.Vector3(0, 0, 1);", + "const tempQ$1 = new THREE.Quaternion();", + "const tempV$1 = new THREE.Vector3();", + "const tempV2$1 = new THREE.Vector3();", + "new THREE.Vector3();", + "const PREWARM_FPS$1 = 60;", + "const DEFAULT_GEOMETRY$1 = new THREE.PlaneGeometry(1, 1, 1, 1);", + "class ParticleSystem {", + " set time(time) {", + " this.emissionState.time = time;", + " }", + " get time() {", + " return this.emissionState.time;", + " }", + " get layers() {", + " return this.rendererSettings.layers;", + " }", + " get texture() {", + " return this.rendererSettings.material.map;", + " }", + " set texture(texture) {", + " this.rendererSettings.material.map = texture;", + " this.neededToUpdateRender = true;", + " }", + " get material() {", + " return this.rendererSettings.material;", + " }", + " set material(material) {", + " this.rendererSettings.material = material;", + " this.neededToUpdateRender = true;", + " }", + " get uTileCount() {", + " return this.rendererSettings.uTileCount;", + " }", + " set uTileCount(u) {", + " this.rendererSettings.uTileCount = u;", + " this.neededToUpdateRender = true;", + " }", + " get vTileCount() {", + " return this.rendererSettings.vTileCount;", + " }", + " set vTileCount(v) {", + " this.rendererSettings.vTileCount = v;", + " this.neededToUpdateRender = true;", + " }", + " get instancingGeometry() {", + " return this.rendererSettings.instancingGeometry;", + " }", + " set instancingGeometry(geometry) {", + " this.restart();", + " this.particles.length = 0;", + " this.rendererSettings.instancingGeometry = geometry;", + " this.neededToUpdateRender = true;", + " }", + " get renderMode() {", + " return this.rendererSettings.renderMode;", + " }", + " set renderMode(renderMode) {", + " if ((this.rendererSettings.renderMode != RenderMode.Trail && renderMode === RenderMode.Trail) ||", + " (this.rendererSettings.renderMode == RenderMode.Trail && renderMode !== RenderMode.Trail)) {", + " this.restart();", + " this.particles.length = 0;", + " }", + " if (this.rendererSettings.renderMode !== renderMode) {", + " switch (renderMode) {", + " case RenderMode.Trail:", + " this.rendererEmitterSettings = {", + " startLength: new ConstantValue(30),", + " followLocalOrigin: false,", + " };", + " break;", + " case RenderMode.Mesh:", + " this.rendererEmitterSettings = {", + " geometry: new THREE.PlaneGeometry(1, 1),", + " };", + " this.startRotation = new AxisAngleGenerator(new THREE.Vector3(0, 1, 0), new ConstantValue(0));", + " break;", + " case RenderMode.StretchedBillBoard:", + " this.rendererEmitterSettings = { speedFactor: 0, lengthFactor: 2 };", + " if (this.rendererSettings.renderMode === RenderMode.Mesh) {", + " this.startRotation = new ConstantValue(0);", + " }", + " break;", + " case RenderMode.BillBoard:", + " case RenderMode.VerticalBillBoard:", + " case RenderMode.HorizontalBillBoard:", + " this.rendererEmitterSettings = {};", + " if (this.rendererSettings.renderMode === RenderMode.Mesh) {", + " this.startRotation = new ConstantValue(0);", + " }", + " break;", + " }", + " }", + " this.rendererSettings.renderMode = renderMode;", + " this.neededToUpdateRender = true;", + " }", + " get renderOrder() {", + " return this.rendererSettings.renderOrder;", + " }", + " set renderOrder(renderOrder) {", + " this.rendererSettings.renderOrder = renderOrder;", + " this.neededToUpdateRender = true;", + " }", + " get blending() {", + " return this.rendererSettings.material.blending;", + " }", + " set blending(blending) {", + " this.rendererSettings.material.blending = blending;", + " this.neededToUpdateRender = true;", + " }", + " constructor(parameters) {", + " var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;", + " this.temp = new THREE.Vector3();", + " this.travelDistance = 0;", + " this.normalMatrix = new THREE.Matrix3();", + " this.firstTimeUpdate = true;", + " this.autoDestroy = parameters.autoDestroy === undefined ? false : parameters.autoDestroy;", + " this.duration = (_a = parameters.duration) !== null && _a !== void 0 ? _a : 1;", + " this.looping = parameters.looping === undefined ? true : parameters.looping;", + " this.prewarm = parameters.prewarm === undefined ? false : parameters.prewarm;", + " this.startLife = (_b = parameters.startLife) !== null && _b !== void 0 ? _b : new ConstantValue(5);", + " this.startSpeed = (_c = parameters.startSpeed) !== null && _c !== void 0 ? _c : new ConstantValue(0);", + " this.startRotation = (_d = parameters.startRotation) !== null && _d !== void 0 ? _d : new ConstantValue(0);", + " this.startSize = (_e = parameters.startSize) !== null && _e !== void 0 ? _e : new ConstantValue(1);", + " this.startColor = (_f = parameters.startColor) !== null && _f !== void 0 ? _f : new ConstantColor(new THREE.Vector4(1, 1, 1, 1));", + " this.emissionOverTime = (_g = parameters.emissionOverTime) !== null && _g !== void 0 ? _g : new ConstantValue(10);", + " this.emissionOverDistance = (_h = parameters.emissionOverDistance) !== null && _h !== void 0 ? _h : new ConstantValue(0);", + " this.emissionBursts = (_j = parameters.emissionBursts) !== null && _j !== void 0 ? _j : [];", + " this.onlyUsedByOther = (_k = parameters.onlyUsedByOther) !== null && _k !== void 0 ? _k : false;", + " this.emitterShape = (_l = parameters.shape) !== null && _l !== void 0 ? _l : new SphereEmitter();", + " this.behaviors = (_m = parameters.behaviors) !== null && _m !== void 0 ? _m : new Array();", + " this.worldSpace = (_o = parameters.worldSpace) !== null && _o !== void 0 ? _o : false;", + " this.rendererEmitterSettings = (_p = parameters.rendererEmitterSettings) !== null && _p !== void 0 ? _p : {};", + " if (parameters.renderMode === RenderMode.StretchedBillBoard) {", + " const stretchedBillboardSettings = this.rendererEmitterSettings;", + " if (parameters.speedFactor !== undefined) {", + " stretchedBillboardSettings.speedFactor = parameters.speedFactor;", + " }", + " stretchedBillboardSettings.speedFactor = (_q = stretchedBillboardSettings.speedFactor) !== null && _q !== void 0 ? _q : 0;", + " stretchedBillboardSettings.lengthFactor = (_r = stretchedBillboardSettings.lengthFactor) !== null && _r !== void 0 ? _r : 0;", + " }", + " this.rendererSettings = {", + " instancingGeometry: (_s = parameters.instancingGeometry) !== null && _s !== void 0 ? _s : DEFAULT_GEOMETRY$1,", + " renderMode: (_t = parameters.renderMode) !== null && _t !== void 0 ? _t : RenderMode.BillBoard,", + " renderOrder: (_u = parameters.renderOrder) !== null && _u !== void 0 ? _u : 0,", + " material: parameters.material,", + " uTileCount: (_v = parameters.uTileCount) !== null && _v !== void 0 ? _v : 1,", + " vTileCount: (_w = parameters.vTileCount) !== null && _w !== void 0 ? _w : 1,", + " layers: (_x = parameters.layers) !== null && _x !== void 0 ? _x : new THREE.Layers(),", + " };", + " this.neededToUpdateRender = true;", + " this.particles = new Array();", + " this.startTileIndex = parameters.startTileIndex || new ConstantValue(0);", + " this.emitter = new ParticleEmitter(this);", + " this.paused = false;", + " this.particleNum = 0;", + " this.emissionState = {", + " burstIndex: 0,", + " burstWaveIndex: 0,", + " time: 0,", + " waitEmiting: 0,", + " travelDistance: 0,", + " };", + " this.emitEnded = false;", + " this.markForDestroy = false;", + " this.prewarmed = false;", + " }", + " pause() {", + " this.paused = true;", + " }", + " play() {", + " this.paused = false;", + " }", + " spawn(count, emissionState, matrix) {", + " tempQ$1.setFromRotationMatrix(matrix);", + " const translation = tempV$1;", + " const quaternion = tempQ$1;", + " const scale = tempV2$1;", + " matrix.decompose(translation, quaternion, scale);", + " for (let i = 0; i < count; i++) {", + " this.particleNum++;", + " while (this.particles.length < this.particleNum) {", + " if (this.rendererSettings.renderMode === RenderMode.Trail) {", + " this.particles.push(new TrailParticle());", + " }", + " else {", + " this.particles.push(new SpriteParticle());", + " }", + " }", + " const particle = this.particles[this.particleNum - 1];", + " particle.speedModifier = 1;", + " this.startColor.genColor(particle.startColor, this.emissionState.time, {});", + " particle.color.copy(particle.startColor);", + " particle.startSpeed = this.startSpeed.genValue(emissionState.time / this.duration);", + " particle.life = this.startLife.genValue(emissionState.time / this.duration);", + " particle.age = 0;", + " particle.startSize = this.startSize.genValue(emissionState.time / this.duration);", + " particle.uvTile = Math.floor(this.startTileIndex.genValue() + 0.001);", + " particle.size = particle.startSize;", + " if (this.rendererSettings.renderMode === RenderMode.Mesh ||", + " this.rendererSettings.renderMode === RenderMode.BillBoard ||", + " this.rendererSettings.renderMode === RenderMode.VerticalBillBoard ||", + " this.rendererSettings.renderMode === RenderMode.HorizontalBillBoard ||", + " this.rendererSettings.renderMode === RenderMode.StretchedBillBoard) {", + " const sprite = particle;", + " if (this.rendererSettings.renderMode === RenderMode.Mesh) {", + " if (!(sprite.rotation instanceof THREE.Quaternion)) {", + " sprite.rotation = new THREE.Quaternion();", + " }", + " if (this.startRotation.type === 'rotation') {", + " this.startRotation.genValue(sprite.rotation, emissionState.time / this.duration);", + " }", + " else {", + " sprite.rotation.setFromAxisAngle(UP, this.startRotation.genValue((emissionState.time / this.duration)));", + " }", + " }", + " else {", + " if (this.startRotation.type === 'rotation') {", + " sprite.rotation = 0;", + " }", + " else {", + " sprite.rotation = this.startRotation.genValue(emissionState.time / this.duration);", + " }", + " }", + " }", + " else if (this.rendererSettings.renderMode === RenderMode.Trail) {", + " const trail = particle;", + " trail.length = this.rendererEmitterSettings.startLength.genValue(emissionState.time / this.duration);", + " }", + " this.emitterShape.initialize(particle);", + " if (this.rendererSettings.renderMode === RenderMode.Trail &&", + " this.rendererEmitterSettings.followLocalOrigin) {", + " const trail = particle;", + " trail.localPosition = new THREE.Vector3().copy(trail.position);", + " }", + " if (this.worldSpace) {", + " particle.position.applyMatrix4(matrix);", + " particle.startSize =", + " (particle.startSize * (Math.abs(scale.x) + Math.abs(scale.y) + Math.abs(scale.z))) / 3;", + " particle.size = particle.startSize;", + " particle.velocity.multiply(scale).applyMatrix3(this.normalMatrix);", + " if (particle.rotation && particle.rotation instanceof THREE.Quaternion) {", + " particle.rotation.multiplyQuaternions(tempQ$1, particle.rotation);", + " }", + " }", + " else {", + " if (this.onlyUsedByOther) {", + " particle.parentMatrix = matrix;", + " }", + " }", + " for (let j = 0; j < this.behaviors.length; j++) {", + " this.behaviors[j].initialize(particle);", + " }", + " }", + " }", + " endEmit() {", + " this.emitEnded = true;", + " if (this.autoDestroy) {", + " this.markForDestroy = true;", + " }", + " }", + " dispose() {", + " if (this._renderer)", + " this._renderer.deleteSystem(this);", + " this.emitter.dispose();", + " if (this.emitter.parent)", + " this.emitter.parent.remove(this.emitter);", + " }", + " restart() {", + " this.paused = false;", + " this.particleNum = 0;", + " this.emissionState.burstIndex = 0;", + " this.emissionState.burstWaveIndex = 0;", + " this.emissionState.time = 0;", + " this.emissionState.waitEmiting = 0;", + " this.behaviors.forEach((behavior) => {", + " behavior.reset();", + " });", + " this.emitEnded = false;", + " this.markForDestroy = false;", + " this.prewarmed = false;", + " }", + " update(delta) {", + " if (this.paused)", + " return;", + " let currentParent = this.emitter;", + " while (currentParent.parent) {", + " currentParent = currentParent.parent;", + " }", + " if (currentParent.type !== 'Scene') {", + " this.dispose();", + " return;", + " }", + " if (this.firstTimeUpdate) {", + " this.firstTimeUpdate = false;", + " this.emitter.updateWorldMatrix(true, false);", + " }", + " if (this.emitEnded && this.particleNum === 0) {", + " if (this.markForDestroy && this.emitter.parent)", + " this.dispose();", + " return;", + " }", + " if (this.looping && this.prewarm && !this.prewarmed) {", + " this.prewarmed = true;", + " for (let i = 0; i < this.duration * PREWARM_FPS$1; i++) {", + " this.update(1.0 / PREWARM_FPS$1);", + " }", + " }", + " if (delta > 0.1) {", + " delta = 0.1;", + " }", + " if (this.neededToUpdateRender) {", + " if (this._renderer)", + " this._renderer.updateSystem(this);", + " this.neededToUpdateRender = false;", + " }", + " if (!this.onlyUsedByOther) {", + " this.emit(delta, this.emissionState, this.emitter.matrixWorld);", + " }", + " this.emitterShape.update(this, delta);", + " for (let j = 0; j < this.behaviors.length; j++) {", + " for (let i = 0; i < this.particleNum; i++) {", + " if (!this.particles[i].died) {", + " this.behaviors[j].update(this.particles[i], delta);", + " }", + " }", + " this.behaviors[j].frameUpdate(delta);", + " }", + " for (let i = 0; i < this.particleNum; i++) {", + " if (this.rendererEmitterSettings.followLocalOrigin &&", + " this.particles[i].localPosition) {", + " this.particles[i].position.copy(this.particles[i].localPosition);", + " if (this.particles[i].parentMatrix) {", + " this.particles[i].position.applyMatrix4(this.particles[i].parentMatrix);", + " }", + " else {", + " this.particles[i].position.applyMatrix4(this.emitter.matrixWorld);", + " }", + " }", + " else {", + " this.particles[i].position.addScaledVector(this.particles[i].velocity, delta * this.particles[i].speedModifier);", + " }", + " this.particles[i].age += delta;", + " }", + " if (this.rendererSettings.renderMode === RenderMode.Trail) {", + " for (let i = 0; i < this.particleNum; i++) {", + " const particle = this.particles[i];", + " particle.update();", + " }", + " }", + " for (let i = 0; i < this.particleNum; i++) {", + " const particle = this.particles[i];", + " if (particle.died && (!(particle instanceof TrailParticle) || particle.previous.length === 0)) {", + " this.particles[i] = this.particles[this.particleNum - 1];", + " this.particles[this.particleNum - 1] = particle;", + " this.particleNum--;", + " i--;", + " }", + " }", + " }", + " emit(delta, emissionState, emitterMatrix) {", + " if (emissionState.time > this.duration) {", + " if (this.looping) {", + " emissionState.time -= this.duration;", + " emissionState.burstIndex = 0;", + " this.behaviors.forEach((behavior) => {", + " behavior.reset();", + " });", + " }", + " else {", + " if (!this.emitEnded && !this.onlyUsedByOther) {", + " this.endEmit();", + " }", + " }", + " }", + " this.normalMatrix.getNormalMatrix(emitterMatrix);", + " const totalSpawn = Math.ceil(emissionState.waitEmiting);", + " this.spawn(totalSpawn, emissionState, emitterMatrix);", + " emissionState.waitEmiting -= totalSpawn;", + " while (emissionState.burstIndex < this.emissionBursts.length &&", + " this.emissionBursts[emissionState.burstIndex].time <= emissionState.time) {", + " if (Math.random() < this.emissionBursts[emissionState.burstIndex].probability) {", + " const count = this.emissionBursts[emissionState.burstIndex].count.genValue(this.time);", + " this.spawn(count, emissionState, emitterMatrix);", + " }", + " emissionState.burstIndex++;", + " }", + " if (!this.emitEnded) {", + " emissionState.waitEmiting += delta * this.emissionOverTime.genValue(emissionState.time / this.duration);", + " if (emissionState.previousWorldPos != undefined) {", + " this.temp.set(emitterMatrix.elements[12], emitterMatrix.elements[13], emitterMatrix.elements[14]);", + " emissionState.travelDistance += emissionState.previousWorldPos.distanceTo(this.temp);", + " const emitPerMeter = this.emissionOverDistance.genValue(emissionState.time / this.duration);", + " if (emissionState.travelDistance * emitPerMeter > 0) {", + " const count = Math.floor(emissionState.travelDistance * emitPerMeter);", + " emissionState.travelDistance -= count / emitPerMeter;", + " emissionState.waitEmiting += count;", + " }", + " }", + " }", + " if (emissionState.previousWorldPos === undefined)", + " emissionState.previousWorldPos = new THREE.Vector3();", + " emissionState.previousWorldPos.set(emitterMatrix.elements[12], emitterMatrix.elements[13], emitterMatrix.elements[14]);", + " emissionState.time += delta;", + " }", + " toJSON(meta, options = {}) {", + " const isRootObject = meta === undefined || typeof meta === 'string';", + " if (isRootObject) {", + " meta = {", + " geometries: {},", + " materials: {},", + " textures: {},", + " images: {},", + " shapes: {},", + " skeletons: {},", + " animations: {},", + " nodes: {},", + " };", + " }", + " meta.materials[this.rendererSettings.material.uuid] = this.rendererSettings.material.toJSON(meta);", + " if (options.useUrlForImage) {", + " if (this.texture.source !== undefined) {", + " const image = this.texture.source;", + " meta.images[image.uuid] = {", + " uuid: image.uuid,", + " url: this.texture.image.url,", + " };", + " }", + " }", + " let rendererSettingsJSON;", + " if (this.renderMode === RenderMode.Trail) {", + " rendererSettingsJSON = {", + " startLength: this.rendererEmitterSettings.startLength.toJSON(),", + " followLocalOrigin: this.rendererEmitterSettings.followLocalOrigin,", + " };", + " }", + " else if (this.renderMode === RenderMode.Mesh) {", + " rendererSettingsJSON = {};", + " }", + " else if (this.renderMode === RenderMode.StretchedBillBoard) {", + " rendererSettingsJSON = {", + " speedFactor: this.rendererEmitterSettings.speedFactor,", + " lengthFactor: this.rendererEmitterSettings.lengthFactor,", + " };", + " }", + " else {", + " rendererSettingsJSON = {};", + " }", + " const geometry = this.rendererSettings.instancingGeometry;", + " if (meta.geometries && !meta.geometries[geometry.uuid]) {", + " meta.geometries[geometry.uuid] = geometry.toJSON();", + " }", + " return {", + " version: '2.0',", + " autoDestroy: this.autoDestroy,", + " looping: this.looping,", + " prewarm: this.prewarm,", + " duration: this.duration,", + " shape: this.emitterShape.toJSON(),", + " startLife: this.startLife.toJSON(),", + " startSpeed: this.startSpeed.toJSON(),", + " startRotation: this.startRotation.toJSON(),", + " startSize: this.startSize.toJSON(),", + " startColor: this.startColor.toJSON(),", + " emissionOverTime: this.emissionOverTime.toJSON(),", + " emissionOverDistance: this.emissionOverDistance.toJSON(),", + " emissionBursts: this.emissionBursts.map((burst) => ({", + " time: burst.time,", + " count: burst.count.toJSON(),", + " probability: burst.probability,", + " interval: burst.interval,", + " cycle: burst.cycle,", + " })),", + " onlyUsedByOther: this.onlyUsedByOther,", + " instancingGeometry: this.rendererSettings.instancingGeometry.uuid,", + " renderOrder: this.renderOrder,", + " renderMode: this.renderMode,", + " rendererEmitterSettings: rendererSettingsJSON,", + " material: this.rendererSettings.material.uuid,", + " layers: this.layers.mask,", + " startTileIndex: this.startTileIndex.toJSON(),", + " uTileCount: this.uTileCount,", + " vTileCount: this.vTileCount,", + " behaviors: this.behaviors.map((behavior) => behavior.toJSON()),", + " worldSpace: this.worldSpace,", + " };", + " }", + " static fromJSON(json, meta, dependencies) {", + " var _a, _b;", + " const shape = EmitterFromJSON(json.shape, meta);", + " let rendererEmitterSettings;", + " if (json.renderMode === RenderMode.Trail) {", + " let trailSettings = json.rendererEmitterSettings;", + " rendererEmitterSettings = {", + " startLength: trailSettings.startLength != undefined", + " ? ValueGeneratorFromJSON(trailSettings.startLength)", + " : new ConstantValue(30),", + " followLocalOrigin: trailSettings.followLocalOrigin,", + " };", + " }", + " else if (json.renderMode === RenderMode.Mesh) {", + " rendererEmitterSettings = {};", + " }", + " else if (json.renderMode === RenderMode.StretchedBillBoard) {", + " rendererEmitterSettings = json.rendererEmitterSettings;", + " if (json.speedFactor != undefined) {", + " rendererEmitterSettings.speedFactor = json.speedFactor;", + " }", + " }", + " else {", + " rendererEmitterSettings = {};", + " }", + " const layers = new THREE.Layers();", + " if (json.layers) {", + " layers.mask = json.layers;", + " }", + " const ps = new ParticleSystem({", + " autoDestroy: json.autoDestroy,", + " looping: json.looping,", + " prewarm: json.prewarm,", + " duration: json.duration,", + " shape: shape,", + " startLife: ValueGeneratorFromJSON(json.startLife),", + " startSpeed: ValueGeneratorFromJSON(json.startSpeed),", + " startRotation: GeneratorFromJSON(json.startRotation),", + " startSize: ValueGeneratorFromJSON(json.startSize),", + " startColor: ColorGeneratorFromJSON(json.startColor),", + " emissionOverTime: ValueGeneratorFromJSON(json.emissionOverTime),", + " emissionOverDistance: ValueGeneratorFromJSON(json.emissionOverDistance),", + " emissionBursts: (_a = json.emissionBursts) === null || _a === void 0 ? void 0 : _a.map((burst) => ({", + " time: burst.time,", + " count: typeof burst.count === 'number'", + " ? new ConstantValue(burst.count)", + " : ValueGeneratorFromJSON(burst.count),", + " probability: burst.probability,", + " interval: burst.interval,", + " cycle: burst.cycle,", + " })),", + " onlyUsedByOther: json.onlyUsedByOther,", + " instancingGeometry: meta.geometries[json.instancingGeometry],", + " renderMode: json.renderMode,", + " rendererEmitterSettings: rendererEmitterSettings,", + " renderOrder: json.renderOrder,", + " layers: layers,", + " material: json.material", + " ? meta.materials[json.material]", + " : json.texture", + " ? new THREE.MeshBasicMaterial({", + " map: meta.textures[json.texture],", + " transparent: (_b = json.transparent) !== null && _b !== void 0 ? _b : true,", + " blending: json.blending,", + " side: THREE.DoubleSide,", + " })", + " : new THREE.MeshBasicMaterial({", + " color: 0xffffff,", + " transparent: true,", + " blending: THREE.AdditiveBlending,", + " side: THREE.DoubleSide,", + " }),", + " startTileIndex: typeof json.startTileIndex === 'number'", + " ? new ConstantValue(json.startTileIndex)", + " : ValueGeneratorFromJSON(json.startTileIndex),", + " uTileCount: json.uTileCount,", + " vTileCount: json.vTileCount,", + " behaviors: [],", + " worldSpace: json.worldSpace,", + " });", + " ps.behaviors = json.behaviors.map((behaviorJson) => {", + " const behavior = BehaviorFromJSON(behaviorJson, ps);", + " if (behavior.type === 'EmitSubParticleSystem') {", + " dependencies[behaviorJson.subParticleSystem] = behavior;", + " }", + " return behavior;", + " });", + " return ps;", + " }", + " addBehavior(behavior) {", + " this.behaviors.push(behavior);", + " }", + " getRendererSettings() {", + " return this.rendererSettings;", + " }", + " clone() {", + " const newEmissionBursts = [];", + " for (const emissionBurst of this.emissionBursts) {", + " const newEmissionBurst = {};", + " Object.assign(newEmissionBurst, emissionBurst);", + " newEmissionBursts.push(newEmissionBurst);", + " }", + " const newBehaviors = [];", + " for (const behavior of this.behaviors) {", + " newBehaviors.push(behavior.clone());", + " }", + " let rendererEmitterSettings;", + " if (this.renderMode === RenderMode.Trail) {", + " rendererEmitterSettings = {", + " startLength: this.rendererEmitterSettings.startLength.clone(),", + " followLocalOrigin: this.rendererEmitterSettings.followLocalOrigin,", + " };", + " }", + " else {", + " rendererEmitterSettings = {};", + " }", + " const layers = new THREE.Layers();", + " layers.mask = this.layers.mask;", + " return new ParticleSystem({", + " autoDestroy: this.autoDestroy,", + " looping: this.looping,", + " duration: this.duration,", + " shape: this.emitterShape.clone(),", + " startLife: this.startLife.clone(),", + " startSpeed: this.startSpeed.clone(),", + " startRotation: this.startRotation.clone(),", + " startSize: this.startSize.clone(),", + " startColor: this.startColor.clone(),", + " emissionOverTime: this.emissionOverTime.clone(),", + " emissionOverDistance: this.emissionOverDistance.clone(),", + " emissionBursts: newEmissionBursts,", + " onlyUsedByOther: this.onlyUsedByOther,", + " instancingGeometry: this.rendererSettings.instancingGeometry,", + " renderMode: this.renderMode,", + " renderOrder: this.renderOrder,", + " rendererEmitterSettings: rendererEmitterSettings,", + " material: this.rendererSettings.material,", + " startTileIndex: this.startTileIndex,", + " uTileCount: this.uTileCount,", + " vTileCount: this.vTileCount,", + " behaviors: newBehaviors,", + " worldSpace: this.worldSpace,", + " layers: layers,", + " });", + " }", + "}", + "", + "var particle_frag = `", + "", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "", + "void main() {", + "", + " #include ", + " ", + " vec3 outgoingLight = vec3( 0.0 );", + " vec4 diffuseColor = vColor;", + " ", + " #include ", + " ", + " #ifdef USE_MAP", + " diffuseColor *= texture2D( map, vMapUv);", + " #endif", + " ", + " #include ", + "", + " outgoingLight = diffuseColor.rgb;", + " ", + " #ifdef USE_COLOR_AS_ALPHA", + " gl_FragColor = vec4( outgoingLight, diffuseColor.r );", + " #else", + " gl_FragColor = vec4( outgoingLight, diffuseColor.a );", + " #endif", + " ", + " ", + " #include ", + "", + "}", + "`;", + "", + "var particle_physics_frag = `", + "#define STANDARD", + "#ifdef PHYSICAL", + "#define IOR", + "#define SPECULAR", + "#endif", + "uniform vec3 diffuse;", + "uniform vec3 emissive;", + "uniform float roughness;", + "uniform float metalness;", + "uniform float opacity;", + "#ifdef IOR", + "uniform float ior;", + "#endif", + "#ifdef SPECULAR", + "uniform float specularIntensity;", + "uniform vec3 specularColor;", + "#ifdef USE_SPECULARINTENSITYMAP", + "uniform sampler2D specularIntensityMap;", + "#endif", + "#ifdef USE_SPECULARCOLORMAP", + "uniform sampler2D specularColorMap;", + "#endif", + "#endif", + "#ifdef USE_CLEARCOAT", + "uniform float clearcoat;", + "uniform float clearcoatRoughness;", + "#endif", + "#ifdef USE_IRIDESCENCE", + "uniform float iridescence;", + "uniform float iridescenceIOR;", + "uniform float iridescenceThicknessMinimum;", + "uniform float iridescenceThicknessMaximum;", + "#endif", + "#ifdef USE_SHEEN", + "uniform vec3 sheenColor;", + "uniform float sheenRoughness;", + "#ifdef USE_SHEENCOLORMAP", + "uniform sampler2D sheenColorMap;", + "#endif", + "#ifdef USE_SHEENROUGHNESSMAP", + "uniform sampler2D sheenRoughnessMap;", + "#endif", + "#endif", + "", + "varying vec3 vViewPosition;", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "", + "void main() {", + " #include ", + " vec4 diffuseColor = vec4( diffuse, opacity );", + " ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );", + " vec3 totalEmissiveRadiance = emissive;", + " #include ", + " #include ", + " #include ", + " #include ", + " #include ", + " #include ", + " #include ", + " #include ", + " #include ", + " #include ", + " #include ", + " #include ", + " // accumulation", + " #include ", + " #include ", + " #include ", + " #include ", + " // modulation", + " #include ", + " vec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;", + " vec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;", + " #include ", + " vec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;", + " #ifdef USE_SHEEN", + " // Sheen energy compensation approximation calculation can be found at the end of", + " // https://drive.google.com/file/d/1T0D1VSyR4AllqIJTQAraEIzjlb5h4FKH/view?usp=sharing", + " float sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );", + " outgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;", + " #endif", + " #ifdef USE_CLEARCOAT", + " float dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );", + " vec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );", + " outgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;", + " #endif", + " #include ", + " #include ", + " #include ", + " #include ", + " #include ", + " #include ", + "}`;", + "", + "var uv_vertex_tile = `", + "", + " #ifdef UV_TILE", + " float col = mod(uvTile, tileCount.x);", + " float row = (tileCount.y - floor(uvTile / tileCount.x) - 1.0);", + " ", + " mat3 tileTransform = mat3(", + " 1.0 / tileCount.x, 0.0, 0.0,", + " 0.0, 1.0 / tileCount.y, 0.0, ", + " col / tileCount.x, row / tileCount.y, 1.0);", + " #else", + " mat3 tileTransform = mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0);", + " #endif", + "", + "#if defined( USE_UV ) || defined( USE_ANISOTROPY )", + "", + "vUv = (tileTransform *vec3( uv, 1 )).xy;", + "", + "#endif", + "#ifdef USE_MAP", + "", + "vMapUv = ( tileTransform * (mapTransform * vec3( MAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_ALPHAMAP", + "", + "vAlphaMapUv = ( tileTransform * (alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_LIGHTMAP", + "", + "vLightMapUv = ( tileTransform * (lightMapTransform * vec3( LIGHTMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_AOMAP", + "", + "vAoMapUv = ( tileTransform * (aoMapTransform * vec3( AOMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_BUMPMAP", + "", + "vBumpMapUv = ( tileTransform * (bumpMapTransform * vec3( BUMPMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_NORMALMAP", + "", + "vNormalMapUv = ( tileTransform * (normalMapTransform * vec3( NORMALMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_DISPLACEMENTMAP", + "", + "vDisplacementMapUv = ( tileTransform * (displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_EMISSIVEMAP", + "", + "vEmissiveMapUv = ( tileTransform * (emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_METALNESSMAP", + "", + "vMetalnessMapUv = ( tileTransform * (metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_ROUGHNESSMAP", + "", + "vRoughnessMapUv = ( tileTransform * (roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_ANISOTROPYMAP", + "", + "vAnisotropyMapUv = ( tileTransform * (anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_CLEARCOATMAP", + "", + "vClearcoatMapUv = ( tileTransform * (clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_CLEARCOAT_NORMALMAP", + "", + "vClearcoatNormalMapUv = ( tileTransform * (clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_CLEARCOAT_ROUGHNESSMAP", + "", + "vClearcoatRoughnessMapUv = ( tileTransform * (clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_IRIDESCENCEMAP", + "", + "vIridescenceMapUv = ( tileTransform * (iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_IRIDESCENCE_THICKNESSMAP", + "", + "vIridescenceThicknessMapUv = ( tileTransform * (iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_SHEEN_COLORMAP", + "", + "vSheenColorMapUv = ( tileTransform * (sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_SHEEN_ROUGHNESSMAP", + "", + "vSheenRoughnessMapUv = ( tileTransform * (sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_SPECULARMAP", + "", + "vSpecularMapUv = ( tileTransform * (specularMapTransform * vec3( SPECULARMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_SPECULAR_COLORMAP", + "", + "vSpecularColorMapUv = ( tileTransform * (specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_SPECULAR_INTENSITYMAP", + "", + "vSpecularIntensityMapUv = ( tileTransform * (specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_TRANSMISSIONMAP", + "", + "vTransmissionMapUv = ( tileTransform * transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_THICKNESSMAP", + "", + "vThicknessMapUv = ( tileTransform * thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) )).xy;", + "", + "#endif", + "`;", + "", + "var particle_vert = `", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "", + "attribute vec3 offset;", + "attribute float rotation;", + "attribute float size;", + "attribute float uvTile;", + "", + "#ifdef UV_TILE", + "uniform vec2 tileCount;", + "#endif", + "", + "void main() {", + "", + " ${uv_vertex_tile}", + "\t", + " vec2 alignedPosition = ( position.xy ) * size;", + " ", + " vec2 rotatedPosition;", + " rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;", + " rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;", + "#ifdef HORIZONTAL", + " vec4 mvPosition = modelMatrix * vec4( offset, 1.0 );", + " mvPosition.x += rotatedPosition.x;", + " mvPosition.z -= rotatedPosition.y;", + " mvPosition = viewMatrix * mvPosition;", + "#elif defined(VERTICAL)", + " vec4 mvPosition = modelMatrix * vec4( offset, 1.0 );", + " mvPosition.y += rotatedPosition.y;", + " mvPosition = viewMatrix * mvPosition;", + " mvPosition.x += rotatedPosition.x;", + "#else", + " vec4 mvPosition = modelViewMatrix * vec4( offset, 1.0 );", + " mvPosition.xy += rotatedPosition;", + "#endif", + "", + "\tvColor = color;", + "", + "\tgl_Position = projectionMatrix * mvPosition;", + "", + "\t#include ", + "\t#include ", + "", + "}", + "`;", + "", + "var local_particle_vert = `", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "", + "attribute vec3 offset;", + "attribute vec4 rotation;", + "attribute float size;", + "// attribute vec4 color;", + "attribute float uvTile;", + "", + "#ifdef UV_TILE", + "uniform vec2 tileCount;", + "#endif", + "", + "void main() {", + "", + " ${uv_vertex_tile}", + " ", + " float x2 = rotation.x + rotation.x, y2 = rotation.y + rotation.y, z2 = rotation.z + rotation.z;", + " float xx = rotation.x * x2, xy = rotation.x * y2, xz = rotation.x * z2;", + " float yy = rotation.y * y2, yz = rotation.y * z2, zz = rotation.z * z2;", + " float wx = rotation.w * x2, wy = rotation.w * y2, wz = rotation.w * z2;", + " float sx = size, sy = size, sz = size;", + " ", + " mat4 matrix = mat4(( 1.0 - ( yy + zz ) ) * sx, ( xy + wz ) * sx, ( xz - wy ) * sx, 0.0, // 1. column", + " ( xy - wz ) * sy, ( 1.0 - ( xx + zz ) ) * sy, ( yz + wx ) * sy, 0.0, // 2. column", + " ( xz + wy ) * sz, ( yz - wx ) * sz, ( 1.0 - ( xx + yy ) ) * sz, 0.0, // 3. column", + " offset.x, offset.y, offset.z, 1.0);", + " ", + " vec4 mvPosition = modelViewMatrix * (matrix * vec4( position, 1.0 ));", + "", + "\tvColor = color;", + "", + "\tgl_Position = projectionMatrix * mvPosition;", + "", + "\t#include ", + "\t#include ", + "", + "}", + "`;", + "", + "var local_particle_physics_vert = `", + "#define STANDARD", + "varying vec3 vViewPosition;", + "#ifdef USE_TRANSMISSION", + "\tvarying vec3 vWorldPosition;", + "#endif", + "#include ", + "#include ", + "", + "attribute vec3 offset;", + "attribute vec4 rotation;", + "attribute float size;", + "attribute float uvTile;", + "", + "#ifdef UV_TILE", + "uniform vec2 tileCount;", + "#endif", + "", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "", + "void main() {", + " ${uv_vertex_tile}", + "", + " float x2 = rotation.x + rotation.x, y2 = rotation.y + rotation.y, z2 = rotation.z + rotation.z;", + " float xx = rotation.x * x2, xy = rotation.x * y2, xz = rotation.x * z2;", + " float yy = rotation.y * y2, yz = rotation.y * z2, zz = rotation.z * z2;", + " float wx = rotation.w * x2, wy = rotation.w * y2, wz = rotation.w * z2;", + " float sx = size, sy = size, sz = size;", + "", + " mat4 particleMatrix = mat4(( 1.0 - ( yy + zz ) ) * sx, ( xy + wz ) * sx, ( xz - wy ) * sx, 0.0, // 1. column", + " ( xy - wz ) * sy, ( 1.0 - ( xx + zz ) ) * sy, ( yz + wx ) * sy, 0.0, // 2. column", + " ( xz + wy ) * sz, ( yz - wx ) * sz, ( 1.0 - ( xx + yy ) ) * sz, 0.0, // 3. column", + " offset.x, offset.y, offset.z, 1.0);", + "", + "\t#include ", + "\t#include ", + "\t#include ", + "\t#include ", + "\t#include ", + "\t#include ", + "", + "\t// replace defaultnormal_vertex", + "\tvec3 transformedNormal = objectNormal;", + " mat3 m = mat3( particleMatrix );", + " transformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );", + " transformedNormal = m * transformedNormal;", + " transformedNormal = normalMatrix * transformedNormal;", + " #ifdef FLIP_SIDED", + " transformedNormal = - transformedNormal;", + " #endif", + " #ifdef USE_TANGENT", + " vec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;", + " #ifdef FLIP_SIDED", + " transformedTangent = - transformedTangent;", + " #endif", + " #endif", + "", + "\t#include ", + "\t#include ", + "\t#include ", + "\t#include ", + "\t#include ", + "", + "\t// replace include ", + " vec4 mvPosition = vec4( transformed, 1.0 );", + " mvPosition = modelViewMatrix * (particleMatrix * mvPosition);", + "\tgl_Position = projectionMatrix * mvPosition;", + "", + "\t#include ", + "\t#include ", + "\t", + "\tvViewPosition = - mvPosition.xyz;", + "\t", + "\t#include ", + "\t#include ", + "\t#include ", + "#ifdef USE_TRANSMISSION", + "\tvWorldPosition = worldPosition.xyz;", + "#endif", + "}", + "`;", + "", + "var stretched_bb_particle_vert = `", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "", + "attribute vec3 offset;", + "attribute float rotation;", + "attribute float size;", + "attribute vec4 velocity;", + "attribute float uvTile;", + "", + "#ifdef UV_TILE", + "uniform vec2 tileCount;", + "#endif", + "", + "uniform float speedFactor;", + "", + "void main() {", + "", + " ${uv_vertex_tile}", + " ", + " float lengthFactor = velocity.w;", + "#ifdef USE_SKEW", + " vec4 mvPosition = modelViewMatrix * vec4( offset, 1.0 );", + " vec3 viewVelocity = normalMatrix * velocity.xyz;", + "", + " vec3 scaledPos = vec3(position.xy * size, position.z);", + " float vlength = length(viewVelocity);", + " vec3 projVelocity = dot(scaledPos, viewVelocity) * viewVelocity / vlength;", + " mvPosition.xyz += scaledPos + projVelocity * (speedFactor / size + lengthFactor / vlength);", + "#else", + " vec4 mvPosition = modelViewMatrix * vec4( offset, 1.0 );", + " vec3 viewVelocity = normalMatrix * velocity.xyz;", + " float vlength = length(viewVelocity); ", + " mvPosition.xyz += position.y * normalize(cross(mvPosition.xyz, viewVelocity)) * size; // switch the cross to match unity implementation", + " mvPosition.xyz -= (position.x + 0.5) * viewVelocity * (1.0 + lengthFactor / vlength) * size; // minus position.x to match unity implementation", + "#endif", + "\tvColor = color;", + "\tgl_Position = projectionMatrix * mvPosition;", + "\t#include ", + "\t#include ", + "}", + "`;", + "", + "function getMaterialUVChannelName(value) {", + " if (value === 0)", + " return 'uv';", + " return `uv${value}`;", + "}", + "", + "new THREE.Vector3(0, 0, 1);", + "class SpriteBatch extends VFXBatch {", + " constructor(settings) {", + " super(settings);", + " this.vector_ = new THREE.Vector3();", + " this.vector2_ = new THREE.Vector3();", + " this.vector3_ = new THREE.Vector3();", + " this.quaternion_ = new THREE.Quaternion();", + " this.quaternion2_ = new THREE.Quaternion();", + " this.quaternion3_ = new THREE.Quaternion();", + " this.rotationMat_ = new THREE.Matrix3();", + " this.rotationMat2_ = new THREE.Matrix3();", + " this.maxParticles = 1000;", + " this.setupBuffers();", + " this.rebuildMaterial();", + " }", + " buildExpandableBuffers() {", + " this.offsetBuffer = new THREE.InstancedBufferAttribute(new Float32Array(this.maxParticles * 3), 3);", + " this.offsetBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('offset', this.offsetBuffer);", + " this.colorBuffer = new THREE.InstancedBufferAttribute(new Float32Array(this.maxParticles * 4), 4);", + " this.colorBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('color', this.colorBuffer);", + " if (this.settings.renderMode === RenderMode.Mesh) {", + " this.rotationBuffer = new THREE.InstancedBufferAttribute(new Float32Array(this.maxParticles * 4), 4);", + " this.rotationBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('rotation', this.rotationBuffer);", + " }", + " else if (this.settings.renderMode === RenderMode.BillBoard ||", + " this.settings.renderMode === RenderMode.HorizontalBillBoard ||", + " this.settings.renderMode === RenderMode.VerticalBillBoard ||", + " this.settings.renderMode === RenderMode.StretchedBillBoard) {", + " this.rotationBuffer = new THREE.InstancedBufferAttribute(new Float32Array(this.maxParticles), 1);", + " this.rotationBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('rotation', this.rotationBuffer);", + " }", + " this.sizeBuffer = new THREE.InstancedBufferAttribute(new Float32Array(this.maxParticles), 1);", + " this.sizeBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('size', this.sizeBuffer);", + " this.uvTileBuffer = new THREE.InstancedBufferAttribute(new Float32Array(this.maxParticles), 1);", + " this.uvTileBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('uvTile', this.uvTileBuffer);", + " if (this.settings.renderMode === RenderMode.StretchedBillBoard) {", + " this.velocityBuffer = new THREE.InstancedBufferAttribute(new Float32Array(this.maxParticles * 4), 4);", + " this.velocityBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('velocity', this.velocityBuffer);", + " }", + " }", + " setupBuffers() {", + " if (this.geometry)", + " this.geometry.dispose();", + " this.geometry = new THREE.InstancedBufferGeometry();", + " this.geometry.setIndex(this.settings.instancingGeometry.getIndex());", + " if (this.settings.instancingGeometry.hasAttribute('normal')) {", + " this.geometry.setAttribute('normal', this.settings.instancingGeometry.getAttribute('normal'));", + " }", + " this.geometry.setAttribute('position', this.settings.instancingGeometry.getAttribute('position'));", + " this.geometry.setAttribute('uv', this.settings.instancingGeometry.getAttribute('uv'));", + " this.buildExpandableBuffers();", + " }", + " expandBuffers(target) {", + " while (target >= this.maxParticles) {", + " this.maxParticles *= 2;", + " }", + " this.setupBuffers();", + " }", + " rebuildMaterial() {", + " this.layers.mask = this.settings.layers.mask;", + " let uniforms;", + " const defines = {};", + " if (this.settings.material.type === 'MeshStandardMaterial' ||", + " this.settings.material.type === 'MeshPhysicalMaterial') {", + " const mat = this.settings.material;", + " uniforms = THREE.UniformsUtils.merge([", + " THREE.UniformsLib.common,", + " THREE.UniformsLib.envmap,", + " THREE.UniformsLib.aomap,", + " THREE.UniformsLib.lightmap,", + " THREE.UniformsLib.emissivemap,", + " THREE.UniformsLib.bumpmap,", + " THREE.UniformsLib.normalmap,", + " THREE.UniformsLib.displacementmap,", + " THREE.UniformsLib.roughnessmap,", + " THREE.UniformsLib.metalnessmap,", + " THREE.UniformsLib.fog,", + " THREE.UniformsLib.lights,", + " {", + " emissive: { value: new THREE.Color(0x000000) },", + " roughness: { value: 1.0 },", + " metalness: { value: 0.0 },", + " envMapIntensity: { value: 1 },", + " },", + " ]);", + " uniforms['diffuse'].value = mat.color;", + " uniforms['opacity'].value = mat.opacity;", + " uniforms['emissive'].value = mat.emissive;", + " uniforms['roughness'].value = mat.roughness;", + " uniforms['metalness'].value = mat.metalness;", + " if (mat.envMap) {", + " uniforms['envMap'].value = mat.envMap;", + " uniforms['envMapIntensity'].value = mat.envMapIntensity;", + " }", + " if (mat.normalMap) {", + " uniforms['normalMap'].value = mat.normalMap;", + " uniforms['normalScale'].value = mat.normalScale;", + " }", + " if (mat.roughnessMap) {", + " uniforms['roughnessMap'].value = mat.roughnessMap;", + " }", + " if (mat.metalnessMap) {", + " uniforms['metalnessMap'].value = mat.metalnessMap;", + " }", + " if (mat.map) {", + " uniforms['map'] = new THREE.Uniform(mat.map);", + " }", + " }", + " else {", + " uniforms = {};", + " uniforms['map'] = new THREE.Uniform(this.settings.material.map);", + " }", + " if (this.settings.material.alphaTest) {", + " defines['USE_ALPHATEST'] = '';", + " uniforms['alphaTest'] = new THREE.Uniform(this.settings.material.alphaTest);", + " }", + " defines['USE_UV'] = '';", + " const uTileCount = this.settings.uTileCount;", + " const vTileCount = this.settings.vTileCount;", + " if (uTileCount > 1 || vTileCount > 1) {", + " defines['UV_TILE'] = '';", + " uniforms['tileCount'] = new THREE.Uniform(new THREE.Vector2(uTileCount, vTileCount));", + " }", + " if (this.settings.material.defines &&", + " this.settings.material.defines['USE_COLOR_AS_ALPHA'] !== undefined) {", + " defines['USE_COLOR_AS_ALPHA'] = '';", + " }", + " if (this.settings.material.normalMap) {", + " defines['USE_NORMALMAP'] = '';", + " defines['NORMALMAP_UV'] = getMaterialUVChannelName(this.settings.material.normalMap.channel);", + " uniforms['normalMapTransform'] = new THREE.Uniform(new THREE.Matrix3().copy(this.settings.material.normalMap.matrix));", + " }", + " if (this.settings.material.map) {", + " defines['USE_MAP'] = '';", + " defines['MAP_UV'] = getMaterialUVChannelName(this.settings.material.map.channel);", + " uniforms['mapTransform'] = new THREE.Uniform(new THREE.Matrix3().copy(this.settings.material.map.matrix));", + " }", + " defines['USE_COLOR_ALPHA'] = '';", + " let needLights = false;", + " if (this.settings.renderMode === RenderMode.BillBoard ||", + " this.settings.renderMode === RenderMode.VerticalBillBoard ||", + " this.settings.renderMode === RenderMode.HorizontalBillBoard ||", + " this.settings.renderMode === RenderMode.Mesh) {", + " let vertexShader;", + " let fragmentShader;", + " if (this.settings.renderMode === RenderMode.Mesh) {", + " if (this.settings.material.type === 'MeshStandardMaterial' ||", + " this.settings.material.type === 'MeshPhysicalMaterial') {", + " defines['USE_COLOR'] = '';", + " vertexShader = local_particle_physics_vert;", + " fragmentShader = particle_physics_frag;", + " needLights = true;", + " }", + " else {", + " vertexShader = local_particle_vert;", + " fragmentShader = particle_frag;", + " }", + " }", + " else {", + " vertexShader = particle_vert;", + " fragmentShader = particle_frag;", + " }", + " if (this.settings.renderMode === RenderMode.VerticalBillBoard) {", + " defines['VERTICAL'] = '';", + " }", + " else if (this.settings.renderMode === RenderMode.HorizontalBillBoard) {", + " defines['HORIZONTAL'] = '';", + " }", + " this.material = new THREE.ShaderMaterial({", + " uniforms: uniforms,", + " defines: defines,", + " vertexShader: vertexShader,", + " fragmentShader: fragmentShader,", + " transparent: this.settings.material.transparent,", + " depthWrite: !this.settings.material.transparent,", + " blending: this.settings.material.blending,", + " side: this.settings.material.side,", + " alphaTest: this.settings.material.alphaTest,", + " lights: needLights,", + " });", + " }", + " else if (this.settings.renderMode === RenderMode.StretchedBillBoard) {", + " uniforms['speedFactor'] = new THREE.Uniform(1.0);", + " this.material = new THREE.ShaderMaterial({", + " uniforms: uniforms,", + " defines: defines,", + " vertexShader: stretched_bb_particle_vert,", + " fragmentShader: particle_frag,", + " transparent: this.settings.material.transparent,", + " depthWrite: !this.settings.material.transparent,", + " blending: this.settings.material.blending,", + " side: this.settings.material.side,", + " alphaTest: this.settings.material.alphaTest,", + " });", + " }", + " else {", + " throw new Error('render mode unavailable');", + " }", + " }", + " update() {", + " let index = 0;", + " let particleCount = 0;", + " this.systems.forEach((system) => {", + " particleCount += system.particleNum;", + " });", + " if (particleCount > this.maxParticles) {", + " this.expandBuffers(particleCount);", + " }", + " this.systems.forEach((system) => {", + " const particles = system.particles;", + " const particleNum = system.particleNum;", + " const rotation = this.quaternion2_;", + " const translation = this.vector2_;", + " const scale = this.vector3_;", + " system.emitter.matrixWorld.decompose(translation, rotation, scale);", + " this.rotationMat_.setFromMatrix4(system.emitter.matrixWorld);", + " for (let j = 0; j < particleNum; j++ , index++) {", + " const particle = particles[j];", + " if (this.settings.renderMode === RenderMode.Mesh) {", + " let q;", + " if (system.worldSpace) {", + " q = particle.rotation;", + " }", + " else {", + " let parentQ;", + " if (particle.parentMatrix) {", + " parentQ = this.quaternion3_.setFromRotationMatrix(particle.parentMatrix);", + " }", + " else {", + " parentQ = rotation;", + " }", + " q = this.quaternion_;", + " q.copy(particle.rotation).multiply(parentQ);", + " }", + " this.rotationBuffer.setXYZW(index, q.x, q.y, q.z, q.w);", + " }", + " else if (this.settings.renderMode === RenderMode.StretchedBillBoard ||", + " this.settings.renderMode === RenderMode.VerticalBillBoard ||", + " this.settings.renderMode === RenderMode.HorizontalBillBoard ||", + " this.settings.renderMode === RenderMode.BillBoard) {", + " this.rotationBuffer.setX(index, particle.rotation);", + " }", + " let vec;", + " if (system.worldSpace) {", + " vec = particle.position;", + " }", + " else {", + " vec = this.vector_;", + " if (particle.parentMatrix) {", + " vec.copy(particle.position).applyMatrix4(particle.parentMatrix);", + " }", + " else {", + " vec.copy(particle.position).applyMatrix4(system.emitter.matrixWorld);", + " }", + " }", + " this.offsetBuffer.setXYZ(index, vec.x, vec.y, vec.z);", + " this.colorBuffer.setXYZW(index, particle.color.x, particle.color.y, particle.color.z, particle.color.w);", + " if (system.worldSpace) {", + " this.sizeBuffer.setX(index, particle.size);", + " }", + " else {", + " if (particle.parentMatrix) {", + " this.sizeBuffer.setX(index, particle.size);", + " }", + " else {", + " this.sizeBuffer.setX(index, (particle.size * (Math.abs(scale.x) + Math.abs(scale.y) + Math.abs(scale.z))) / 3);", + " }", + " }", + " this.uvTileBuffer.setX(index, particle.uvTile);", + " if (this.settings.renderMode === RenderMode.StretchedBillBoard && this.velocityBuffer) {", + " let speedFactor = system.rendererEmitterSettings.speedFactor;", + " if (speedFactor === 0)", + " speedFactor = 0.001;", + " const lengthFactor = system.rendererEmitterSettings.lengthFactor;", + " let vec;", + " if (system.worldSpace) {", + " vec = particle.velocity;", + " }", + " else {", + " vec = this.vector_;", + " if (particle.parentMatrix) {", + " this.rotationMat2_.setFromMatrix4(particle.parentMatrix);", + " vec.copy(particle.velocity).applyMatrix3(this.rotationMat2_);", + " }", + " else {", + " vec.copy(particle.velocity).applyMatrix3(this.rotationMat_);", + " }", + " }", + " this.velocityBuffer.setXYZW(index, vec.x * speedFactor, vec.y * speedFactor, vec.z * speedFactor, lengthFactor);", + " }", + " }", + " });", + " this.geometry.instanceCount = index;", + " if (index > 0) {", + " this.offsetBuffer.clearUpdateRanges();", + " this.offsetBuffer.addUpdateRange(0, index * 3);", + " this.offsetBuffer.needsUpdate = true;", + " this.sizeBuffer.clearUpdateRanges();", + " this.sizeBuffer.addUpdateRange(0, index);", + " this.sizeBuffer.needsUpdate = true;", + " this.colorBuffer.clearUpdateRanges();", + " this.colorBuffer.addUpdateRange(0, index * 4);", + " this.colorBuffer.needsUpdate = true;", + " this.uvTileBuffer.clearUpdateRanges();", + " this.uvTileBuffer.addUpdateRange(0, index);", + " this.uvTileBuffer.needsUpdate = true;", + " if (this.settings.renderMode === RenderMode.StretchedBillBoard && this.velocityBuffer) {", + " this.velocityBuffer.clearUpdateRanges();", + " this.velocityBuffer.addUpdateRange(0, index * 4);", + " this.velocityBuffer.needsUpdate = true;", + " }", + " if (this.settings.renderMode === RenderMode.Mesh) {", + " this.rotationBuffer.clearUpdateRanges();", + " this.rotationBuffer.addUpdateRange(0, index * 4);", + " this.rotationBuffer.needsUpdate = true;", + " }", + " else if (this.settings.renderMode === RenderMode.StretchedBillBoard ||", + " this.settings.renderMode === RenderMode.HorizontalBillBoard ||", + " this.settings.renderMode === RenderMode.VerticalBillBoard ||", + " this.settings.renderMode === RenderMode.BillBoard) {", + " this.rotationBuffer.clearUpdateRanges();", + " this.rotationBuffer.addUpdateRange(0, index);", + " this.rotationBuffer.needsUpdate = true;", + " }", + " }", + " }", + " dispose() {", + " this.geometry.dispose();", + " }", + "}", + "", + "var trail_frag = `", + "", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "", + "uniform sampler2D alphaMap;", + "uniform float useAlphaMap;", + "uniform float visibility;", + "uniform float alphaTest;", + "uniform vec2 repeat;", + "", + "varying vec4 vColor;", + " ", + "void main() {", + " #include ", + " #include ", + "", + " vec4 c = vColor;", + " ", + " #ifdef USE_MAP", + " #ifdef USE_COLOR_AS_ALPHA", + " vec4 tex = texture2D( map, vUv * repeat );", + " c *= vec4(tex.rgb, tex.r);", + " #else", + " c *= texture2D( map, vUv * repeat );", + " #endif", + " #endif", + " if( useAlphaMap == 1. ) c.a *= texture2D( alphaMap, vUv * repeat ).a;", + " if( c.a < alphaTest ) discard;", + " gl_FragColor = c;", + "", + " #include ", + " #include ", + "}`;", + "", + "var trail_vert = `", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "", + "attribute vec3 previous;", + "attribute vec3 next;", + "attribute float side;", + "attribute float width;", + "", + "uniform vec2 resolution;", + "uniform float lineWidth;", + "uniform float sizeAttenuation;", + " ", + "vec2 fix(vec4 i, float aspect) {", + " vec2 res = i.xy / i.w;", + " res.x *= aspect;", + " return res;", + "}", + " ", + "void main() {", + "", + " ${uv_vertex_tile}", + " ", + " float aspect = resolution.x / resolution.y;", + "", + " vColor = color;", + "", + " mat4 m = projectionMatrix * modelViewMatrix;", + " vec4 finalPosition = m * vec4( position, 1.0 );", + " vec4 prevPos = m * vec4( previous, 1.0 );", + " vec4 nextPos = m * vec4( next, 1.0 );", + "", + " vec2 currentP = fix( finalPosition, aspect );", + " vec2 prevP = fix( prevPos, aspect );", + " vec2 nextP = fix( nextPos, aspect );", + "", + " float w = lineWidth * width;", + "", + " vec2 dir;", + " if( nextP == currentP ) dir = normalize( currentP - prevP );", + " else if( prevP == currentP ) dir = normalize( nextP - currentP );", + " else {", + " vec2 dir1 = normalize( currentP - prevP );", + " vec2 dir2 = normalize( nextP - currentP );", + " dir = normalize( dir1 + dir2 );", + "", + " vec2 perp = vec2( -dir1.y, dir1.x );", + " vec2 miter = vec2( -dir.y, dir.x );", + " //w = clamp( w / dot( miter, perp ), 0., 4., * lineWidth * width );", + "", + " }", + "", + " //vec2 normal = ( cross( vec3( dir, 0. ) vec3( 0., 0., 1. ) ) ).xy;", + " vec4 normal = vec4( -dir.y, dir.x, 0., 1. );", + " normal.xy *= .5 * w;", + " normal *= projectionMatrix;", + " if( sizeAttenuation == 0. ) {", + " normal.xy *= finalPosition.w;", + " normal.xy /= ( vec4( resolution, 0., 1. ) * projectionMatrix ).xy;", + " }", + "", + " finalPosition.xy += normal.xy * side;", + "", + " gl_Position = finalPosition;", + "", + "\t#include ", + "\t#include ", + "\t", + " vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );", + " ", + "\t#include ", + "}`;", + "", + "new THREE.Vector3(0, 0, 1);", + "class TrailBatch extends VFXBatch {", + " constructor(settings) {", + " super(settings);", + " this.vector_ = new THREE.Vector3();", + " this.vector2_ = new THREE.Vector3();", + " this.vector3_ = new THREE.Vector3();", + " this.quaternion_ = new THREE.Quaternion();", + " this.maxParticles = 10000;", + " this.setupBuffers();", + " this.rebuildMaterial();", + " }", + " setupBuffers() {", + " if (this.geometry)", + " this.geometry.dispose();", + " this.geometry = new THREE.BufferGeometry();", + " this.indexBuffer = new THREE.BufferAttribute(new Uint32Array(this.maxParticles * 6), 1);", + " this.indexBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setIndex(this.indexBuffer);", + " this.positionBuffer = new THREE.BufferAttribute(new Float32Array(this.maxParticles * 6), 3);", + " this.positionBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('position', this.positionBuffer);", + " this.previousBuffer = new THREE.BufferAttribute(new Float32Array(this.maxParticles * 6), 3);", + " this.previousBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('previous', this.previousBuffer);", + " this.nextBuffer = new THREE.BufferAttribute(new Float32Array(this.maxParticles * 6), 3);", + " this.nextBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('next', this.nextBuffer);", + " this.widthBuffer = new THREE.BufferAttribute(new Float32Array(this.maxParticles * 2), 1);", + " this.widthBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('width', this.widthBuffer);", + " this.sideBuffer = new THREE.BufferAttribute(new Float32Array(this.maxParticles * 2), 1);", + " this.sideBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('side', this.sideBuffer);", + " this.uvBuffer = new THREE.BufferAttribute(new Float32Array(this.maxParticles * 4), 2);", + " this.uvBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('uv', this.uvBuffer);", + " this.colorBuffer = new THREE.BufferAttribute(new Float32Array(this.maxParticles * 8), 4);", + " this.colorBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('color', this.colorBuffer);", + " }", + " expandBuffers(target) {", + " while (target >= this.maxParticles) {", + " this.maxParticles *= 2;", + " }", + " this.setupBuffers();", + " }", + " rebuildMaterial() {", + " this.layers.mask = this.settings.layers.mask;", + " const uniforms = {", + " lineWidth: { value: 1 },", + " map: { value: null },", + " useMap: { value: 0 },", + " alphaMap: { value: null },", + " useAlphaMap: { value: 0 },", + " resolution: { value: new THREE.Vector2(1, 1) },", + " sizeAttenuation: { value: 1 },", + " visibility: { value: 1 },", + " alphaTest: { value: 0 },", + " repeat: { value: new THREE.Vector2(1, 1) },", + " };", + " const defines = {};", + " defines['USE_UV'] = '';", + " defines['USE_COLOR_ALPHA'] = '';", + " if (this.settings.material.map) {", + " defines['USE_MAP'] = '';", + " defines['MAP_UV'] = getMaterialUVChannelName(this.settings.material.map.channel);", + " uniforms['map'] = new THREE.Uniform(this.settings.material.map);", + " uniforms['mapTransform'] = new THREE.Uniform(new THREE.Matrix3().copy(this.settings.material.map.matrix));", + " }", + " if (this.settings.material.defines &&", + " this.settings.material.defines['USE_COLOR_AS_ALPHA'] !== undefined) {", + " defines['USE_COLOR_AS_ALPHA'] = '';", + " }", + " if (this.settings.renderMode === RenderMode.Trail) {", + " this.material = new THREE.ShaderMaterial({", + " uniforms: uniforms,", + " defines: defines,", + " vertexShader: trail_vert,", + " fragmentShader: trail_frag,", + " transparent: this.settings.material.transparent,", + " depthWrite: !this.settings.material.transparent,", + " side: this.settings.material.side,", + " blending: this.settings.material.blending || THREE.AdditiveBlending,", + " });", + " }", + " else {", + " throw new Error('render mode unavailable');", + " }", + " }", + " update() {", + " let index = 0;", + " let triangles = 0;", + " let particleCount = 0;", + " this.systems.forEach((system) => {", + " for (let j = 0; j < system.particleNum; j++) {", + " particleCount += system.particles[j].previous.length * 2;", + " }", + " });", + " if (particleCount > this.maxParticles) {", + " this.expandBuffers(particleCount);", + " }", + " this.systems.forEach((system) => {", + " const rotation = this.quaternion_;", + " const translation = this.vector2_;", + " const scale = this.vector3_;", + " system.emitter.matrixWorld.decompose(translation, rotation, scale);", + " const particles = system.particles;", + " const particleNum = system.particleNum;", + " const uTileCount = this.settings.uTileCount;", + " const vTileCount = this.settings.vTileCount;", + " const tileWidth = 1 / uTileCount;", + " const tileHeight = 1 / vTileCount;", + " for (let j = 0; j < particleNum; j++) {", + " const particle = particles[j];", + " const col = particle.uvTile % vTileCount;", + " const row = Math.floor(particle.uvTile / vTileCount + 0.001);", + " const iter = particle.previous.values();", + " let curIter = iter.next();", + " let previous = curIter.value;", + " let current = previous;", + " if (!curIter.done)", + " curIter = iter.next();", + " let next;", + " if (curIter.value !== undefined) {", + " next = curIter.value;", + " }", + " else {", + " next = current;", + " }", + " for (let i = 0; i < particle.previous.length; i++ , index += 2) {", + " this.positionBuffer.setXYZ(index, current.position.x, current.position.y, current.position.z);", + " this.positionBuffer.setXYZ(index + 1, current.position.x, current.position.y, current.position.z);", + " if (system.worldSpace) {", + " this.positionBuffer.setXYZ(index, current.position.x, current.position.y, current.position.z);", + " this.positionBuffer.setXYZ(index + 1, current.position.x, current.position.y, current.position.z);", + " }", + " else {", + " if (particle.parentMatrix) {", + " this.vector_.copy(current.position).applyMatrix4(particle.parentMatrix);", + " }", + " else {", + " this.vector_.copy(current.position).applyMatrix4(system.emitter.matrixWorld);", + " }", + " this.positionBuffer.setXYZ(index, this.vector_.x, this.vector_.y, this.vector_.z);", + " this.positionBuffer.setXYZ(index + 1, this.vector_.x, this.vector_.y, this.vector_.z);", + " }", + " if (system.worldSpace) {", + " this.previousBuffer.setXYZ(index, previous.position.x, previous.position.y, previous.position.z);", + " this.previousBuffer.setXYZ(index + 1, previous.position.x, previous.position.y, previous.position.z);", + " }", + " else {", + " if (particle.parentMatrix) {", + " this.vector_.copy(previous.position).applyMatrix4(particle.parentMatrix);", + " }", + " else {", + " this.vector_.copy(previous.position).applyMatrix4(system.emitter.matrixWorld);", + " }", + " this.previousBuffer.setXYZ(index, this.vector_.x, this.vector_.y, this.vector_.z);", + " this.previousBuffer.setXYZ(index + 1, this.vector_.x, this.vector_.y, this.vector_.z);", + " }", + " if (system.worldSpace) {", + " this.nextBuffer.setXYZ(index, next.position.x, next.position.y, next.position.z);", + " this.nextBuffer.setXYZ(index + 1, next.position.x, next.position.y, next.position.z);", + " }", + " else {", + " if (particle.parentMatrix) {", + " this.vector_.copy(next.position).applyMatrix4(particle.parentMatrix);", + " }", + " else {", + " this.vector_.copy(next.position).applyMatrix4(system.emitter.matrixWorld);", + " }", + " this.nextBuffer.setXYZ(index, this.vector_.x, this.vector_.y, this.vector_.z);", + " this.nextBuffer.setXYZ(index + 1, this.vector_.x, this.vector_.y, this.vector_.z);", + " }", + " this.sideBuffer.setX(index, -1);", + " this.sideBuffer.setX(index + 1, 1);", + " if (system.worldSpace) {", + " this.widthBuffer.setX(index, current.size);", + " this.widthBuffer.setX(index + 1, current.size);", + " }", + " else {", + " if (particle.parentMatrix) {", + " this.widthBuffer.setX(index, current.size);", + " this.widthBuffer.setX(index + 1, current.size);", + " }", + " else {", + " const objectScale = (Math.abs(scale.x) + Math.abs(scale.y) + Math.abs(scale.z)) / 3;", + " this.widthBuffer.setX(index, current.size * objectScale);", + " this.widthBuffer.setX(index + 1, current.size * objectScale);", + " }", + " }", + " this.uvBuffer.setXY(index, (i / particle.previous.length + col) * tileWidth, (vTileCount - row - 1) * tileHeight);", + " this.uvBuffer.setXY(index + 1, (i / particle.previous.length + col) * tileWidth, (vTileCount - row) * tileHeight);", + " this.colorBuffer.setXYZW(index, current.color.x, current.color.y, current.color.z, current.color.w);", + " this.colorBuffer.setXYZW(index + 1, current.color.x, current.color.y, current.color.z, current.color.w);", + " if (i + 1 < particle.previous.length) {", + " this.indexBuffer.setX(triangles * 3, index);", + " this.indexBuffer.setX(triangles * 3 + 1, index + 1);", + " this.indexBuffer.setX(triangles * 3 + 2, index + 2);", + " triangles++;", + " this.indexBuffer.setX(triangles * 3, index + 2);", + " this.indexBuffer.setX(triangles * 3 + 1, index + 1);", + " this.indexBuffer.setX(triangles * 3 + 2, index + 3);", + " triangles++;", + " }", + " previous = current;", + " current = next;", + " if (!curIter.done) {", + " curIter = iter.next();", + " if (curIter.value !== undefined) {", + " next = curIter.value;", + " }", + " }", + " }", + " }", + " });", + " this.positionBuffer.clearUpdateRanges();", + " this.positionBuffer.addUpdateRange(0, index * 3);", + " this.positionBuffer.needsUpdate = true;", + " this.previousBuffer.clearUpdateRanges();", + " this.previousBuffer.addUpdateRange(0, index * 3);", + " this.previousBuffer.needsUpdate = true;", + " this.nextBuffer.clearUpdateRanges();", + " this.nextBuffer.addUpdateRange(0, index * 3);", + " this.nextBuffer.needsUpdate = true;", + " this.sideBuffer.clearUpdateRanges();", + " this.sideBuffer.addUpdateRange(0, index);", + " this.sideBuffer.needsUpdate = true;", + " this.widthBuffer.clearUpdateRanges();", + " this.widthBuffer.addUpdateRange(0, index);", + " this.widthBuffer.needsUpdate = true;", + " this.uvBuffer.clearUpdateRanges();", + " this.uvBuffer.addUpdateRange(0, index * 2);", + " this.uvBuffer.needsUpdate = true;", + " this.colorBuffer.clearUpdateRanges();", + " this.colorBuffer.addUpdateRange(0, index * 4);", + " this.colorBuffer.needsUpdate = true;", + " this.indexBuffer.clearUpdateRanges();", + " this.indexBuffer.addUpdateRange(0, triangles * 3);", + " this.indexBuffer.needsUpdate = true;", + " this.geometry.setDrawRange(0, triangles * 3);", + " }", + " dispose() {", + " this.geometry.dispose();", + " }", + "}", + "", + "class BatchedRenderer extends THREE.Object3D {", + " constructor() {", + " super();", + " this.batches = [];", + " this.systemToBatchIndex = new Map();", + " this.type = 'BatchedRenderer';", + " }", + " static equals(a, b) {", + " return (a.material.side === b.material.side &&", + " a.material.blending === b.material.blending &&", + " a.material.transparent === b.material.transparent &&", + " a.material.type === b.material.type &&", + " a.material.alphaTest === b.material.alphaTest &&", + " a.material.map === b.material.map &&", + " a.renderMode === b.renderMode &&", + " a.uTileCount === b.uTileCount &&", + " a.vTileCount === b.vTileCount &&", + " a.instancingGeometry === b.instancingGeometry &&", + " a.renderOrder === b.renderOrder &&", + " a.layers.mask === b.layers.mask);", + " }", + " addSystem(system) {", + " system._renderer = this;", + " const settings = system.getRendererSettings();", + " for (let i = 0; i < this.batches.length; i++) {", + " if (BatchedRenderer.equals(this.batches[i].settings, settings)) {", + " this.batches[i].addSystem(system);", + " this.systemToBatchIndex.set(system, i);", + " return;", + " }", + " }", + " let batch;", + " switch (settings.renderMode) {", + " case RenderMode.Trail:", + " batch = new TrailBatch(settings);", + " break;", + " case RenderMode.Mesh:", + " case RenderMode.BillBoard:", + " case RenderMode.VerticalBillBoard:", + " case RenderMode.HorizontalBillBoard:", + " case RenderMode.StretchedBillBoard:", + " batch = new SpriteBatch(settings);", + " break;", + " }", + " batch.addSystem(system);", + " this.batches.push(batch);", + " this.systemToBatchIndex.set(system, this.batches.length - 1);", + " this.add(batch);", + " }", + " deleteSystem(system) {", + " const batchIndex = this.systemToBatchIndex.get(system);", + " if (batchIndex != undefined) {", + " this.batches[batchIndex].removeSystem(system);", + " this.systemToBatchIndex.delete(system);", + " }", + " }", + " updateSystem(system) {", + " this.deleteSystem(system);", + " this.addSystem(system);", + " }", + " update(delta) {", + " this.systemToBatchIndex.forEach((value, ps) => {", + " ps.update(delta);", + " });", + " for (let i = 0; i < this.batches.length; i++) {", + " this.batches[i].update();", + " }", + " }", + "}", + "", + "const BatchedParticleRenderer = BatchedRenderer;", + "", + "class QuarksLoader extends THREE.ObjectLoader {", + " constructor(manager) {", + " super(manager);", + " }", + " linkReference(object) {", + " const objectsMap = {};", + " object.traverse(function (child) {", + " objectsMap[child.uuid] = child;", + " });", + " object.traverse(function (child) {", + " if (child.type === 'ParticleEmitter') {", + " const system = child.system;", + " system.emitterShape;", + " for (let i = 0; i < system.behaviors.length; i++) {", + " if (system.behaviors[i] instanceof EmitSubParticleSystem) {", + " system.behaviors[i].subParticleSystem = objectsMap[system.behaviors[i].subParticleSystem];", + " }", + " }", + " }", + " });", + " }", + " parse(json, onLoad) {", + " const object = super.parse(json, onLoad);", + " this.linkReference(object);", + " return object;", + " }", + " parseObject(data, geometries, materials, textures, animations) {", + " let object;", + " function getGeometry(name) {", + " if (geometries[name] === undefined) {", + " console.warn('THREE.ObjectLoader: Undefined geometry', name);", + " }", + " return geometries[name];", + " }", + " function getMaterial(name) {", + " if (name === undefined)", + " return undefined;", + " if (Array.isArray(name)) {", + " const array = [];", + " for (let i = 0, l = name.length; i < l; i++) {", + " const uuid = name[i];", + " if (materials[uuid] === undefined) {", + " console.warn('THREE.ObjectLoader: Undefined material', uuid);", + " }", + " array.push(materials[uuid]);", + " }", + " return array;", + " }", + " if (materials[name] === undefined) {", + " console.warn('THREE.ObjectLoader: Undefined material', name);", + " }", + " return materials[name];", + " }", + " function getTexture(uuid) {", + " if (textures[uuid] === undefined) {", + " console.warn('THREE.ObjectLoader: Undefined texture', uuid);", + " }", + " return textures[uuid];", + " }", + " let geometry, material;", + " const meta = {", + " textures: textures,", + " geometries: geometries,", + " materials: materials,", + " };", + " const dependencies = {};", + " switch (data.type) {", + " case 'ParticleEmitter':", + " object = ParticleSystem.fromJSON(data.ps, meta, dependencies).emitter;", + " break;", + " case 'Scene':", + " object = new THREE.Scene();", + " if (data.background !== undefined) {", + " if (Number.isInteger(data.background)) {", + " object.background = new THREE.Color(data.background);", + " }", + " else {", + " object.background = getTexture(data.background);", + " }", + " }", + " if (data.environment !== undefined) {", + " object.environment = getTexture(data.environment);", + " }", + " if (data.fog !== undefined) {", + " if (data.fog.type === 'Fog') {", + " object.fog = new THREE.Fog(data.fog.color, data.fog.near, data.fog.far);", + " }", + " else if (data.fog.type === 'FogExp2') {", + " object.fog = new THREE.FogExp2(data.fog.color, data.fog.density);", + " }", + " }", + " if (data.backgroundBlurriness !== undefined)", + " object.backgroundBlurriness = data.backgroundBlurriness;", + " break;", + " case 'PerspectiveCamera':", + " object = new THREE.PerspectiveCamera(data.fov, data.aspect, data.near, data.far);", + " if (data.focus !== undefined)", + " object.focus = data.focus;", + " if (data.zoom !== undefined)", + " object.zoom = data.zoom;", + " if (data.filmGauge !== undefined)", + " object.filmGauge = data.filmGauge;", + " if (data.filmOffset !== undefined)", + " object.filmOffset = data.filmOffset;", + " if (data.view !== undefined)", + " object.view = Object.assign({}, data.view);", + " break;", + " case 'OrthographicCamera':", + " object = new THREE.OrthographicCamera(data.left, data.right, data.top, data.bottom, data.near, data.far);", + " if (data.zoom !== undefined)", + " object.zoom = data.zoom;", + " if (data.view !== undefined)", + " object.view = Object.assign({}, data.view);", + " break;", + " case 'AmbientLight':", + " object = new THREE.AmbientLight(data.color, data.intensity);", + " break;", + " case 'DirectionalLight':", + " object = new THREE.DirectionalLight(data.color, data.intensity);", + " break;", + " case 'PointLight':", + " object = new THREE.PointLight(data.color, data.intensity, data.distance, data.decay);", + " break;", + " case 'RectAreaLight':", + " object = new THREE.RectAreaLight(data.color, data.intensity, data.width, data.height);", + " break;", + " case 'SpotLight':", + " object = new THREE.SpotLight(data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay);", + " break;", + " case 'HemisphereLight':", + " object = new THREE.HemisphereLight(data.color, data.groundColor, data.intensity);", + " break;", + " case 'LightProbe':", + " object = new THREE.LightProbe().fromJSON(data);", + " break;", + " case 'SkinnedMesh':", + " geometry = getGeometry(data.geometry);", + " material = getMaterial(data.material);", + " object = new THREE.SkinnedMesh(geometry, material);", + " if (data.bindMode !== undefined)", + " object.bindMode = data.bindMode;", + " if (data.bindMatrix !== undefined)", + " object.bindMatrix.fromArray(data.bindMatrix);", + " if (data.skeleton !== undefined)", + " object.skeleton = data.skeleton;", + " break;", + " case 'Mesh':", + " geometry = getGeometry(data.geometry);", + " material = getMaterial(data.material);", + " object = new THREE.Mesh(geometry, material);", + " break;", + " case 'InstancedMesh': {", + " geometry = getGeometry(data.geometry);", + " material = getMaterial(data.material);", + " const count = data.count;", + " const instanceMatrix = data.instanceMatrix;", + " const instanceColor = data.instanceColor;", + " object = new THREE.InstancedMesh(geometry, material, count);", + " object.instanceMatrix = new THREE.InstancedBufferAttribute(new Float32Array(instanceMatrix.array), 16);", + " if (instanceColor !== undefined)", + " object.instanceColor = new THREE.InstancedBufferAttribute(new Float32Array(instanceColor.array), instanceColor.itemSize);", + " break;", + " }", + " case 'LOD':", + " object = new THREE.LOD();", + " break;", + " case 'Line':", + " object = new THREE.Line(getGeometry(data.geometry), getMaterial(data.material));", + " break;", + " case 'LineLoop':", + " object = new THREE.LineLoop(getGeometry(data.geometry), getMaterial(data.material));", + " break;", + " case 'LineSegments':", + " object = new THREE.LineSegments(getGeometry(data.geometry), getMaterial(data.material));", + " break;", + " case 'PointCloud':", + " case 'Points':", + " object = new THREE.Points(getGeometry(data.geometry), getMaterial(data.material));", + " break;", + " case 'Sprite':", + " object = new THREE.Sprite(getMaterial(data.material));", + " break;", + " case 'Group':", + " object = new THREE.Group();", + " break;", + " case 'Bone':", + " object = new THREE.Bone();", + " break;", + " default:", + " object = new THREE.Object3D();", + " }", + " object.uuid = data.uuid;", + " if (data.name !== undefined)", + " object.name = data.name;", + " if (data.matrix !== undefined) {", + " object.matrix.fromArray(data.matrix);", + " if (data.matrixAutoUpdate !== undefined)", + " object.matrixAutoUpdate = data.matrixAutoUpdate;", + " if (object.matrixAutoUpdate)", + " object.matrix.decompose(object.position, object.quaternion, object.scale);", + " }", + " else {", + " if (data.position !== undefined)", + " object.position.fromArray(data.position);", + " if (data.rotation !== undefined)", + " object.rotation.fromArray(data.rotation);", + " if (data.quaternion !== undefined)", + " object.quaternion.fromArray(data.quaternion);", + " if (data.scale !== undefined)", + " object.scale.fromArray(data.scale);", + " }", + " if (data.castShadow !== undefined)", + " object.castShadow = data.castShadow;", + " if (data.receiveShadow !== undefined)", + " object.receiveShadow = data.receiveShadow;", + " if (data.shadow) {", + " if (data.shadow.bias !== undefined)", + " object.shadow.bias = data.shadow.bias;", + " if (data.shadow.normalBias !== undefined)", + " object.normalBias = data.shadow.normalBias;", + " if (data.shadow.radius !== undefined)", + " object.radius = data.shadow.radius;", + " if (data.shadow.mapSize !== undefined)", + " object.mapSize.fromArray(data.shadow.mapSize);", + " if (data.shadow.camera !== undefined) {", + " object.camera = this.parseObject(data.shadow.camera);", + " }", + " }", + " if (data.visible !== undefined)", + " object.visible = data.visible;", + " if (data.frustumCulled !== undefined)", + " object.frustumCulled = data.frustumCulled;", + " if (data.renderOrder !== undefined)", + " object.renderOrder = data.renderOrder;", + " if (data.userData !== undefined)", + " object.userData = data.userData;", + " if (data.layers !== undefined)", + " object.layers.mask = data.layers;", + " if (data.children !== undefined) {", + " const children = data.children;", + " for (let i = 0; i < children.length; i++) {", + " object.add(this.parseObject(children[i], geometries, materials, textures, animations));", + " }", + " }", + " if (data.animations !== undefined) {", + " const objectAnimations = data.animations;", + " for (let i = 0; i < objectAnimations.length; i++) {", + " const uuid = objectAnimations[i];", + " object.animations.push(animations[uuid]);", + " }", + " }", + " if (data.type === 'LOD') {", + " if (data.autoUpdate !== undefined)", + " object.autoUpdate = data.autoUpdate;", + " const levels = data.levels;", + " for (let l = 0; l < levels.length; l++) {", + " const level = levels[l];", + " const child = object.getObjectByProperty('uuid', level.object);", + " if (child !== undefined) {", + " object.addLevel(child, level.distance);", + " }", + " }", + " }", + " return object;", + " }", + "}", + "", + "const Plugins = [];", + "function loadPlugin(plugin) {", + " const existing = Plugins.find((item) => item.id === plugin.id);", + " if (!existing) {", + " plugin.initialize();", + " for (const emitterShape of plugin.emitterShapes) {", + " if (!EmitterShapes[emitterShape.type]) {", + " EmitterShapes[emitterShape.type] = emitterShape;", + " }", + " }", + " for (const behavior of plugin.behaviors) {", + " if (!BehaviorTypes[behavior.type]) {", + " BehaviorTypes[behavior.type] = behavior;", + " }", + " }", + " }", + "}", + "function unloadPlugin(pluginId) {", + " const plugin = Plugins.find((item) => item.id === pluginId);", + " if (plugin) {", + " for (const emitterShape of plugin.emitterShapes) {", + " if (EmitterShapes[emitterShape.type]) {", + " delete EmitterShapes[emitterShape.type];", + " }", + " }", + " for (const behavior of plugin.behaviors) {", + " if (BehaviorTypes[behavior.type]) {", + " delete BehaviorTypes[behavior.type];", + " }", + " }", + " }", + "}", + "", + "let NodeValueType = void 0;", + "(function (NodeValueType) {", + " NodeValueType[NodeValueType[\"Number\"] = 0] = \"Number\";", + " NodeValueType[NodeValueType[\"Vec2\"] = 1] = \"Vec2\";", + " NodeValueType[NodeValueType[\"Vec3\"] = 2] = \"Vec3\";", + " NodeValueType[NodeValueType[\"Vec4\"] = 3] = \"Vec4\";", + " NodeValueType[NodeValueType[\"Boolean\"] = 4] = \"Boolean\";", + " NodeValueType[NodeValueType[\"AnyType\"] = 5] = \"AnyType\";", + " NodeValueType[NodeValueType[\"NullableAnyType\"] = 6] = \"NullableAnyType\";", + " NodeValueType[NodeValueType[\"EventStream\"] = 7] = \"EventStream\";", + "})(NodeValueType || (NodeValueType = {}));", + "const genDefaultForNodeValueType = (type) => {", + " switch (type) {", + " case NodeValueType.Boolean:", + " return false;", + " case NodeValueType.Number:", + " return 0;", + " case NodeValueType.Vec2:", + " return new THREE.Vector2();", + " case NodeValueType.Vec3:", + " return new THREE.Vector3();", + " case NodeValueType.Vec4:", + " return new THREE.Vector4();", + " case NodeValueType.AnyType:", + " return 0;", + " case NodeValueType.NullableAnyType:", + " return undefined;", + " }", + "};", + "", + "class Node {", + " constructor(type, signatureIndex = -1, data = {}) {", + " this.inputs = [];", + " this.outputs = [];", + " this.signatureIndex = -1;", + " this.position = new THREE.Vector2();", + " this.outputValues = [];", + " this.id = '' + Math.round(Math.random() * 100000);", + " this.type = type;", + " this.signatureIndex = signatureIndex;", + " this.data = data;", + " const realIndex = signatureIndex === -1 ? 0 : signatureIndex;", + " for (let i = 0; i < type.nodeTypeSignatures[realIndex].inputTypes.length; i++) {", + " this.inputs.push(undefined);", + " }", + " for (let i = 0; i < type.nodeTypeSignatures[realIndex].outputTypes.length; i++) {", + " this.outputs.push([]);", + " this.outputValues.push(genDefaultForNodeValueType(type.nodeTypeSignatures[realIndex].outputTypes[i]));", + " }", + " }", + " get inputTypes() {", + " const signatureIndex = this.signatureIndex === -1 ? 0 : this.signatureIndex;", + " return this.type.nodeTypeSignatures[signatureIndex].inputTypes;", + " }", + " get outputTypes() {", + " const signatureIndex = this.signatureIndex === -1 ? 0 : this.signatureIndex;", + " return this.type.nodeTypeSignatures[signatureIndex].outputTypes;", + " }", + " func(context, inputs, outputs) {", + " const signatureIndex = this.signatureIndex === -1 ? 0 : this.signatureIndex;", + " this.type.nodeTypeSignatures[signatureIndex].func(context, this.data, inputs, outputs);", + " }", + "}", + "class Wire {", + " constructor(input, inputIndex, output, outputIndex) {", + " this.input = input;", + " this.inputIndex = inputIndex;", + " this.input.outputs[inputIndex].push(this);", + " this.output = output;", + " this.outputIndex = outputIndex;", + " this.output.inputs[outputIndex] = this;", + " }", + "}", + "", + "class BaseCompiler {", + " constructor() {", + " this.visited = new Set();", + " BaseCompiler.Instance = this;", + " }", + " buildExecutionOrder(graph, context) {", + " graph.nodesInOrder.length = 0;", + " this.visited.clear();", + " for (let i = 0; i < graph.outputNodes.length; i++) {", + " const node = graph.outputNodes[i];", + " if (node.inputs[0] !== undefined) {", + " this._traverse(node, graph, context);", + " }", + " }", + " graph.compiled = true;", + " }", + " _traverse(node, graph, context) {", + " this.visited.add(node.id);", + " for (let i = 0; i < node.inputs.length; i++) {", + " if (node.inputs[i] instanceof Wire) {", + " const inputNode = node.inputs[i].input;", + " if (!this.visited.has(inputNode.id)) {", + " this._traverse(inputNode, graph, context);", + " }", + " }", + " else if (node.inputs[i] !== undefined);", + " else;", + " }", + " graph.nodesInOrder.push(node);", + " }", + "}", + "", + "class Interpreter extends BaseCompiler {", + " constructor() {", + " super();", + " }", + " executeCompiledGraph(graph, context) {", + " const nodes = graph.nodesInOrder;", + " for (let i = 0; i < nodes.length; i++) {", + " const inputValues = [];", + " const node = nodes[i];", + " for (let j = 0; j < node.inputs.length; j++) {", + " if (node.inputs[j] instanceof Wire) {", + " inputValues.push(node.inputs[j].input.outputValues[node.inputs[j].inputIndex]);", + " }", + " else if (node.inputs[j] !== undefined) {", + " inputValues.push(node.inputs[j].getValue(context));", + " }", + " else {", + " inputValues.push(undefined);", + " }", + " }", + " node.func(context, inputValues, node.outputValues);", + " }", + " }", + " run(graph, context) {", + " if (!graph.compiled) {", + " this.buildExecutionOrder(graph, context);", + " }", + " this.executeCompiledGraph(graph, context);", + " }", + "}", + "", + "class NodeType {", + " constructor(name) {", + " this.nodeTypeSignatures = [];", + " this.name = name;", + " }", + " addSignature(inputTypes, outputTypes, func) {", + " this.nodeTypeSignatures.push({", + " inputTypes: inputTypes,", + " outputTypes: outputTypes,", + " func: func,", + " });", + " }", + "}", + "class GraphNodeType extends NodeType {", + " constructor(nodeGraph) {", + " const inputTypes = [];", + " for (let i = 0; i < nodeGraph.inputNodes.length; i++) {", + " if (nodeGraph.inputNodes[i].type.name === 'input') {", + " inputTypes.push(nodeGraph.inputNodes[i].data.type);", + " }", + " }", + " const outputTypes = [];", + " for (let i = 0; i < nodeGraph.outputNodes.length; i++) {", + " if (nodeGraph.outputNodes[i].type.name === 'output') {", + " outputTypes.push(nodeGraph.outputNodes[i].data.type);", + " }", + " }", + " super(nodeGraph.name);", + " this.addSignature(inputTypes, outputTypes, (context, data, inputs, outputs) => {", + " context.inputs = inputs;", + " context.outputs = outputs;", + " Interpreter.Instance.run(nodeGraph, context);", + " });", + " this.nodeGraph = nodeGraph;", + " }", + "}", + "", + "const NodeTypes = {};", + "const addNode = new NodeType('add');", + "addNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] + inputs[1];", + "});", + "addNode.addSignature([NodeValueType.Vec2, NodeValueType.Vec2], [NodeValueType.Vec2], (context, data, inputs, outputs) => {", + " outputs[0].addVectors(inputs[0], inputs[1]);", + "});", + "addNode.addSignature([NodeValueType.Vec3, NodeValueType.Vec3], [NodeValueType.Vec3], (context, data, inputs, outputs) => {", + " outputs[0].addVectors(inputs[0], inputs[1]);", + "});", + "addNode.addSignature([NodeValueType.Vec4, NodeValueType.Vec4], [NodeValueType.Vec4], (context, data, inputs, outputs) => {", + " outputs[0].addVectors(inputs[0], inputs[1]);", + "});", + "NodeTypes['add'] = addNode;", + "const subNode = new NodeType('sub');", + "subNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] - inputs[1];", + "});", + "subNode.addSignature([NodeValueType.Vec2, NodeValueType.Vec2], [NodeValueType.Vec2], (context, data, inputs, outputs) => {", + " outputs[0].subVectors(inputs[0], inputs[1]);", + "});", + "subNode.addSignature([NodeValueType.Vec3, NodeValueType.Vec3], [NodeValueType.Vec3], (context, data, inputs, outputs) => {", + " outputs[0].subVectors(inputs[0], inputs[1]);", + "});", + "subNode.addSignature([NodeValueType.Vec4, NodeValueType.Vec4], [NodeValueType.Vec4], (context, data, inputs, outputs) => {", + " outputs[0].subVectors(inputs[0], inputs[1]);", + "});", + "NodeTypes['sub'] = subNode;", + "const mulNode = new NodeType('mul');", + "mulNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] * inputs[1];", + "});", + "mulNode.addSignature([NodeValueType.Vec2, NodeValueType.Number], [NodeValueType.Vec2], (context, data, inputs, outputs) => {", + " outputs[0].copy(inputs[0]).multiplyScalar(inputs[1]);", + "});", + "mulNode.addSignature([NodeValueType.Vec3, NodeValueType.Number], [NodeValueType.Vec3], (context, data, inputs, outputs) => {", + " outputs[0].copy(inputs[0]).multiplyScalar(inputs[1]);", + "});", + "mulNode.addSignature([NodeValueType.Vec4, NodeValueType.Number], [NodeValueType.Vec4], (context, data, inputs, outputs) => {", + " outputs[0].copy(inputs[0]).multiplyScalar(inputs[1]);", + "});", + "NodeTypes['mul'] = mulNode;", + "const divNode = new NodeType('div');", + "divNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] / inputs[1];", + "});", + "divNode.addSignature([NodeValueType.Vec2, NodeValueType.Number], [NodeValueType.Vec2], (context, data, inputs, outputs) => {", + " outputs[0].copy(inputs[0]).divideScalar(inputs[1]);", + "});", + "divNode.addSignature([NodeValueType.Vec3, NodeValueType.Number], [NodeValueType.Vec3], (context, data, inputs, outputs) => {", + " outputs[0].copy(inputs[0]).divideScalar(inputs[1]);", + "});", + "divNode.addSignature([NodeValueType.Vec4, NodeValueType.Number], [NodeValueType.Vec4], (context, data, inputs, outputs) => {", + " outputs[0].copy(inputs[0]).divideScalar(inputs[1]);", + "});", + "NodeTypes['div'] = divNode;", + "const sinNode = new NodeType('sin');", + "sinNode.addSignature([NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = Math.sin(inputs[0]);", + "});", + "NodeTypes['sin'] = sinNode;", + "const cosNode = new NodeType('cos');", + "cosNode.addSignature([NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = Math.cos(inputs[0]);", + "});", + "NodeTypes['cos'] = cosNode;", + "const tanNode = new NodeType('tan');", + "tanNode.addSignature([NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = Math.tan(inputs[0]);", + "});", + "NodeTypes['tan'] = tanNode;", + "const absNode = new NodeType('abs');", + "absNode.addSignature([NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = Math.abs(inputs[0]);", + "});", + "NodeTypes['abs'] = absNode;", + "const minNode = new NodeType('min');", + "minNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = Math.min(inputs[0], inputs[1]);", + "});", + "NodeTypes['min'] = minNode;", + "const maxNode = new NodeType('max');", + "maxNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = Math.max(inputs[0], inputs[1]);", + "});", + "NodeTypes['max'] = maxNode;", + "const dot = new NodeType('dot');", + "dot.addSignature([NodeValueType.Vec2, NodeValueType.Vec2], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].dot(inputs[1]);", + "});", + "dot.addSignature([NodeValueType.Vec3, NodeValueType.Vec3], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].dot(inputs[1]);", + "});", + "dot.addSignature([NodeValueType.Vec4, NodeValueType.Vec4], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].dot(inputs[1]);", + "});", + "NodeTypes['dot'] = dot;", + "const cross = new NodeType('cross');", + "cross.addSignature([NodeValueType.Vec3, NodeValueType.Vec3], [NodeValueType.Vec3], (context, data, inputs, outputs) => {", + " outputs[0].crossVectors(inputs[0], inputs[1]);", + "});", + "NodeTypes['cross'] = cross;", + "const length = new NodeType('length');", + "length.addSignature([NodeValueType.Vec2], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].length();", + "});", + "length.addSignature([NodeValueType.Vec3], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].length();", + "});", + "length.addSignature([NodeValueType.Vec4], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].length();", + "});", + "NodeTypes['length'] = length;", + "const lengthSq = new NodeType('lengthSq');", + "lengthSq.addSignature([NodeValueType.Vec2], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].lengthSq();", + "});", + "lengthSq.addSignature([NodeValueType.Vec3], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].lengthSq();", + "});", + "lengthSq.addSignature([NodeValueType.Vec4], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].lengthSq();", + "});", + "NodeTypes['lengthSq'] = lengthSq;", + "const normalize = new NodeType('normalize');", + "normalize.addSignature([NodeValueType.Vec2], [NodeValueType.Vec2], (context, data, inputs, outputs) => {", + " outputs[0].copy(inputs[0]).normalize();", + "});", + "normalize.addSignature([NodeValueType.Vec3], [NodeValueType.Vec3], (context, data, inputs, outputs) => {", + " outputs[0].copy(inputs[0]).normalize();", + "});", + "normalize.addSignature([NodeValueType.Vec4], [NodeValueType.Vec4], (context, data, inputs, outputs) => {", + " outputs[0].copy(inputs[0]).normalize();", + "});", + "NodeTypes['normalize'] = normalize;", + "const distance = new NodeType('distance');", + "distance.addSignature([NodeValueType.Vec2, NodeValueType.Vec2], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].distanceTo(inputs[1]);", + "});", + "distance.addSignature([NodeValueType.Vec3, NodeValueType.Vec3], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].distanceTo(inputs[1]);", + "});", + "NodeTypes['distance'] = distance;", + "const andNode = new NodeType('and');", + "andNode.addSignature([NodeValueType.Boolean, NodeValueType.Boolean], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] && inputs[1];", + "});", + "NodeTypes['and'] = andNode;", + "const orNode = new NodeType('or');", + "orNode.addSignature([NodeValueType.Boolean, NodeValueType.Boolean], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] || inputs[1];", + "});", + "NodeTypes['or'] = orNode;", + "const notNode = new NodeType('not');", + "notNode.addSignature([NodeValueType.Boolean], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = !inputs[0];", + "});", + "NodeTypes['not'] = notNode;", + "const equalNode = new NodeType('equal');", + "equalNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] === inputs[1];", + "});", + "equalNode.addSignature([NodeValueType.Vec2, NodeValueType.Vec2], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].equals(inputs[1]);", + "});", + "equalNode.addSignature([NodeValueType.Vec3, NodeValueType.Vec3], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].equals(inputs[1]);", + "});", + "equalNode.addSignature([NodeValueType.Vec4, NodeValueType.Vec4], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].equals(inputs[1]);", + "});", + "NodeTypes['equal'] = equalNode;", + "const lessThanNode = new NodeType('lessThan');", + "lessThanNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] < inputs[1];", + "});", + "NodeTypes['lessThan'] = lessThanNode;", + "const greaterThanNode = new NodeType('greaterThan');", + "greaterThanNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] > inputs[1];", + "});", + "NodeTypes['greaterThan'] = greaterThanNode;", + "const lessThanOrEqualNode = new NodeType('lessThanOrEqual');", + "lessThanOrEqualNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] <= inputs[1];", + "});", + "NodeTypes['lessThanOrEqual'] = lessThanOrEqualNode;", + "const greaterThanOrEqualNode = new NodeType('greaterThanOrEqual');", + "greaterThanOrEqualNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] >= inputs[1];", + "});", + "NodeTypes['greaterThanOrEqual'] = greaterThanOrEqualNode;", + "const ifNode = new NodeType('if');", + "ifNode.addSignature([NodeValueType.Boolean, NodeValueType.AnyType, NodeValueType.AnyType], [NodeValueType.AnyType], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] ? inputs[1] : inputs[2];", + "});", + "NodeTypes['if'] = ifNode;", + "const numberNode = new NodeType('number');", + "numberNode.addSignature([], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = data.value;", + "});", + "NodeTypes['number'] = numberNode;", + "const vec2Node = new NodeType('vec2');", + "vec2Node.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Vec2], (context, data, inputs, outputs) => {", + " outputs[0].x = inputs[0];", + " outputs[0].y = inputs[1];", + "});", + "NodeTypes['vec2'] = vec2Node;", + "const vec3Node = new NodeType('vec3');", + "vec3Node.addSignature([NodeValueType.Number, NodeValueType.Number, NodeValueType.Number], [NodeValueType.Vec3], (context, data, inputs, outputs) => {", + " outputs[0].x = inputs[0];", + " outputs[0].y = inputs[1];", + " outputs[0].z = inputs[2];", + "});", + "NodeTypes['vec3'] = vec3Node;", + "const vec4Node = new NodeType('vec4');", + "vec4Node.addSignature([NodeValueType.Number, NodeValueType.Number, NodeValueType.Number, NodeValueType.Number], [NodeValueType.Vec4], (context, data, inputs, outputs) => {", + " outputs[0].x = inputs[0];", + " outputs[0].y = inputs[1];", + " outputs[0].z = inputs[2];", + " outputs[0].w = inputs[3];", + "});", + "NodeTypes['vec4'] = vec4Node;", + "const splitVec2Node = new NodeType('splitVec2');", + "splitVec2Node.addSignature([NodeValueType.Vec2], [NodeValueType.Number, NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].x;", + " outputs[1] = inputs[0].y;", + "});", + "NodeTypes['splitVec2'] = splitVec2Node;", + "const splitVec3Node = new NodeType('splitVec3');", + "splitVec3Node.addSignature([NodeValueType.Vec3], [NodeValueType.Number, NodeValueType.Number, NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].x;", + " outputs[1] = inputs[0].y;", + " outputs[2] = inputs[0].z;", + "});", + "NodeTypes['splitVec3'] = splitVec3Node;", + "const splitVec4Node = new NodeType('splitVec4');", + "splitVec4Node.addSignature([NodeValueType.Vec4], [NodeValueType.Number, NodeValueType.Number, NodeValueType.Number, NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].x;", + " outputs[1] = inputs[0].y;", + " outputs[2] = inputs[0].z;", + " outputs[3] = inputs[0].w;", + "});", + "NodeTypes['splitVec4'] = splitVec4Node;", + "const boolNode = new NodeType('bool');", + "boolNode.addSignature([], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = data.value;", + "});", + "NodeTypes['bool'] = boolNode;", + "const particlePropertyNode = new NodeType('particleProperty');", + "particlePropertyNode.addSignature([NodeValueType.NullableAnyType], [NodeValueType.NullableAnyType], (context, data, inputs, outputs) => {", + " if (inputs[0] !== undefined) {", + " if (typeof inputs[0] === 'object') {", + " context.particle[data.property].copy(inputs[0]);", + " }", + " else {", + " context.particle[data.property] = inputs[0];", + " }", + " }", + " if (context.particle[data.property] !== undefined) {", + " if (typeof outputs[0] === 'object') {", + " outputs[0].copy(context.particle[data.property]);", + " }", + " else {", + " outputs[0] = context.particle[data.property];", + " }", + " }", + "});", + "NodeTypes['particleProperty'] = particlePropertyNode;", + "const emitNode = new NodeType('emit');", + "emitNode.addSignature([NodeValueType.EventStream], [], (context, data, inputs, outputs) => {", + " const arr = inputs[0];", + " for (let i = 0; i < arr.length; i++) {", + " context.signal(i, arr[i]);", + " }", + "});", + "NodeTypes['emit'] = emitNode;", + "const graphPropertyNode = new NodeType('graphProperty');", + "graphPropertyNode.addSignature([NodeValueType.NullableAnyType], [NodeValueType.NullableAnyType], (context, data, inputs, outputs) => {", + " if (inputs[0] !== undefined) {", + " if (typeof inputs[0] === 'object') {", + " context.graph[data.property].copy(inputs[0]);", + " }", + " else {", + " context.graph[data.property] = inputs[0];", + " }", + " }", + " if (context.graph[data.property] !== undefined) {", + " if (typeof outputs[0] === 'object') {", + " outputs[0].copy(context.graph[data.property]);", + " }", + " else {", + " outputs[0] = context.graph[data.property];", + " }", + " }", + "});", + "NodeTypes['graphProperty'] = graphPropertyNode;", + "const startEventNode = new NodeType('startEvent');", + "startEventNode.addSignature([], [NodeValueType.EventStream], (context, data, inputs, outputs) => {", + " outputs[0] = [{ type: 'start' }];", + "});", + "NodeTypes['startEvent'] = startEventNode;", + "const repeaterNode = new NodeType('repeater');", + "repeaterNode.addSignature([NodeValueType.EventStream, NodeValueType.Number], [NodeValueType.EventStream], (context, data, inputs, outputs) => {", + " const arr = inputs[0];", + " const count = inputs[1];", + " const result = [];", + " for (let j = 0; j < arr.length; j++) {", + " for (let i = 0; i < count; i++) {", + " result.push(arr[j]);", + " }", + " }", + " outputs[0] = result;", + "});", + "NodeTypes['repeater'] = repeaterNode;", + "const timeNode = new NodeType('time');", + "timeNode.addSignature([], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = context.emissionState.time;", + "});", + "NodeTypes['time'] = timeNode;", + "const deltaNode = new NodeType('delta');", + "deltaNode.addSignature([], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = context.delta;", + "});", + "NodeTypes['delta'] = deltaNode;", + "const outputNode = new NodeType('output');", + "outputNode.addSignature([NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0];", + "});", + "outputNode.addSignature([NodeValueType.Vec2], [NodeValueType.Vec2], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0];", + "});", + "outputNode.addSignature([NodeValueType.Vec3], [NodeValueType.Vec3], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0];", + "});", + "outputNode.addSignature([NodeValueType.Vec4], [NodeValueType.Vec4], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0];", + "});", + "outputNode.addSignature([NodeValueType.Boolean], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0];", + "});", + "NodeTypes['output'] = outputNode;", + "const lerpNode = new NodeType('lerp');", + "lerpNode.addSignature([NodeValueType.Number, NodeValueType.Number, NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] =", + " inputs[0] * (1 - inputs[2]) + inputs[1] * inputs[2];", + "});", + "lerpNode.addSignature([NodeValueType.Vec2, NodeValueType.Vec2, NodeValueType.Number], [NodeValueType.Vec2], (context, data, inputs, outputs) => {", + " outputs[0].lerpVectors(inputs[0], inputs[1], inputs[2]);", + "});", + "lerpNode.addSignature([NodeValueType.Vec3, NodeValueType.Vec3, NodeValueType.Number], [NodeValueType.Vec3], (context, data, inputs, outputs) => {", + " outputs[0].lerpVectors(inputs[0], inputs[1], inputs[2]);", + "});", + "lerpNode.addSignature([NodeValueType.Vec4, NodeValueType.Vec4, NodeValueType.Number], [NodeValueType.Vec4], (context, data, inputs, outputs) => {", + " outputs[0].lerpVectors(inputs[0], inputs[1], inputs[2]);", + "});", + "NodeTypes['lerp'] = lerpNode;", + "const normalD = (x) => {", + " return (1 / Math.sqrt(2 * Math.PI)) * Math.exp(x * x * -0.5);", + "};", + "const normalDistributionNode = new NodeType('normDistrib');", + "normalDistributionNode.addSignature([NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = normalD(inputs[0]);", + "});", + "NodeTypes['normDistrib'] = normalDistributionNode;", + "const normcdfNode = new NodeType('normcdf');", + "normcdfNode.addSignature([NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " let x = inputs[0];", + " const a1 = 0.254829592;", + " const a2 = -0.284496736;", + " const a3 = 1.421413741;", + " const a4 = -1.453152027;", + " const a5 = 1.061405429;", + " const p = 0.3275911;", + " let sign = 1;", + " if (x < 0)", + " sign = -1;", + " x = Math.abs(x) / Math.sqrt(2.0);", + " const t = 1.0 / (1.0 + p * x);", + " const y = 1.0 - ((((a5 * t + a4) * t + a3) * t + a2) * t + a1) * t * Math.exp(-x * x);", + " outputs[0] = 0.5 * (1.0 + sign * y);", + "});", + "NodeTypes['normcdf'] = normcdfNode;", + "const normcdfInvNode = new NodeType('normcdfInv');", + "const rationalApproximation = (t) => {", + " const c = [2.515517, 0.802853, 0.010328];", + " const d = [1.432788, 0.189269, 0.001308];", + " return t - ((c[2] * t + c[1]) * t + c[0]) / (((d[2] * t + d[1]) * t + d[0]) * t + 1.0);", + "};", + "const normcdfInv = (p) => {", + " if (p < 0.5) {", + " return -rationalApproximation(Math.sqrt(-2.0 * Math.log(p)));", + " }", + " else {", + " return rationalApproximation(Math.sqrt(-2.0 * Math.log(1 - p)));", + " }", + "};", + "normcdfInvNode.addSignature([NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = normcdfInv(inputs[0]);", + "});", + "NodeTypes['normcdfInv'] = normcdfInvNode;", + "const clampNode = new NodeType('clamp');", + "clampNode.addSignature([NodeValueType.Number, NodeValueType.Number, NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = Math.max(Math.min(inputs[0], inputs[2]), inputs[1]);", + "});", + "NodeTypes['clamp'] = clampNode;", + "const smoothstepNode = new NodeType('smoothstep');", + "smoothstepNode.addSignature([NodeValueType.Number, NodeValueType.Number, NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " const x = Math.max(Math.min(inputs[0], inputs[2]), inputs[1]);", + " outputs[0] = x * x * (3 - 2 * x);", + "});", + "NodeTypes['smoothstep'] = smoothstepNode;", + "const randomNode = new NodeType('random');", + "randomNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = Math.random() * (inputs[1] - inputs[0]) + inputs[0];", + "});", + "randomNode.addSignature([NodeValueType.Vec2, NodeValueType.Vec2], [NodeValueType.Vec2], (context, data, inputs, outputs) => {", + " let random = Math.random();", + " outputs[0].lerpVectors(inputs[0], inputs[1], random);", + "});", + "randomNode.addSignature([NodeValueType.Vec3, NodeValueType.Vec3], [NodeValueType.Vec3], (context, data, inputs, outputs) => {", + " let random = Math.random();", + " outputs[0].lerpVectors(inputs[0], inputs[1], random);", + "});", + "randomNode.addSignature([NodeValueType.Vec4, NodeValueType.Vec4], [NodeValueType.Vec4], (context, data, inputs, outputs) => {", + " let random = Math.random();", + " outputs[0].lerpVectors(inputs[0], inputs[1], random);", + "});", + "NodeTypes['random'] = randomNode;", + "const vrandNode = new NodeType('vrand');", + "vrandNode.addSignature([], [NodeValueType.Vec2], (context, data, inputs, outputs) => {", + " let x = normcdfInv(Math.random());", + " let y = normcdfInv(Math.random());", + " const mag = Math.sqrt(x * x + y * y);", + " outputs[0].set(x / mag, y / mag);", + "});", + "vrandNode.addSignature([], [NodeValueType.Vec3], (context, data, inputs, outputs) => {", + " let x = normcdfInv(Math.random());", + " let y = normcdfInv(Math.random());", + " let z = normcdfInv(Math.random());", + " const mag = Math.sqrt(x * x + y * y + z * z);", + " outputs[0].set(x / mag, y / mag, z / mag);", + "});", + "vrandNode.addSignature([], [NodeValueType.Vec4], (context, data, inputs, outputs) => {", + " let x = normcdfInv(Math.random());", + " let y = normcdfInv(Math.random());", + " let z = normcdfInv(Math.random());", + " let w = normcdfInv(Math.random());", + " const mag = Math.sqrt(x * x + y * y + z * z + w * w);", + " outputs[0].set(x / mag, y / mag, z / mag, w / mag);", + "});", + "NodeTypes['vrand'] = vrandNode;", + "const bsdfNode = new NodeType('bsdf');", + "bsdfNode.addSignature([NodeValueType.Vec3, NodeValueType.Vec3, NodeValueType.Vec3, NodeValueType.Number], [], (context, data, inputs, outputs) => { });", + "NodeTypes['bsdf'] = bsdfNode;", + "const OutputNodeTypeNames = new Set(['output', 'particleProperty', 'graphProperty', 'emit']);", + "", + "class NodeGraph {", + " constructor(name) {", + " this.inputNodes = [];", + " this.outputNodes = [];", + " this.allNodes = new Map();", + " this.wires = [];", + " this.compiled = false;", + " this.nodesInOrder = [];", + " this.version = '1.0';", + " this.uuid = THREE.MathUtils.generateUUID();", + " this.name = name;", + " this.revision = 0;", + " }", + " addWire(wire) {", + " this.wires.push(wire);", + " this.revision++;", + " }", + " addNode(node) {", + " this.allNodes.set(node.id, node);", + " if (node.type === NodeTypes['input']) {", + " this.inputNodes.push(node);", + " }", + " else if (OutputNodeTypeNames.has(node.type.name)) {", + " this.outputNodes.push(node);", + " }", + " this.revision++;", + " }", + " getNode(id) {", + " return this.allNodes.get(id);", + " }", + " deleteNode(node) {", + " this.allNodes.delete(node.id);", + " this.revision++;", + " }", + " deleteWire(wire) {", + " let index = wire.input.outputs[wire.inputIndex].indexOf(wire);", + " if (index !== -1) {", + " wire.input.outputs[wire.inputIndex].splice(index, 1);", + " }", + " wire.output.inputs[wire.outputIndex] = undefined;", + " index = this.wires.indexOf(wire);", + " if (index != -1) {", + " this.wires[index] = this.wires[this.wires.length - 1];", + " this.wires.pop();", + " }", + " this.revision++;", + " }", + " toJSON() {", + " throw new Error('not implemented');", + " }", + " clone() {", + " throw new Error('not implemented');", + " }", + "}", + "", + "new THREE.Vector3(0, 0, 1);", + "const tempQ = new THREE.Quaternion();", + "const tempV = new THREE.Vector3();", + "const tempV2 = new THREE.Vector3();", + "const PREWARM_FPS = 60;", + "const DEFAULT_GEOMETRY = new THREE.PlaneGeometry(1, 1, 1, 1);", + "class NodeVFX {", + " set time(time) {", + " this.emissionState.time = time;", + " }", + " get time() {", + " return this.emissionState.time;", + " }", + " get layers() {", + " return this.rendererSettings.layers;", + " }", + " get texture() {", + " return this.rendererSettings.material.map;", + " }", + " set texture(texture) {", + " this.rendererSettings.material.map = texture;", + " this.neededToUpdateRender = true;", + " }", + " get material() {", + " return this.rendererSettings.material;", + " }", + " set material(material) {", + " this.rendererSettings.material = material;", + " this.neededToUpdateRender = true;", + " }", + " get instancingGeometry() {", + " return this.rendererSettings.instancingGeometry;", + " }", + " set instancingGeometry(geometry) {", + " this.restart();", + " this.particles.length = 0;", + " this.rendererSettings.instancingGeometry = geometry;", + " this.neededToUpdateRender = true;", + " }", + " get renderMode() {", + " return this.rendererSettings.renderMode;", + " }", + " set renderMode(renderMode) {", + " if ((this.rendererSettings.renderMode != RenderMode.Trail && renderMode === RenderMode.Trail) ||", + " (this.rendererSettings.renderMode == RenderMode.Trail && renderMode !== RenderMode.Trail)) {", + " this.restart();", + " this.particles.length = 0;", + " }", + " if (this.rendererSettings.renderMode !== renderMode) {", + " switch (renderMode) {", + " case RenderMode.Trail:", + " this.rendererEmitterSettings = {", + " startLength: 30,", + " followLocalOrigin: false,", + " };", + " break;", + " case RenderMode.Mesh:", + " this.rendererEmitterSettings = {", + " geometry: new THREE.PlaneGeometry(1, 1),", + " };", + " break;", + " case RenderMode.BillBoard:", + " case RenderMode.VerticalBillBoard:", + " case RenderMode.HorizontalBillBoard:", + " case RenderMode.StretchedBillBoard:", + " this.rendererEmitterSettings = {};", + " break;", + " }", + " }", + " this.rendererSettings.renderMode = renderMode;", + " this.neededToUpdateRender = true;", + " }", + " get renderOrder() {", + " return this.rendererSettings.renderOrder;", + " }", + " set renderOrder(renderOrder) {", + " this.rendererSettings.renderOrder = renderOrder;", + " this.neededToUpdateRender = true;", + " }", + " get blending() {", + " return this.rendererSettings.material.blending;", + " }", + " set blending(blending) {", + " this.rendererSettings.material.blending = blending;", + " this.neededToUpdateRender = true;", + " }", + " constructor(parameters) {", + " var _a, _b, _c, _d, _e, _f, _g;", + " this.temp = new THREE.Vector3();", + " this.travelDistance = 0;", + " this.normalMatrix = new THREE.Matrix3();", + " this.speedFactor = 0;", + " this.autoDestroy = parameters.autoDestroy === undefined ? false : parameters.autoDestroy;", + " this.duration = (_a = parameters.duration) !== null && _a !== void 0 ? _a : 1;", + " this.looping = parameters.looping === undefined ? true : parameters.looping;", + " this.prewarm = parameters.prewarm === undefined ? false : parameters.prewarm;", + " this.worldSpace = (_b = parameters.worldSpace) !== null && _b !== void 0 ? _b : false;", + " this.rendererEmitterSettings = (_c = parameters.rendererEmitterSettings) !== null && _c !== void 0 ? _c : {};", + " this.emissionGraph = parameters.emissionGraph;", + " this.updateGraph = parameters.updateGraph;", + " this.interpreter = new Interpreter();", + " this.rendererSettings = {", + " instancingGeometry: (_d = parameters.instancingGeometry) !== null && _d !== void 0 ? _d : DEFAULT_GEOMETRY,", + " renderMode: (_e = parameters.renderMode) !== null && _e !== void 0 ? _e : RenderMode.BillBoard,", + " renderOrder: (_f = parameters.renderOrder) !== null && _f !== void 0 ? _f : 0,", + " material: parameters.material,", + " layers: (_g = parameters.layers) !== null && _g !== void 0 ? _g : new THREE.Layers(),", + " uTileCount: 1,", + " vTileCount: 1,", + " };", + " this.neededToUpdateRender = true;", + " this.particles = new Array();", + " this.emitter = new ParticleEmitter(this);", + " this.paused = false;", + " this.particleNum = 0;", + " this.emissionState = {", + " time: 0,", + " };", + " this.emitEnded = false;", + " this.markForDestroy = false;", + " this.prewarmed = false;", + " }", + " pause() {", + " this.paused = true;", + " }", + " play() {", + " this.paused = false;", + " }", + " spawn(emissionState, matrix) {", + " tempQ.setFromRotationMatrix(matrix);", + " const translation = tempV;", + " const quaternion = tempQ;", + " const scale = tempV2;", + " matrix.decompose(translation, quaternion, scale);", + " this.particleNum++;", + " while (this.particles.length < this.particleNum) {", + " this.particles.push(new NodeParticle());", + " }", + " const particle = this.particles[this.particleNum - 1];", + " particle.reset();", + " this.interpreter.run(this.updateGraph, { particle: particle, emissionState: this.emissionState });", + " if (this.rendererSettings.renderMode === RenderMode.Trail &&", + " this.rendererEmitterSettings.followLocalOrigin) {", + " const trail = particle;", + " trail.localPosition = new THREE.Vector3().copy(trail.position);", + " }", + " if (this.worldSpace) {", + " particle.position.applyMatrix4(matrix);", + " particle.size *= (Math.abs(scale.x) + Math.abs(scale.y) + Math.abs(scale.z)) / 3;", + " particle.velocity.multiply(scale).applyMatrix3(this.normalMatrix);", + " if (particle.rotation && particle.rotation instanceof THREE.Quaternion) {", + " particle.rotation.multiplyQuaternions(tempQ, particle.rotation);", + " }", + " }", + " }", + " endEmit() {", + " this.emitEnded = true;", + " if (this.autoDestroy) {", + " this.markForDestroy = true;", + " }", + " }", + " dispose() {", + " if (this._renderer)", + " this._renderer.deleteSystem(this);", + " this.emitter.dispose();", + " if (this.emitter.parent)", + " this.emitter.parent.remove(this.emitter);", + " }", + " restart() {", + " this.paused = false;", + " this.particleNum = 0;", + " this.emissionState.time = 0;", + " this.emitEnded = false;", + " this.markForDestroy = false;", + " this.prewarmed = false;", + " }", + " update(delta) {", + " if (this.paused)", + " return;", + " let currentParent = this.emitter;", + " while (currentParent.parent) {", + " currentParent = currentParent.parent;", + " }", + " if (currentParent.type !== 'Scene') {", + " this.dispose();", + " return;", + " }", + " if (this.emitEnded && this.particleNum === 0) {", + " if (this.markForDestroy && this.emitter.parent)", + " this.dispose();", + " return;", + " }", + " if (this.looping && this.prewarm && !this.prewarmed) {", + " this.prewarmed = true;", + " for (let i = 0; i < this.duration * PREWARM_FPS; i++) {", + " this.update(1.0 / PREWARM_FPS);", + " }", + " }", + " if (delta > 0.1) {", + " delta = 0.1;", + " }", + " if (this.neededToUpdateRender) {", + " if (this._renderer)", + " this._renderer.updateSystem(this);", + " this.neededToUpdateRender = false;", + " }", + " this.emit(delta, this.emissionState, this.emitter.matrixWorld);", + " const context = { particle: undefined, emissionState: this.emissionState, delta };", + " for (let i = 0; i < this.particleNum; i++) {", + " context.particle = this.particles[i];", + " this.interpreter.run(this.updateGraph, context);", + " }", + " for (let i = 0; i < this.particleNum; i++) {", + " if (this.rendererEmitterSettings.followLocalOrigin &&", + " this.particles[i].localPosition) {", + " this.particles[i].position.copy(this.particles[i].localPosition);", + " if (this.particles[i].parentMatrix) {", + " this.particles[i].position.applyMatrix4(this.particles[i].parentMatrix);", + " }", + " else {", + " this.particles[i].position.applyMatrix4(this.emitter.matrixWorld);", + " }", + " }", + " else {", + " this.particles[i].position.addScaledVector(this.particles[i].velocity, delta);", + " }", + " this.particles[i].age += delta;", + " }", + " if (this.rendererSettings.renderMode === RenderMode.Trail) {", + " for (let i = 0; i < this.particleNum; i++) {", + " const particle = this.particles[i];", + " particle.update();", + " }", + " }", + " for (let i = 0; i < this.particleNum; i++) {", + " const particle = this.particles[i];", + " if (particle.died && (!(particle instanceof TrailParticle) || particle.previous.length === 0)) {", + " this.particles[i] = this.particles[this.particleNum - 1];", + " this.particles[this.particleNum - 1] = particle;", + " this.particleNum--;", + " i--;", + " }", + " }", + " }", + " emit(delta, emissionState, emitterMatrix) {", + " if (emissionState.time > this.duration) {", + " if (this.looping) {", + " emissionState.time -= this.duration;", + " }", + " else {", + " if (!this.emitEnded) {", + " this.endEmit();", + " }", + " }", + " }", + " this.normalMatrix.getNormalMatrix(emitterMatrix);", + " const context = {", + " signal: () => {", + " this.spawn(emissionState, emitterMatrix);", + " },", + " emissionState,", + " delta,", + " };", + " if (!this.emitEnded) {", + " this.interpreter.run(this.emissionGraph, context);", + " }", + " if (this.previousWorldPos === undefined)", + " this.previousWorldPos = new THREE.Vector3();", + " this.emitter.getWorldPosition(this.previousWorldPos);", + " emissionState.time += delta;", + " }", + " toJSON(meta, options = {}) {", + " return {};", + " }", + " getRendererSettings() {", + " return this.rendererSettings;", + " }", + " clone() {", + " return this;", + " }", + "}", + "", + "gdjs.__particleEmmiter3DExtension = {", + " ParticleEmitter3DRenderer,", + " ParticleEmitterAdapter,", + " ParticleEmitterHelper,", + "", + " ApplyCollision,", + " ApplyForce,", + " ApplySequences,", + " AxisAngleGenerator,", + " BatchedParticleRenderer,", + " BatchedRenderer,", + " BehaviorFromJSON,", + " BehaviorTypes,", + " Bezier,", + " ChangeEmitDirection,", + " ColorGeneratorFromJSON,", + " ColorOverLife,", + " ColorRange,", + " ConeEmitter,", + " ConstantColor,", + " ConstantValue,", + " DonutEmitter,", + " EmitSubParticleSystem,", + " EmitterFromJSON,", + " EmitterMode,", + " EmitterShapes,", + " EulerGenerator,", + " ForceOverLife,", + " FrameOverLife,", + " GeneratorFromJSON,", + " Gradient,", + " GraphNodeType,", + " GravityForce,", + " GridEmitter,", + " Interpreter,", + " IntervalValue,", + " MeshSurfaceEmitter,", + " Node,", + " NodeGraph,", + " NodeType,", + " NodeTypes,", + " NodeValueType,", + " Noise,", + " OrbitOverLife,", + " ParticleEmitter,", + " ParticleSystem,", + " PiecewiseBezier,", + " PiecewiseFunction,", + " Plugins,", + " PointEmitter,", + " QuarksLoader,", + " RandomColor,", + " RandomColorBetweenGradient,", + " RandomQuatGenerator,", + " RecordState,", + " RenderMode,", + " Rotation3DOverLife,", + " RotationGeneratorFromJSON,", + " RotationOverLife,", + " SequencerFromJSON,", + " SizeOverLife,", + " SpeedOverLife,", + " SphereEmitter,", + " SpriteBatch,", + " SpriteParticle,", + " SubParticleEmitMode,", + " TextureSequencer,", + " TrailBatch,", + " TrailParticle,", + " TurbulenceField,", + " VFXBatch,", + " ValueGeneratorFromJSON,", + " WidthOverLength,", + " Wire,", + " genDefaultForNodeValueType,", + " getPhysicsResolver,", + " loadPlugin,", + " setPhysicsResolver,", + " unloadPlugin,", + "}" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "onScenePreEvents", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "// See doStepPostEvents\r", + "runtimeScene.__particleEmmiter3DExtension = runtimeScene.__particleEmmiter3DExtension || {};\r", + "runtimeScene.__particleEmmiter3DExtension.emittersStepped = 0;" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "DefineHelperClasses" + }, + { + "functionName": "onScenePreEvents" + } + ] + }, + "eventsBasedBehaviors": [], + "eventsBasedObjects": [ + { + "areaMaxX": 64, + "areaMaxY": 64, + "areaMaxZ": 64, + "areaMinX": 0, + "areaMinY": 0, + "areaMinZ": 0, + "assetStoreTag": "3d particles", + "defaultName": "ParticleEmitter", + "description": "Display a large number of particles to create visual effects.", + "fullName": "3D particle emitter", + "helpPath": "", + "iconUrl": "", + "is3D": true, + "isUsingLegacyInstancesRenderer": true, + "name": "ParticleEmitter3D", + "previewIconUrl": "", + "objects": [ + { + "adaptCollisionMaskAutomatically": true, + "assetStoreId": "", + "name": "Particle", + "type": "Sprite", + "updateIfNotVisible": false, + "variables": [], + "effects": [], + "behaviors": [], + "animations": [ + { + "name": "Image", + "useMultipleDirections": false, + "directions": [ + { + "looping": false, + "timeBetweenFrames": 0.08, + "sprites": [] + } + ] + } + ] + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "objectName": "Particle" + } + ] + }, + "objectsGroups": [], + "layers": [ + { + "ambientLightColorB": 200, + "ambientLightColorG": 200, + "ambientLightColorR": 200, + "camera2DPlaneMaxDrawingDistance": 5000, + "camera3DFarPlaneDistance": 10000, + "camera3DFieldOfView": 45, + "camera3DNearPlaneDistance": 3, + "cameraType": "", + "followBaseLayerCamera": false, + "isLightingLayer": false, + "isLocked": false, + "name": "", + "renderingType": "", + "visibility": true, + "cameras": [ + { + "defaultSize": true, + "defaultViewport": true, + "height": 0, + "viewportBottom": 1, + "viewportLeft": 0, + "viewportRight": 1, + "viewportTop": 0, + "width": 0 + } + ], + "effects": [] + } + ], + "instances": [], + "editionSettings": [], + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "onCreated", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ParticleEmitter3D::DefineHelperClasses" + }, + "parameters": [ + "", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const {", + " ParticleEmitterAdapter,", + " ParticleEmitter3DRenderer,", + " ParticleEmitterHelper,", + "", + " ParticleSystem,", + " IntervalValue,", + " ConstantValue,", + " ConstantColor,", + " ColorOverLife,", + " SizeOverLife,", + " ApplyForce,", + " WidthOverLength,", + " Gradient,", + " PiecewiseBezier,", + " Bezier,", + " PointEmitter,", + " ConeEmitter,", + " RenderMode", + "} = gdjs.__particleEmmiter3DExtension;", + "", + "/** @type {gdjs.CustomRuntimeObject} */", + "const object = objects[0];", + "// Force the size of the object because it doesn't contain any instance.", + "object._innerArea = {", + " min: [-16, -16, -16],", + " max: [16, 16, 16],", + " };", + "const hitbox = new gdjs.Polygon();", + "hitbox.vertices = [[-16, -16], [16, -16], [16, 16], [-16, 16]];", + "object._untransformedHitBoxes = [hitbox];", + "object._unrotatedAABB.min[0] = -16;", + "object._unrotatedAABB.min[1] = -16;", + "object._unrotatedAABB.max[0] = 16;", + "object._unrotatedAABB.max[1] = 16;", + "object._updateUntransformedHitBoxes = () => {};", + "", + "// Here runtimeScene is the gdjs.CustomRuntimeObjectInstanceContainer inside the custom object.", + "const gameScene = object.getRuntimeScene();", + "const game = runtimeScene.getGame();", + "", + "const texture = game.getImageManager().getThreeTexture('');", + "", + "// Set the blending here because changes are not applied after the emitter creation.", + "const blendingString = object._getBlending();", + "const blending =", + " blendingString === \"Additive\" ? THREE.AdditiveBlending :", + " blendingString === \"Normal\" ? THREE.NormalBlending :", + " blendingString === \"Subtractive\" ? THREE.SubtractiveBlending :", + " blendingString === \"Multiply\" ? THREE.MultiplyBlending :", + " blendingString === \"None\" ? THREE.NoBlending :", + " THREE.AdditiveBlending;", + "", + "", + "// Build a configuration with the right kind of objects.", + "// These values are not important as they are overrided by the object properties values.", + "const muzzle = {", + " duration: 10,", + " looping: false,", + " startLife: new IntervalValue(1, 2),", + " startSpeed: new IntervalValue(100, 200),", + " startSize: new IntervalValue(20, 50),", + " startColor: new ConstantColor(new THREE.Vector4(1, 1, 1, 1)),", + " worldSpace: true,", + "", + " maxParticle: 5,", + " emissionOverTime: new ConstantValue(50),", + " emissionBursts: [{", + " time: 0,", + " count: new ConstantValue(1),", + " cycle: 1,", + " interval: 0.01,", + " probability: 1,", + " }],", + "", + " shape: new PointEmitter(),", + " material: new THREE.MeshBasicMaterial({", + " map: texture,", + " blending: blending,", + " transparent: true,", + " side: THREE.DoubleSide", + " }),", + " startTileIndex: 0,", + " uTileCount: 1,", + " vTileCount: 1,", + " renderOrder: 2,", + " renderMode: RenderMode.BillBoard", + "};", + "const particleSystem = new ParticleSystem(muzzle);", + "", + "const colorOverLife = new ColorOverLife(", + " new Gradient(", + " [", + " [new THREE.Vector3(1, 0, 0), 0],", + " [new THREE.Vector3(1, 0, 0), 1],", + " ],", + " [", + " [1, 0],", + " [1, 1],", + " ]", + " ));", + "particleSystem.addBehavior(colorOverLife);", + "const sizeOverLife = new SizeOverLife(new PiecewiseBezier([[new Bezier(1, 2 / 3, 1 / 3, 0), 0]]));", + "particleSystem.addBehavior(sizeOverLife);", + "const applyForce = new ApplyForce(new THREE.Vector3(0, 0, -1), new ConstantValue(0));", + "particleSystem.addBehavior(applyForce);", + "const widthOverLength = new WidthOverLength(new PiecewiseBezier([[new Bezier(1, 2 / 3, 1 / 3, 0), 0]]));", + "particleSystem.addBehavior(widthOverLength);", + "", + "particleSystem.emitter.name = object.getName() + object.getNameId();", + "", + "const inverseWorldScale = gameScene.getRenderer3DInverseWorldScale ? gameScene.getRenderer3DInverseWorldScale() : 1;", + "object.__particleEmitterAdapter = new ParticleEmitterAdapter(inverseWorldScale, particleSystem, colorOverLife, sizeOverLife, applyForce, widthOverLength);", + "object.__particleSystem = particleSystem;", + "", + "// This is a hack that may break in future releases.", + "// Replace the group that would hold children objects by the emmiter.", + "const layer = object.getInstanceContainer().getLayer(object.getLayer());", + "const group = object.getRenderer()._threeGroup;", + "layer.getRenderer().remove3DRendererObject(group);", + "particleSystem.emitter.position.copy(group.position);", + "particleSystem.emitter.rotation.order = 'ZYX';", + "particleSystem.emitter.rotation.copy(group.rotation);", + "", + "const particleEmitter3DRenderer = new ParticleEmitter3DRenderer(object, object._instanceContainer, object.getInstanceContainer());", + "object._renderer = particleEmitter3DRenderer;", + "if (game.isInGameEdition && game.isInGameEdition()) {", + " const particleEmitterHelper = new ParticleEmitterHelper(object);", + " particleEmitter3DRenderer._threeGroup = particleEmitterHelper;", + " layer.getRenderer().add3DRendererObject(particleEmitterHelper);", + "}", + "else {", + " particleEmitter3DRenderer._threeGroup = particleSystem.emitter;", + " layer.getRenderer().add3DRendererObject(particleSystem.emitter);", + "}", + "", + "particleSystem.emitter.updateMatrixWorld(true);", + "", + "", + "// See doStepPostEvents", + "gameScene.__particleEmmiter3DExtension = gameScene.__particleEmmiter3DExtension || {};", + "gameScene.__particleEmmiter3DExtension.emittersCount = gameScene.__particleEmmiter3DExtension.emittersCount || 0;", + "gameScene.__particleEmmiter3DExtension.emittersCount++;", + "", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::UpdateFromProperties" + }, + "parameters": [ + "Object", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetRotationCenter" + }, + "parameters": [ + "Object", + "0", + "0", + "0" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "onDestroy", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "/** @type {gdjs.CustomRuntimeObject} */", + "const object = objects[0];", + "// Here runtimeScene is the gdjs.CustomRuntimeObjectInstanceContainer inside the custom object.", + "const gameScene = object.getRuntimeScene();", + "", + "object.__particleSystem.dispose();", + "", + "// See doStepPostEvents", + "gameScene.__particleEmmiter3DExtension.emittersCount--;", + "", + "if (gameScene.__particleEmmiter3DExtension.emittersCount === 0) {", + " // Update batch system now because doStepPostEvents won't be called.", + " gameScene.__particleEmmiter3DExtension.layerNames = gameScene.__particleEmmiter3DExtension.layerNames || [];", + " const layerNames = gameScene.__particleEmmiter3DExtension.layerNames;", + " gameScene.getAllLayerNames(layerNames);", + " for (const layerName of layerNames) {", + " const layer = gameScene.getLayer(layerName);", + " if (layer.__particleEmmiter3DExtension) {", + " layer.__particleEmmiter3DExtension.batchSystem.update(layer.getElapsedTime() / 1000);", + " }", + " }", + "}" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "onHotReloading", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::UpdateFromProperties" + }, + "parameters": [ + "Object", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Update from properties.", + "fullName": "Update from properties", + "functionType": "Action", + "name": "UpdateFromProperties", + "private": true, + "sentence": "Update from properties of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetZ" + }, + "parameters": [ + "Object", + "=", + "Object.Z()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetRotationX" + }, + "parameters": [ + "Object", + "=", + "Object.PropertyRotationX()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetRotationY" + }, + "parameters": [ + "Object", + "=", + "Object.PropertyRotationY()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetRenderMode" + }, + "parameters": [ + "Object", + "=", + "RenderMode", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetTrailStartLengthMin" + }, + "parameters": [ + "Object", + "=", + "TrailStartLengthMin", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetTrailStartLengthMax" + }, + "parameters": [ + "Object", + "=", + "TrailStartLengthMax", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetTrailEndWidthRatio" + }, + "parameters": [ + "Object", + "=", + "TrailEndWidthRatio", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetStartColor" + }, + "parameters": [ + "Object", + "=", + "Object.StartColor()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetEndColor" + }, + "parameters": [ + "Object", + "=", + "Object.EndColor()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetStartOpacity" + }, + "parameters": [ + "Object", + "=", + "Object.StartOpacity()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetEndOpacity" + }, + "parameters": [ + "Object", + "=", + "Object.EndOpacity()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetFlow" + }, + "parameters": [ + "Object", + "=", + "Object.Flow()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetStartSizeMin" + }, + "parameters": [ + "Object", + "=", + "Object.StartSizeMin()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetStartSizeMax" + }, + "parameters": [ + "Object", + "=", + "Object.StartSizeMax()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetEndScale" + }, + "parameters": [ + "Object", + "=", + "Object.EndScale()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetStartSpeedMin" + }, + "parameters": [ + "Object", + "=", + "Object.StartSpeedMin()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetStartSpeedMax" + }, + "parameters": [ + "Object", + "=", + "Object.StartSpeedMax()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetLifespanMin" + }, + "parameters": [ + "Object", + "=", + "Object.LifespanMin()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetLifespanMax" + }, + "parameters": [ + "Object", + "=", + "Object.LifespanMax()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetDuration" + }, + "parameters": [ + "Object", + "=", + "Object.Duration()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetSpayConeAngle" + }, + "parameters": [ + "Object", + "=", + "Object.SpayConeAngle()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetGravity" + }, + "parameters": [ + "Object", + "=", + "Object.Gravity()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetGravityTop" + }, + "parameters": [ + "Object", + "=", + "Object.GravityTop()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::UpdateImage" + }, + "parameters": [ + "Object", + "" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "BooleanVariable" + }, + "parameters": [ + "IsTrailFollowingLocalOrigin", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetIsTrailFollowingLocalOrigin" + }, + "parameters": [ + "Object", + "=", + "TrailStartLengthMax" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsTrailFollowingLocalOrigin", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetIsTrailFollowingLocalOrigin" + }, + "parameters": [ + "Object", + "yes", + "TrailStartLengthMax" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "BooleanVariable" + }, + "parameters": [ + "AreParticlesRelative", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetAreParticlesRelative" + }, + "parameters": [ + "Object", + "no", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "AreParticlesRelative", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetAreParticlesRelative" + }, + "parameters": [ + "Object", + "yes", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "TODO: Blending can't be changed." + }, + { + "disabled": true, + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetBlending" + }, + "parameters": [ + "Object", + "=", + "Object.Blending()", + "" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::UpdateHelper" + }, + "parameters": [ + "Object", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "Update helper", + "functionType": "Action", + "name": "UpdateHelper", + "private": true, + "sentence": "Update graphical helper of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const game = runtimeScene.getGame();", + "if (game.isInGameEdition && game.isInGameEdition()) {", + " const particleEmitterHelper = objects[0].get3DRendererObject();", + " particleEmitterHelper.update();", + "}" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "Update particle image", + "functionType": "Action", + "name": "UpdateImage", + "private": true, + "sentence": "Update particle image of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "/** @type {gdjs.CustomRuntimeObject3D} */\r", + "const object = objects[0];\r", + "/** @type {SpriteObjectDataType} */\r", + "const particleSpriteData = object._instanceContainer._objects.get(\"Particle\");\r", + "/** @type {gdjs.SpriteAnimationData} */\r", + "const animation = particleSpriteData.animations[0];\r", + "const animationFrame = animation ? animation.directions[0].sprites[0] : null;\r", + "const resourceName = animationFrame ? animationFrame.image : '';\r", + "object.__particleEmitterAdapter.setImage(resourceName);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "doStepPostEvents", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::HasEnded" + }, + "parameters": [ + "Object", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::Delete" + }, + "parameters": [ + "Object", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "ParticleEmitter3D::ParticleEmitter3D::HasEnded" + }, + "parameters": [ + "Object", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::RegisterInLayer" + }, + "parameters": [ + "Object", + "" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "/** @type {gdjs.CustomRuntimeObject3D} */", + "const object = objects[0];", + "// Here runtimeScene is the gdjs.CustomRuntimeObjectInstanceContainer inside the custom object.", + "const gameScene = object.getRuntimeScene();", + "", + "// Update batch system after having moved every emitter.", + "// See onScenePreEvents", + "gameScene.__particleEmmiter3DExtension.emittersStepped++;", + "if (gameScene.__particleEmmiter3DExtension.emittersStepped === gameScene.__particleEmmiter3DExtension.emittersCount) {", + " gameScene.__particleEmmiter3DExtension.layerNames = gameScene.__particleEmmiter3DExtension.layerNames || [];", + " const layerNames = gameScene.__particleEmmiter3DExtension.layerNames;", + " gameScene.getAllLayerNames(layerNames);", + " for (const layerName of layerNames) {", + " const layer = gameScene.getLayer(layerName);", + " if (layer.__particleEmmiter3DExtension) {", + " const timeDelta = layer.getElapsedTime() / 1000;", + " if (timeDelta > 0) {", + " layer.__particleEmmiter3DExtension.batchSystem.update(timeDelta);", + " }", + " }", + " }", + "}" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "Register in layer", + "functionType": "Action", + "name": "RegisterInLayer", + "private": true, + "sentence": "Register _PARAM0_ in layer", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "/** @type {gdjs.CustomRuntimeObject} */", + "const object = objects[0];", + "", + "// TODO Handle layer changes?", + "if (object.__emitterLayerName === undefined) {", + " // Here runtimeScene is the gdjs.CustomRuntimeObjectInstanceContainer inside the custom object.", + " const gameScene = object.getRuntimeScene();", + "", + " let rootObject = object;", + " while (rootObject.getInstanceContainer().getOwner) {", + " rootObject = rootObject.getInstanceContainer().getOwner();", + " }", + "", + " const layer = gameScene.getLayer(rootObject.getLayer());", + " layer.__particleEmmiter3DExtension = layer.__particleEmmiter3DExtension || {};", + " if (!layer.__particleEmmiter3DExtension.batchSystem) {", + " const batchSystem = new gdjs.__particleEmmiter3DExtension.BatchedRenderer();", + " const worldScale = gameScene.getRenderer3DWorldScale ? gameScene.getRenderer3DWorldScale() : 1;", + " batchSystem.scale.set(worldScale, -worldScale, worldScale);", + " const threeScene = layer.getRenderer().getThreeScene();", + " if (threeScene) {", + " threeScene.add(batchSystem);", + " }", + " layer.__particleEmmiter3DExtension.batchSystem = batchSystem;", + " }", + " layer.__particleEmmiter3DExtension.batchSystem.addSystem(object.__particleSystem);", + " object.__emitterLayerName = layer.getName();", + "}" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Delete itself", + "fullName": "Delete itself", + "functionType": "Action", + "name": "Delete", + "private": true, + "sentence": "Delete _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "", + "object.deleteFromScene(object.getParent());", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Check that emission has ended and no particle is alive anymore.", + "fullName": "Emission has ended", + "functionType": "Condition", + "name": "HasEnded", + "sentence": "Emission from _PARAM0_ has ended", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "\r", + "eventsFunctionContext.returnValue =\r", + " object._getShouldAutodestruct()\r", + " && object.__particleSystem.emitEnded\r", + " && object.__particleSystem.particleNum === 0;\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Restart particule emission from the beginning.", + "fullName": "Restart", + "functionType": "Action", + "name": "Restart", + "sentence": "Restart particule emission from _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "/** @type {gdjs.CustomRuntimeObject} */\r", + "const object = objects[0];\r", + "\r", + "object.__particleSystem.restart();\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the Z position of the emitter.", + "fullName": "Z elevaltion (deprecated)", + "functionType": "ExpressionAndCondition", + "group": "Position", + "name": "Z", + "private": true, + "sentence": "the Z position", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Object.PropertyZ()" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "Z", + "group": "Position", + "name": "SetZ", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Z", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the rotation on X axis of the emitter.", + "fullName": "Rotation on X axis (deprecated)", + "functionType": "ExpressionAndCondition", + "group": "Angle", + "name": "RotationX", + "private": true, + "sentence": "the rotation on X axis", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Object.PropertyRotationX()" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "RotationX", + "group": "Angle", + "name": "SetRotationX", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "RotationX", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "\r", + "object.__particleSystem.emitter.rotation.x = eventsFunctionContext.getArgument(\"Value\") * Math.PI / 180;" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the rotation on Y axis of the emitter.", + "fullName": "Rotation on Y axis (deprecated)", + "functionType": "ExpressionAndCondition", + "group": "Angle", + "name": "RotationY", + "private": true, + "sentence": "the rotation on Y axis", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Object.PropertyRotationY()" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "RotationY", + "group": "Angle", + "name": "SetRotationY", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "RotationY", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "\r", + "object.__particleSystem.emitter.rotation.y = (90 + eventsFunctionContext.getArgument(\"Value\")) * Math.PI / 180;" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the start color of the object.", + "fullName": "Start color", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter color configuration", + "name": "StartColor", + "sentence": "the start color", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnString" + }, + "parameters": [ + "StartColor" + ] + } + ] + } + ], + "expressionType": { + "type": "color" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "StartColor", + "group": "3D particle emitter color configuration", + "name": "SetStartColor", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "StartColor", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const startColor = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setStartColor(startColor);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the end color of the object.", + "fullName": "End color", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter color configuration", + "name": "EndColor", + "sentence": "the end color", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnString" + }, + "parameters": [ + "EndColor" + ] + } + ] + } + ], + "expressionType": { + "type": "color" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "EndColor", + "group": "3D particle emitter color configuration", + "name": "SetEndColor", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "EndColor", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const endColor = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setEndColor(endColor);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the start opacity of the object.", + "fullName": "Start opacity", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter color configuration", + "name": "StartOpacity", + "sentence": "the start opacity", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "StartOpacity" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "StartOpacity", + "group": "3D particle emitter color configuration", + "name": "SetStartOpacity", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "StartOpacity", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const startOpacity = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setStartOpacity(startOpacity);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the end opacity of the object.", + "fullName": "End opacity", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter color configuration", + "name": "EndOpacity", + "sentence": "the end opacity", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "EndOpacity" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "EndOpacity", + "group": "3D particle emitter color configuration", + "name": "SetEndOpacity", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "EndOpacity", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const endOpacity = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setEndOpacity(endOpacity);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the flow of particles of the object (particles per second).", + "fullName": "Flow of particles", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter configuration", + "name": "Flow", + "sentence": "the flow of particles", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Flow" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "Flow", + "group": "3D particle emitter configuration", + "name": "SetFlow", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Flow", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const flow = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setFlow(flow);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the start min size of the object.", + "fullName": "Start min size", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter configuration", + "name": "StartSizeMin", + "sentence": "the start min size", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "StartSizeMin" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "StartSizeMin", + "group": "3D particle emitter configuration", + "name": "SetStartSizeMin", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "StartSizeMin", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const startMinSize = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setStartMinSize(startMinSize);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the start max size of the object.", + "fullName": "Start max size", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter configuration", + "name": "StartSizeMax", + "sentence": "the start max size", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "StartSizeMax" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "StartSizeMax", + "group": "3D particle emitter configuration", + "name": "SetStartSizeMax", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "StartSizeMax", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const startMaxSize = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setStartMaxSize(startMaxSize);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the end scale of the object.", + "fullName": "End scale", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter configuration", + "name": "EndScale", + "sentence": "the end scale", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "EndScale" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "EndScale", + "group": "3D particle emitter configuration", + "name": "SetEndScale", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "EndScale", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const endScale = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setEndScale(endScale);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the min start speed of the object.", + "fullName": "Min start speed", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter speed configuration", + "name": "StartSpeedMin", + "sentence": "the min start speed", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "StartSpeedMin" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "StartSpeedMin", + "group": "3D particle emitter speed configuration", + "name": "SetStartSpeedMin", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "StartSpeedMin", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const startSpeedMin = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setStartSpeedMin(startSpeedMin);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the max start speed of the object.", + "fullName": "Max start speed", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter speed configuration", + "name": "StartSpeedMax", + "sentence": "the max start speed", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "StartSpeedMax" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "StartSpeedMax", + "group": "3D particle emitter speed configuration", + "name": "SetStartSpeedMax", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "StartSpeedMax", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const startSpeedMax = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setStartSpeedMax(startSpeedMax);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the min lifespan of the object.", + "fullName": "Min lifespan", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter configuration", + "name": "LifespanMin", + "sentence": "the min lifespan", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "LifespanMin" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "LifespanMin", + "group": "3D particle emitter configuration", + "name": "SetLifespanMin", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "LifespanMin", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const lifespanMin = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setLifespanMin(lifespanMin);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the max lifespan of the object.", + "fullName": "Max lifespan", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter configuration", + "name": "LifespanMax", + "sentence": "the max lifespan", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "LifespanMax" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "LifespanMax", + "group": "3D particle emitter configuration", + "name": "SetLifespanMax", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "LifespanMax", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const lifespanMax = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setLifespanMax(lifespanMax);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the emission duration of the object.", + "fullName": "Emission duration", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter configuration", + "name": "Duration", + "sentence": "the emission duration", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Duration" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "Duration", + "group": "3D particle emitter configuration", + "name": "SetDuration", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Duration", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const duration = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setDuration(duration);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Check if particles move with the emitter.", + "fullName": "Particles move with the emitter", + "functionType": "Condition", + "group": "3D particle emitter speed configuration", + "name": "AreParticlesRelative", + "sentence": "_PARAM0_ particles move with the emitter", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "AreParticlesRelative", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Change if particles move with the emitter.", + "fullName": "Particles move with the emitter", + "functionType": "Action", + "group": "3D particle emitter speed configuration", + "name": "SetAreParticlesRelative", + "sentence": "_PARAM0_ particles move with the emitter: _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "AreParticlesRelative", + "False", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "AreParticlesRelative", + "True", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const areParticlesRelative = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setParticlesRelative(areParticlesRelative);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + }, + { + "defaultValue": "yes", + "description": "AreParticlesRelative", + "name": "Value", + "optional": true, + "type": "yesorno" + } + ], + "objectGroups": [] + }, + { + "description": "the spay cone angle of the object.", + "fullName": "Spay cone angle", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter configuration", + "name": "SpayConeAngle", + "sentence": "the spay cone angle", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "SpayConeAngle" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "SpayConeAngle", + "group": "3D particle emitter configuration", + "name": "SetSpayConeAngle", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "SpayConeAngle", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const sprayConeAngle = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setSprayConeAngle(sprayConeAngle);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the blending of the object.", + "fullName": "Blending", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter color configuration", + "name": "Blending", + "sentence": "the blending", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnString" + }, + "parameters": [ + "Blending" + ] + } + ] + } + ], + "expressionType": { + "supplementaryInformation": "[\"Normal\",\"Additive\",\"Substractive\",\"Multiply\",\"None\"]", + "type": "stringWithSelector" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "Blending", + "group": "3D particle emitter color configuration", + "name": "SetBlending", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Blending", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const blending = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setBlending(blending);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the gravity top of the object.", + "fullName": "Gravity top", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter speed configuration", + "name": "GravityTop", + "sentence": "the gravity top", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnString" + }, + "parameters": [ + "GravityTop" + ] + } + ] + } + ], + "expressionType": { + "supplementaryInformation": "[\"Y-\",\"Z+\"]", + "type": "stringWithSelector" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "GravityTop", + "group": "3D particle emitter speed configuration", + "name": "SetGravityTop", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "GravityTop", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const gravityTop = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setGravityTop(gravityTop);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the gravity of the object.", + "fullName": "Gravity", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter speed configuration", + "name": "Gravity", + "sentence": "the gravity", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Gravity" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "Gravity", + "group": "3D particle emitter speed configuration", + "name": "SetGravity", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Gravity", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const gravity = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setGravity(gravity);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Check if delete when emission ends.", + "fullName": "Delete when emission ends", + "functionType": "Condition", + "group": "3D particle emitter configuration", + "name": "ShouldAutodestruct", + "sentence": "_PARAM0_ delete when emission ends", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "ShouldAutodestruct", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Change if delete when emission ends.", + "fullName": "Delete when emission ends", + "functionType": "Action", + "group": "3D particle emitter configuration", + "name": "SetShouldAutodestruct", + "sentence": "_PARAM0_ delete when emission ends: _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "ShouldAutodestruct", + "False", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "ShouldAutodestruct", + "True", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + }, + { + "defaultValue": "yes", + "description": "ShouldAutodestruct", + "name": "Value", + "optional": true, + "type": "yesorno" + } + ], + "objectGroups": [] + }, + { + "description": "the start min trail length of the object.", + "fullName": "Start min trail length", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter trail configuration", + "name": "TrailStartLengthMin", + "sentence": "the start min trail length", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "TrailStartLengthMin" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "TrailStartLengthMin", + "group": "3D particle emitter trail configuration", + "name": "SetTrailStartLengthMin", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TrailStartLengthMin", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setTrailStartLengthMin(value);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the start max trail length of the object.", + "fullName": "Start max trail length", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter trail configuration", + "name": "TrailStartLengthMax", + "sentence": "the start max trail length", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "TrailStartLengthMax" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "TrailStartLengthMax", + "group": "3D particle emitter trail configuration", + "name": "SetTrailStartLengthMax", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TrailStartLengthMax", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setTrailStartLengthMax(value);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Check if the trail should follow the object.", + "fullName": "Trail following the object", + "functionType": "Condition", + "group": "3D particle emitter trail configuration", + "name": "IsTrailFollowingLocalOrigin", + "sentence": "The trail is following _PARAM0_ ", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsTrailFollowingLocalOrigin", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Change if the trail should follow the object or not.", + "fullName": "Make the trail follow", + "functionType": "Action", + "group": "3D particle emitter trail configuration", + "name": "SetIsTrailFollowingLocalOrigin", + "sentence": "Make the trail follow _PARAM0_: _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "False", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "IsTrailFollowingLocalOrigin", + "False", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "IsTrailFollowingLocalOrigin", + "True", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setTrailFollowingLocalOrigin(value);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + }, + { + "defaultValue": "yes", + "description": "IsTrailFollowingLocalOrigin", + "name": "Value", + "optional": true, + "type": "yesorno" + } + ], + "objectGroups": [] + }, + { + "description": "the tail end width ratio of the object.", + "fullName": "Tail end width ratio", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter trail configuration", + "name": "TrailEndWidthRatio", + "sentence": "the tail end width ratio", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "TrailEndWidthRatio" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "TrailEndWidthRatio", + "group": "3D particle emitter trail configuration", + "name": "SetTrailEndWidthRatio", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TrailEndWidthRatio", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setTrailEndWidthRatio(value);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the render mode of the object.", + "fullName": "Render mode", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter configuration", + "name": "RenderMode", + "private": true, + "sentence": "the render mode", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnString" + }, + "parameters": [ + "RenderMode" + ] + } + ] + } + ], + "expressionType": { + "supplementaryInformation": "[\"Billboard\",\"Trail\"]", + "type": "stringWithSelector" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "RenderMode", + "group": "3D particle emitter configuration", + "name": "SetRenderMode", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "RenderMode", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setRenderMode(value);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Update the trail properties because the RenderMode setter reset them" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "RenderMode", + "=", + "\"Trail\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetTrailStartLengthMin" + }, + "parameters": [ + "Object", + "=", + "TrailStartLengthMin", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetTrailStartLengthMax" + }, + "parameters": [ + "Object", + "=", + "TrailStartLengthMax", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "onCreated" + }, + { + "functionName": "onDestroy" + }, + { + "functionName": "onHotReloading" + }, + { + "functionName": "UpdateFromProperties" + }, + { + "functionName": "UpdateHelper" + }, + { + "functionName": "UpdateImage" + }, + { + "functionName": "doStepPostEvents" + }, + { + "functionName": "RegisterInLayer" + }, + { + "functionName": "Delete" + }, + { + "functionName": "HasEnded" + }, + { + "functionName": "Restart" + }, + { + "folderName": "Position", + "children": [ + { + "functionName": "Z" + }, + { + "functionName": "SetZ" + } + ] + }, + { + "folderName": "Angle", + "children": [ + { + "functionName": "RotationX" + }, + { + "functionName": "SetRotationX" + }, + { + "functionName": "RotationY" + }, + { + "functionName": "SetRotationY" + } + ] + }, + { + "folderName": "3D particle emitter color configuration", + "children": [ + { + "functionName": "StartColor" + }, + { + "functionName": "SetStartColor" + }, + { + "functionName": "EndColor" + }, + { + "functionName": "SetEndColor" + }, + { + "functionName": "StartOpacity" + }, + { + "functionName": "SetStartOpacity" + }, + { + "functionName": "EndOpacity" + }, + { + "functionName": "SetEndOpacity" + }, + { + "functionName": "Blending" + }, + { + "functionName": "SetBlending" + } + ] + }, + { + "folderName": "3D particle emitter configuration", + "children": [ + { + "functionName": "Flow" + }, + { + "functionName": "SetFlow" + }, + { + "functionName": "StartSizeMin" + }, + { + "functionName": "SetStartSizeMin" + }, + { + "functionName": "StartSizeMax" + }, + { + "functionName": "SetStartSizeMax" + }, + { + "functionName": "EndScale" + }, + { + "functionName": "SetEndScale" + }, + { + "functionName": "LifespanMin" + }, + { + "functionName": "SetLifespanMin" + }, + { + "functionName": "LifespanMax" + }, + { + "functionName": "SetLifespanMax" + }, + { + "functionName": "Duration" + }, + { + "functionName": "SetDuration" + }, + { + "functionName": "SpayConeAngle" + }, + { + "functionName": "SetSpayConeAngle" + }, + { + "functionName": "ShouldAutodestruct" + }, + { + "functionName": "SetShouldAutodestruct" + }, + { + "functionName": "RenderMode" + }, + { + "functionName": "SetRenderMode" + } + ] + }, + { + "folderName": "3D particle emitter speed configuration", + "children": [ + { + "functionName": "StartSpeedMin" + }, + { + "functionName": "SetStartSpeedMin" + }, + { + "functionName": "StartSpeedMax" + }, + { + "functionName": "SetStartSpeedMax" + }, + { + "functionName": "AreParticlesRelative" + }, + { + "functionName": "SetAreParticlesRelative" + }, + { + "functionName": "GravityTop" + }, + { + "functionName": "SetGravityTop" + }, + { + "functionName": "Gravity" + }, + { + "functionName": "SetGravity" + } + ] + }, + { + "folderName": "3D particle emitter trail configuration", + "children": [ + { + "functionName": "TrailStartLengthMin" + }, + { + "functionName": "SetTrailStartLengthMin" + }, + { + "functionName": "TrailStartLengthMax" + }, + { + "functionName": "SetTrailStartLengthMax" + }, + { + "functionName": "IsTrailFollowingLocalOrigin" + }, + { + "functionName": "SetIsTrailFollowingLocalOrigin" + }, + { + "functionName": "TrailEndWidthRatio" + }, + { + "functionName": "SetTrailEndWidthRatio" + } + ] + } + ] + }, + "propertyDescriptors": [ + { + "value": "255;0;0", + "type": "Color", + "label": "Start color", + "group": "Color", + "name": "StartColor" + }, + { + "value": "255;255;0", + "type": "Color", + "label": "End color", + "group": "Color", + "name": "EndColor" + }, + { + "value": "255", + "type": "Number", + "unit": "Dimensionless", + "label": "Start opacity", + "group": "Color", + "name": "StartOpacity" + }, + { + "value": "0", + "type": "Number", + "unit": "Dimensionless", + "label": "End opacity", + "group": "Color", + "name": "EndOpacity" + }, + { + "value": "50", + "type": "Number", + "label": "Flow of particles (particles per second)", + "name": "Flow" + }, + { + "value": "10", + "type": "Number", + "unit": "Pixel", + "label": "Start min size", + "group": "Size", + "name": "StartSizeMin" + }, + { + "value": "20", + "type": "Number", + "unit": "Pixel", + "label": "Start max size", + "group": "Size", + "name": "StartSizeMax" + }, + { + "value": "0", + "type": "Number", + "unit": "Dimensionless", + "label": "End scale", + "group": "Size", + "name": "EndScale" + }, + { + "value": "100", + "type": "Number", + "unit": "PixelSpeed", + "label": "Start min speed", + "group": "Speed", + "name": "StartSpeedMin" + }, + { + "value": "100", + "type": "Number", + "unit": "PixelSpeed", + "label": "Start max speed", + "group": "Speed", + "name": "StartSpeedMax" + }, + { + "value": "1", + "type": "Number", + "unit": "Second", + "label": "Min lifespan", + "name": "LifespanMin" + }, + { + "value": "2", + "type": "Number", + "unit": "Second", + "label": "Max lifespan", + "name": "LifespanMax" + }, + { + "value": "5", + "type": "Number", + "unit": "Second", + "label": "Emission duration", + "name": "Duration" + }, + { + "value": "", + "type": "Boolean", + "label": "Particles move with the emitter", + "group": "Speed", + "name": "AreParticlesRelative" + }, + { + "value": "30", + "type": "Number", + "unit": "DegreeAngle", + "label": "Spay cone angle", + "group": "Position", + "name": "SpayConeAngle" + }, + { + "value": "Additive", + "type": "Choice", + "label": "Blending", + "group": "Color", + "choices": [ + { + "label": "Normal", + "value": "Normal" + }, + { + "label": "Additive", + "value": "Additive" + }, + { + "label": "Subtractive", + "value": "Subtractive" + }, + { + "label": "Multiply", + "value": "Multiply" + }, + { + "label": "None", + "value": "None" + } + ], + "name": "Blending" + }, + { + "value": "Y-", + "type": "Choice", + "label": "Gravity top", + "group": "Speed", + "choices": [ + { + "label": "Y-", + "value": "Y-" + }, + { + "label": "Z+", + "value": "Z+" + } + ], + "name": "GravityTop" + }, + { + "value": "0", + "type": "Number", + "unit": "PixelAcceleration", + "label": "Gravity", + "group": "Speed", + "name": "Gravity" + }, + { + "value": "true", + "type": "Boolean", + "label": "Delete when emission ends", + "name": "ShouldAutodestruct" + }, + { + "value": "Center-center", + "type": "String", + "label": "", + "description": "Only used by the scene editor.", + "hidden": true, + "name": "ParentOrigin" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Z (elevation)", + "description": "Deprecated", + "group": "Position", + "hidden": true, + "name": "Z" + }, + { + "value": "0", + "type": "Number", + "unit": "DegreeAngle", + "label": "Rotation on X axis", + "group": "Position", + "hidden": true, + "name": "RotationX" + }, + { + "value": "0", + "type": "Number", + "unit": "DegreeAngle", + "label": "Rotation on Y axis", + "group": "Position", + "hidden": true, + "name": "RotationY" + }, + { + "value": "120", + "type": "Number", + "unit": "Pixel", + "label": "Start min length", + "group": "Trail", + "advanced": true, + "name": "TrailStartLengthMin" + }, + { + "value": "120", + "type": "Number", + "unit": "Pixel", + "label": "Start max length", + "group": "Trail", + "advanced": true, + "name": "TrailStartLengthMax" + }, + { + "value": "Billboard", + "type": "Choice", + "label": "Render mode", + "choices": [ + { + "label": "Image facing the camera", + "value": "Billboard" + }, + { + "label": "Image following a trail", + "value": "Trail" + } + ], + "advanced": true, + "name": "RenderMode" + }, + { + "value": "", + "type": "Boolean", + "label": "Follow the object", + "group": "Trail", + "advanced": true, + "name": "IsTrailFollowingLocalOrigin" + }, + { + "value": "0", + "type": "Number", + "unit": "Dimensionless", + "label": "Tail end width ratio", + "group": "Trail", + "advanced": true, + "name": "TrailEndWidthRatio" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "propertyName": "Flow" + }, + { + "propertyName": "LifespanMin" + }, + { + "propertyName": "LifespanMax" + }, + { + "propertyName": "Duration" + }, + { + "propertyName": "ShouldAutodestruct" + }, + { + "propertyName": "RenderMode" + }, + { + "folderName": "Color", + "children": [ + { + "propertyName": "StartColor" + }, + { + "propertyName": "EndColor" + }, + { + "propertyName": "StartOpacity" + }, + { + "propertyName": "EndOpacity" + }, + { + "propertyName": "Blending" + } + ] + }, + { + "folderName": "Size", + "children": [ + { + "propertyName": "StartSizeMin" + }, + { + "propertyName": "StartSizeMax" + }, + { + "propertyName": "EndScale" + } + ] + }, + { + "folderName": "Trail", + "children": [ + { + "propertyName": "TrailStartLengthMin" + }, + { + "propertyName": "TrailStartLengthMax" + }, + { + "propertyName": "TrailEndWidthRatio" + }, + { + "propertyName": "IsTrailFollowingLocalOrigin" + } + ] + }, + { + "folderName": "Speed", + "children": [ + { + "propertyName": "StartSpeedMin" + }, + { + "propertyName": "StartSpeedMax" + }, + { + "propertyName": "AreParticlesRelative" + }, + { + "propertyName": "GravityTop" + }, + { + "propertyName": "Gravity" + } + ] + }, + { + "folderName": "Position", + "children": [ + { + "propertyName": "SpayConeAngle" + }, + { + "propertyName": "Z" + }, + { + "propertyName": "RotationX" + }, + { + "propertyName": "RotationY" + } + ] + }, + { + "propertyName": "ParentOrigin" + } + ] + }, + "variants": [] + } + ] + }, + { + "author": "PANDAKO-GitHub", + "category": "Input", + "dimension": "", + "extensionNamespace": "", + "fullName": "Mouse Pointer Lock", + "gdevelopVersion": ">=5.5.222", + "helpPath": "", + "iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAyMy4wLjMsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iSWNvbnMiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgMzIgMzIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDMyIDMyOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KCS5zdDB7ZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9DQo8L3N0eWxlPg0KPHBvbHlsaW5lIGNsYXNzPSJzdDAiIHBvaW50cz0iMTksMTkgMjQsMTkgMjQsMjQgIi8+DQo8cG9seWxpbmUgY2xhc3M9InN0MCIgcG9pbnRzPSI2LDIzIDExLDIzIDExLDE4ICIvPg0KPHBhdGggY2xhc3M9InN0MCIgZD0iTTI0LDE5LjRjLTAuNywwLjgtMS40LDEuNi0yLjIsMi40Yy03LDctMTUuMywxMC4yLTE4LjUsN3MtMC4xLTExLjUsNy0xOC41czE1LjMtMTAuMiwxOC41LTcNCgljMS40LDEuNCwxLjYsMy42LDAuOCw2LjMiLz4NCjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0xMSwyMi41Yy0wLjMtMC4yLTAuNS0wLjUtMC44LTAuOGMtNy03LTEwLjItMTUuMy03LTE4LjVzMTEuNS0wLjEsMTguNSw3czEwLjIsMTUuMyw3LDE4LjUNCgljLTEuNywxLjctNC44LDEuNi04LjQsMC4xIi8+DQo8L3N2Zz4NCg==", + "name": "MousePointerLock", + "previewIconUrl": "https://resources.gdevelop-app.com/assets/Icons/Line Hero Pack/Master/SVG/Virtual Reality/Virtual Reality_360_rotate_vr_movement.svg", + "shortDescription": "Lock and hide mouse pointer for unlimited movement (e.g., FPS mouse look).", + "version": "0.3.1", + "description": [ + "This behavior removes the limit on the distance the mouse can move and hides the cursor.", + "", + "For example, a user can rotate or continue to manipulate an object by moving the mouse endlessly ([open the project online](https://editor.gdevelop.io/?project=example://mouse-pointer-lock)).", + "Without the pointer lock, the rotation or operation will stop the moment the pointer reaches the edge of the browser or screen.", + "", + "Game players don't have to worry about leaving the gameplay area or accidentally clicking on another application that moves the mouse focus away from the game.", + "", + "Locking the pointer locks `CursorX()` and `CursorY()` expressions.", + "Use `MovementX()` and `MovementY()` instead.", + "" + ], + "origin": { + "identifier": "MousePointerLock", + "name": "gdevelop-extension-store" + }, + "tags": [ + "mouse", + "lock", + "cursor", + "pointer" + ], + "authorIds": [ + "Zu55H5hcb9YmZTltIVOTAFDJQyB2", + "IWykYNRvhCZBN3vEgKEbBPOR3Oc2" + ], + "dependencies": [], + "globalVariables": [], + "sceneVariables": [ + { + "name": "TouchId", + "type": "number", + "value": -1 + }, + { + "name": "OldX", + "type": "number", + "value": 0 + }, + { + "name": "OldY", + "type": "number", + "value": 0 + }, + { + "name": "TouchSpeedFactor", + "type": "number", + "value": 4 + } + ], + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "onFirstSceneLoaded", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "class PointerLockHandler {", + " movementX = 0;", + " movementY = 0;", + " retried = false;", + " /**", + " * @type {gdjs.RuntimeGame}", + " */", + " game;", + "", + " /**", + " * @param {gdjs.RuntimeGame} game", + " */", + " constructor(game) {", + " this.game = game;", + " const canvas = game.getRenderer().getCanvas();", + "", + " canvas.addEventListener(\"pointermove\", event => {", + " if (!!document.pointerLockElement) {", + " this.movementX += event.movementX || 0;", + " this.movementY += event.movementY || 0;", + " }", + " }, false);", + "", + " document.addEventListener(\"pointerlockerror\", event => {", + " if (!this.retried) {", + " canvas.requestPointerLock();", + " this.retried = true;", + " }", + " });", + " }", + "", + " requestPointerLock() {", + " const canvas = this.game.getRenderer().getCanvas();", + " if (canvas.requestPointerLock && !document.pointerLockElement) {", + " this.retried = false;", + " canvas.requestPointerLock({ unadjustedMovement: true });", + " }", + " }", + "", + " exitPointerLock() {", + " if (document.exitPointerLock) {", + " document.exitPointerLock();", + " }", + " }", + "", + " isPointerLocked() {", + " return !!document.pointerLockElement;", + " }", + "", + " resetMovement() {", + " this.movementX = 0;", + " this.movementY = 0;", + " }", + "};", + "", + "gdjs._MousePointerLockExtension = { handler: new PointerLockHandler(runtimeScene.getGame()) };", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "onScenePostEvents", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const { handler } = gdjs._MousePointerLockExtension;\r", + "\r", + "handler.resetMovement();\r", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "MousePointerLock::isEmulatingPointerLock" + }, + "parameters": [ + "", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "MousePointerLock::SetMovementX" + }, + "parameters": [ + "", + "=", + "(MousePointerLock::TouchX(TouchId) - OldX) * TouchSpeedFactor", + "" + ] + }, + { + "type": { + "value": "MousePointerLock::SetMovementY" + }, + "parameters": [ + "", + "=", + "(MousePointerLock::TouchY(TouchId) - OldY) * TouchSpeedFactor", + "" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "OldX", + "=", + "MousePointerLock::TouchX(TouchId)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "OldY", + "=", + "MousePointerLock::TouchY(TouchId)" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "HasTouchEnded" + }, + "parameters": [ + "", + "TouchId" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TouchId", + "=", + "-1" + ] + } + ] + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "description": "Lock the mouse pointer to hide it.", + "fullName": "Request Pointer Lock", + "functionType": "Action", + "name": "RequestPointerLock", + "sentence": "Request Pointer Lock", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "HasAnyTouchOrMouseStarted" + }, + "parameters": [ + "" + ] + }, + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "TouchId", + "=", + "-1" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TouchId", + "=", + "StartedTouchOrMouseId(0)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "OldX", + "=", + "MousePointerLock::TouchX(TouchId)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "OldY", + "=", + "MousePointerLock::TouchY(TouchId)" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const { handler } = gdjs._MousePointerLockExtension;\r", + "\r", + "handler.requestPointerLock();\r", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "description": "Unlocks the mouse pointer and show it.", + "fullName": "Exit pointer lock", + "functionType": "Action", + "name": "ExitPointerLock", + "sentence": "Exit pointer lock", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TouchId", + "=", + "-1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const { handler } = gdjs._MousePointerLockExtension;\r", + "\r", + "handler.exitPointerLock();\r", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "description": "Check if the mouse pointer is locked.", + "fullName": "Pointer is locked", + "functionType": "Condition", + "name": "isPointerLocked", + "sentence": "The mouse pointer is locked", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "TouchId", + ">=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "TouchId", + "<", + "0" + ] + }, + { + "type": { + "value": "MousePointerLock::isPointerActuallyLocked" + }, + "parameters": [ + "", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "description": "Check if the mouse pointer is actually locked.", + "fullName": "Pointer is actually locked", + "functionType": "Condition", + "name": "isPointerActuallyLocked", + "private": true, + "sentence": "The mouse pointer actually is locked", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const { handler } = gdjs._MousePointerLockExtension;\r", + "\r", + "eventsFunctionContext.returnValue = handler.isPointerLocked();\r", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "description": "Check if the mouse pointer lock is emulated.", + "fullName": "Pointer lock is emulated", + "functionType": "Condition", + "name": "isEmulatingPointerLock", + "private": true, + "sentence": "The mouse pointer lock is emulated", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "MousePointerLock::isPointerActuallyLocked" + }, + "parameters": [ + "", + "" + ] + }, + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "TouchId", + ">=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "description": "Check if the locked pointer is moving.", + "fullName": "Locked pointer is moving", + "functionType": "Condition", + "name": "IsMoving", + "sentence": "Locked pointer is moving", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Or" + }, + "parameters": [], + "subInstructions": [ + { + "type": { + "value": "MousePointerLock::MovementX" + }, + "parameters": [ + "", + "!=", + "0", + "" + ] + }, + { + "type": { + "value": "MousePointerLock::MovementY" + }, + "parameters": [ + "", + "!=", + "0", + "" + ] + } + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "description": "the movement of the locked pointer on the X axis.", + "fullName": "Pointer X movement", + "functionType": "ExpressionAndCondition", + "name": "MovementX", + "sentence": "the movement of the locked pointer on the X axis", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "eventsFunctionContext.returnValue = gdjs._MousePointerLockExtension.handler.movementX || 0;\r", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [], + "objectGroups": [] + }, + { + "description": "the movement of the locked pointer on the X axis.", + "fullName": "Pointer X movement", + "functionType": "ActionWithOperator", + "getterName": "MovementX", + "name": "SetMovementX", + "private": true, + "sentence": "the movement of the locked pointer on the X axis", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "gdjs._MousePointerLockExtension.handler.movementX = value;\r", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "description": "the movement of the pointer on the Y axis.", + "fullName": "Pointer Y movement", + "functionType": "ExpressionAndCondition", + "name": "MovementY", + "sentence": "the movement of the pointer on the Y axis", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "eventsFunctionContext.returnValue = gdjs._MousePointerLockExtension.handler.movementY || 0;\r", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [], + "objectGroups": [] + }, + { + "description": "the movement of the locked pointer on the X axis.", + "fullName": "Pointer X movement", + "functionType": "ActionWithOperator", + "getterName": "MovementY", + "name": "SetMovementY", + "private": true, + "sentence": "the movement of the locked pointer on the X axis", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "gdjs._MousePointerLockExtension.handler.movementY = value;\r", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "description": "Return the X position of a specific touch", + "fullName": "Touch X position", + "functionType": "Expression", + "name": "TouchX", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const touchId = eventsFunctionContext.getArgument(\"NewTouchId\");", + "eventsFunctionContext.returnValue = runtimeScene.getGame().getInputManager().getTouchX(touchId);", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Touch identifier", + "name": "NewTouchId", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Return the Y position of a specific touch", + "fullName": "Touch Y position", + "functionType": "Expression", + "name": "TouchY", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const touchId = eventsFunctionContext.getArgument(\"NewTouchId\");", + "eventsFunctionContext.returnValue = runtimeScene.getGame().getInputManager().getTouchY(touchId);", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Touch identifier", + "name": "NewTouchId", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "the speed factor for touch movement.", + "fullName": "Speed factor for touch movement", + "functionType": "ExpressionAndCondition", + "name": "TouchSpeedFactor", + "sentence": "the speed factor for touch movement", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "TouchSpeedFactor" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "TouchSpeedFactor", + "name": "SetTouchSpeedFactor", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TouchSpeedFactor", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "onFirstSceneLoaded" + }, + { + "functionName": "onScenePostEvents" + }, + { + "functionName": "RequestPointerLock" + }, + { + "functionName": "ExitPointerLock" + }, + { + "functionName": "isPointerLocked" + }, + { + "functionName": "isPointerActuallyLocked" + }, + { + "functionName": "isEmulatingPointerLock" + }, + { + "functionName": "IsMoving" + }, + { + "functionName": "MovementX" + }, + { + "functionName": "SetMovementX" + }, + { + "functionName": "MovementY" + }, + { + "functionName": "SetMovementY" + }, + { + "functionName": "TouchX" + }, + { + "functionName": "TouchY" + }, + { + "functionName": "TouchSpeedFactor" + }, + { + "functionName": "SetTouchSpeedFactor" + } + ] + }, + "eventsBasedBehaviors": [ + { + "description": "Control camera rotations with a mouse.", + "fullName": "First person camera mouse mapper", + "helpPath": "", + "iconUrl": "", + "name": "FirstPersonPointerMapper", + "objectType": "", + "previewIconUrl": "", + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "doStepPreEvents", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "TODO It's probably a bad idea to rotate the object around Y." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "MousePointerLock::isPointerLocked" + }, + "parameters": [ + "", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetAngle" + }, + "parameters": [ + "Object", + "+", + "MousePointerLock::MovementX() * HorizontalSpeed / SceneWindowWidth()" + ] + }, + { + "type": { + "value": "Scene3D::Base3DBehavior::SetRotationY" + }, + "parameters": [ + "Object", + "Object3D", + "+", + "MousePointerLock::MovementY() * VerticalSpeed / SceneWindowHeight()" + ] + }, + { + "type": { + "value": "Scene3D::Base3DBehavior::SetRotationY" + }, + "parameters": [ + "Object", + "Object3D", + "=", + "clamp(Object.Object3D::RotationY(), VerticalAngleMin, VerticalAngleMax)" + ] + }, + { + "type": { + "value": "MousePointerLock::FirstPersonPointerMapper::LookFromObjectEyes" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "MouseButtonReleased" + }, + "parameters": [ + "", + "Left" + ] + }, + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "ShouldLock", + "True", + "" + ] + }, + { + "type": { + "inverted": true, + "value": "MousePointerLock::isPointerLocked" + }, + "parameters": [ + "", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "MousePointerLock::RequestPointerLock" + }, + "parameters": [ + "", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "MousePointerLock::FirstPersonPointerMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Move the camera to look though _PARAM1_ eyes. The object must look to the right when all its angles are 0 and the top of its head be toward Z+.", + "fullName": "Look through object eyes", + "functionType": "Action", + "group": "Layers and cameras", + "name": "LookFromObjectEyes", + "private": true, + "sentence": "Move the camera to look though _PARAM0_ eyes", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "CenterCameraOnObject" + }, + "parameters": [ + "", + "Object", + "", + "Object.Layer()", + "" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraZ" + }, + "parameters": [ + "", + "=", + "Object.Object3D::Z() + Object.Object3D::Depth() + OffsetZ", + "", + "" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraRotationX" + }, + "parameters": [ + "", + "=", + "- Object.Object3D::RotationY() + 90", + "GetArgumentAsString(\"Layer\")", + "" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraRotationY" + }, + "parameters": [ + "", + "=", + "Object.Object3D::RotationX()", + "GetArgumentAsString(\"Layer\")", + "" + ] + }, + { + "type": { + "value": "SetCameraAngle" + }, + "parameters": [ + "", + "=", + "Object.Angle() + 90", + "Object.Layer()", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "MousePointerLock::FirstPersonPointerMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the horizontal rotation speed factor of the object.", + "fullName": "Horizontal rotation speed factor", + "functionType": "ExpressionAndCondition", + "group": "First person camera mouse mapper configuration", + "name": "HorizontalSpeed", + "sentence": "the horizontal rotation speed factor", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "HorizontalSpeed" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "MousePointerLock::FirstPersonPointerMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "HorizontalSpeed", + "group": "First person camera mouse mapper configuration", + "name": "SetHorizontalSpeed", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "HorizontalSpeed", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "MousePointerLock::FirstPersonPointerMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the vertical rotation speed factor of the object.", + "fullName": "Vertical rotation speed factor", + "functionType": "ExpressionAndCondition", + "group": "First person camera mouse mapper configuration", + "name": "VerticalSpeed", + "sentence": "the vertical rotation speed factor", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "VerticalSpeed" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "MousePointerLock::FirstPersonPointerMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "VerticalSpeed", + "group": "First person camera mouse mapper configuration", + "name": "SetVerticalSpeed", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "VerticalSpeed", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "MousePointerLock::FirstPersonPointerMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the minimum vertical camera angle of the object.", + "fullName": "Minimum vertical camera angle", + "functionType": "ExpressionAndCondition", + "group": "First person camera mouse mapper configuration", + "name": "VerticalAngleMin", + "sentence": "the minimum vertical camera angle", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "VerticalAngleMin" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "MousePointerLock::FirstPersonPointerMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "VerticalAngleMin", + "group": "First person camera mouse mapper configuration", + "name": "SetVerticalAngleMin", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "VerticalAngleMin", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "MousePointerLock::FirstPersonPointerMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the maximum vertical camera angle of the object.", + "fullName": "Maximum vertical camera angle", + "functionType": "ExpressionAndCondition", + "group": "First person camera mouse mapper configuration", + "name": "VerticalAngleMax", + "sentence": "the maximum vertical camera angle", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "VerticalAngleMax" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "MousePointerLock::FirstPersonPointerMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "VerticalAngleMax", + "group": "First person camera mouse mapper configuration", + "name": "SetVerticalAngleMax", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "VerticalAngleMax", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "MousePointerLock::FirstPersonPointerMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the z position offset of the object.", + "fullName": "Z position offset", + "functionType": "ExpressionAndCondition", + "group": "First person camera mouse mapper configuration", + "name": "OffsetZ", + "sentence": "the z position offset", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "OffsetZ" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "MousePointerLock::FirstPersonPointerMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "OffsetZ", + "group": "First person camera mouse mapper configuration", + "name": "SetOffsetZ", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "OffsetZ", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "MousePointerLock::FirstPersonPointerMapper", + "type": "behavior" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "doStepPreEvents" + }, + { + "folderName": "Layers and cameras", + "children": [ + { + "functionName": "LookFromObjectEyes" + } + ] + }, + { + "folderName": "First person camera mouse mapper configuration", + "children": [ + { + "functionName": "HorizontalSpeed" + }, + { + "functionName": "SetHorizontalSpeed" + }, + { + "functionName": "VerticalSpeed" + }, + { + "functionName": "SetVerticalSpeed" + }, + { + "functionName": "VerticalAngleMin" + }, + { + "functionName": "SetVerticalAngleMin" + }, + { + "functionName": "VerticalAngleMax" + }, + { + "functionName": "SetVerticalAngleMax" + }, + { + "functionName": "OffsetZ" + }, + { + "functionName": "SetOffsetZ" + } + ] + } + ] + }, + "propertyDescriptors": [ + { + "value": "", + "type": "Behavior", + "label": "3D capability", + "extraInformation": [ + "Scene3D::Base3DBehavior" + ], + "choices": [], + "name": "Object3D" + }, + { + "value": "200", + "type": "Number", + "unit": "Dimensionless", + "label": "Horizontal rotation speed factor", + "name": "HorizontalSpeed" + }, + { + "value": "100", + "type": "Number", + "unit": "Dimensionless", + "label": "Vertical rotation speed factor", + "name": "VerticalSpeed" + }, + { + "value": "-90", + "type": "Number", + "unit": "DegreeAngle", + "label": "Minimum vertical camera angle", + "name": "VerticalAngleMin" + }, + { + "value": "90", + "type": "Number", + "unit": "DegreeAngle", + "label": "Maximum vertical camera angle", + "name": "VerticalAngleMax" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Z position offset", + "name": "OffsetZ" + }, + { + "value": "true", + "type": "Boolean", + "label": "Lock the pointer on click", + "name": "ShouldLock" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "propertyName": "Object3D" + }, + { + "propertyName": "HorizontalSpeed" + }, + { + "propertyName": "VerticalSpeed" + }, + { + "propertyName": "VerticalAngleMin" + }, + { + "propertyName": "VerticalAngleMax" + }, + { + "propertyName": "OffsetZ" + }, + { + "propertyName": "ShouldLock" + } + ] + } + } + ], + "eventsBasedObjects": [] + } + ], + "externalLayouts": [], + "externalLayoutsFolderStructure": { + "folderName": "__ROOT" + } +} \ No newline at end of file diff --git a/examples/3d-air-hockey/README.md b/examples/3d-air-hockey/README.md new file mode 100644 index 000000000..020da2648 --- /dev/null +++ b/examples/3d-air-hockey/README.md @@ -0,0 +1,3 @@ +# 3D Air Hockey + +A 3D air hockey match on a football-pitch table against a computer opponent, with team selection, power-ups, a cheering stadium and match commentary. \ No newline at end of file diff --git a/examples/3d-air-hockey/TAGS.md b/examples/3d-air-hockey/TAGS.md new file mode 100644 index 000000000..09ba07039 --- /dev/null +++ b/examples/3d-air-hockey/TAGS.md @@ -0,0 +1 @@ +game, advanced \ No newline at end of file diff --git a/examples/3d-air-hockey/assets/Camera.glb b/examples/3d-air-hockey/assets/Camera.glb new file mode 100644 index 000000000..2f141005a Binary files /dev/null and b/examples/3d-air-hockey/assets/Camera.glb differ diff --git a/examples/3d-air-hockey/assets/fonts/Coiny-Regular.ttf b/examples/3d-air-hockey/assets/fonts/Coiny-Regular.ttf new file mode 100644 index 000000000..f566d5e34 Binary files /dev/null and b/examples/3d-air-hockey/assets/fonts/Coiny-Regular.ttf differ diff --git a/examples/3d-air-hockey/assets/fonts/RobotoMono-Bold.ttf b/examples/3d-air-hockey/assets/fonts/RobotoMono-Bold.ttf new file mode 100644 index 000000000..f6e32ad98 Binary files /dev/null and b/examples/3d-air-hockey/assets/fonts/RobotoMono-Bold.ttf differ diff --git a/examples/3d-air-hockey/assets/images/ButtonHovered.png b/examples/3d-air-hockey/assets/images/ButtonHovered.png new file mode 100644 index 000000000..210810730 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/ButtonHovered.png differ diff --git a/examples/3d-air-hockey/assets/images/ButtonIdle.png b/examples/3d-air-hockey/assets/images/ButtonIdle.png new file mode 100644 index 000000000..5bb82915f Binary files /dev/null and b/examples/3d-air-hockey/assets/images/ButtonIdle.png differ diff --git a/examples/3d-air-hockey/assets/images/ButtonPressed.png b/examples/3d-air-hockey/assets/images/ButtonPressed.png new file mode 100644 index 000000000..fc9a3b0c0 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/ButtonPressed.png differ diff --git a/examples/3d-air-hockey/assets/images/CloseButtonHovered.png b/examples/3d-air-hockey/assets/images/CloseButtonHovered.png new file mode 100644 index 000000000..30552e250 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/CloseButtonHovered.png differ diff --git a/examples/3d-air-hockey/assets/images/CloseButtonIdle.png b/examples/3d-air-hockey/assets/images/CloseButtonIdle.png new file mode 100644 index 000000000..a7ae52212 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/CloseButtonIdle.png differ diff --git a/examples/3d-air-hockey/assets/images/CloseButtonPressed.png b/examples/3d-air-hockey/assets/images/CloseButtonPressed.png new file mode 100644 index 000000000..a0dfcc429 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/CloseButtonPressed.png differ diff --git a/examples/3d-air-hockey/assets/images/Confetti.png b/examples/3d-air-hockey/assets/images/Confetti.png new file mode 100644 index 000000000..ceb110ed7 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/Confetti.png differ diff --git a/examples/3d-air-hockey/assets/images/FlagBelgium.png b/examples/3d-air-hockey/assets/images/FlagBelgium.png new file mode 100644 index 000000000..b751299e0 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/FlagBelgium.png differ diff --git a/examples/3d-air-hockey/assets/images/FlagCanada.png b/examples/3d-air-hockey/assets/images/FlagCanada.png new file mode 100644 index 000000000..dd19da7a7 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/FlagCanada.png differ diff --git a/examples/3d-air-hockey/assets/images/FlagFrance.png b/examples/3d-air-hockey/assets/images/FlagFrance.png new file mode 100644 index 000000000..5eaa7e53f Binary files /dev/null and b/examples/3d-air-hockey/assets/images/FlagFrance.png differ diff --git a/examples/3d-air-hockey/assets/images/FlagGermany.png b/examples/3d-air-hockey/assets/images/FlagGermany.png new file mode 100644 index 000000000..31120dd86 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/FlagGermany.png differ diff --git a/examples/3d-air-hockey/assets/images/FlagSpain.png b/examples/3d-air-hockey/assets/images/FlagSpain.png new file mode 100644 index 000000000..a1725c37a Binary files /dev/null and b/examples/3d-air-hockey/assets/images/FlagSpain.png differ diff --git a/examples/3d-air-hockey/assets/images/FlagUSA.png b/examples/3d-air-hockey/assets/images/FlagUSA.png new file mode 100644 index 000000000..05bef2b25 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/FlagUSA.png differ diff --git a/examples/3d-air-hockey/assets/images/GearButtonHovered.png b/examples/3d-air-hockey/assets/images/GearButtonHovered.png new file mode 100644 index 000000000..08a4516e5 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/GearButtonHovered.png differ diff --git a/examples/3d-air-hockey/assets/images/GearButtonIdle.png b/examples/3d-air-hockey/assets/images/GearButtonIdle.png new file mode 100644 index 000000000..7ba406ce9 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/GearButtonIdle.png differ diff --git a/examples/3d-air-hockey/assets/images/GearButtonPressed.png b/examples/3d-air-hockey/assets/images/GearButtonPressed.png new file mode 100644 index 000000000..338d09df1 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/GearButtonPressed.png differ diff --git a/examples/3d-air-hockey/assets/images/GoalShieldWall.png b/examples/3d-air-hockey/assets/images/GoalShieldWall.png new file mode 100644 index 000000000..2d722a83a Binary files /dev/null and b/examples/3d-air-hockey/assets/images/GoalShieldWall.png differ diff --git a/examples/3d-air-hockey/assets/images/ModalPanel.png b/examples/3d-air-hockey/assets/images/ModalPanel.png new file mode 100644 index 000000000..90f7418b4 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/ModalPanel.png differ diff --git a/examples/3d-air-hockey/assets/images/ModalScrim.png b/examples/3d-air-hockey/assets/images/ModalScrim.png new file mode 100644 index 000000000..ffe2fc4b6 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/ModalScrim.png differ diff --git a/examples/3d-air-hockey/assets/images/PowerUpBigMallet.png b/examples/3d-air-hockey/assets/images/PowerUpBigMallet.png new file mode 100644 index 000000000..6d09f1901 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/PowerUpBigMallet.png differ diff --git a/examples/3d-air-hockey/assets/images/PowerUpFreeze.png b/examples/3d-air-hockey/assets/images/PowerUpFreeze.png new file mode 100644 index 000000000..67fd33a7c Binary files /dev/null and b/examples/3d-air-hockey/assets/images/PowerUpFreeze.png differ diff --git a/examples/3d-air-hockey/assets/images/PowerUpRing100.png b/examples/3d-air-hockey/assets/images/PowerUpRing100.png new file mode 100644 index 000000000..0e9bd2cf8 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/PowerUpRing100.png differ diff --git a/examples/3d-air-hockey/assets/images/PowerUpRing25.png b/examples/3d-air-hockey/assets/images/PowerUpRing25.png new file mode 100644 index 000000000..dfc40ee15 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/PowerUpRing25.png differ diff --git a/examples/3d-air-hockey/assets/images/PowerUpRing40.png b/examples/3d-air-hockey/assets/images/PowerUpRing40.png new file mode 100644 index 000000000..df4795a3d Binary files /dev/null and b/examples/3d-air-hockey/assets/images/PowerUpRing40.png differ diff --git a/examples/3d-air-hockey/assets/images/PowerUpRing60.png b/examples/3d-air-hockey/assets/images/PowerUpRing60.png new file mode 100644 index 000000000..1ca805b43 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/PowerUpRing60.png differ diff --git a/examples/3d-air-hockey/assets/images/PowerUpRing80.png b/examples/3d-air-hockey/assets/images/PowerUpRing80.png new file mode 100644 index 000000000..af236337f Binary files /dev/null and b/examples/3d-air-hockey/assets/images/PowerUpRing80.png differ diff --git a/examples/3d-air-hockey/assets/images/PowerUpShield.png b/examples/3d-air-hockey/assets/images/PowerUpShield.png new file mode 100644 index 000000000..a5c0e8f4e Binary files /dev/null and b/examples/3d-air-hockey/assets/images/PowerUpShield.png differ diff --git a/examples/3d-air-hockey/assets/images/PowerUpTurbo.png b/examples/3d-air-hockey/assets/images/PowerUpTurbo.png new file mode 100644 index 000000000..8cf28b0fc Binary files /dev/null and b/examples/3d-air-hockey/assets/images/PowerUpTurbo.png differ diff --git a/examples/3d-air-hockey/assets/images/PuckTrail.png b/examples/3d-air-hockey/assets/images/PuckTrail.png new file mode 100644 index 000000000..588c95389 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/PuckTrail.png differ diff --git a/examples/3d-air-hockey/assets/images/ResultPanel.png b/examples/3d-air-hockey/assets/images/ResultPanel.png new file mode 100644 index 000000000..45c0277be Binary files /dev/null and b/examples/3d-air-hockey/assets/images/ResultPanel.png differ diff --git a/examples/3d-air-hockey/assets/images/Scoreboard.png b/examples/3d-air-hockey/assets/images/Scoreboard.png new file mode 100644 index 000000000..0b9509ec0 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/Scoreboard.png differ diff --git a/examples/3d-air-hockey/assets/images/SecondaryButtonHovered.png b/examples/3d-air-hockey/assets/images/SecondaryButtonHovered.png new file mode 100644 index 000000000..f2173f13e Binary files /dev/null and b/examples/3d-air-hockey/assets/images/SecondaryButtonHovered.png differ diff --git a/examples/3d-air-hockey/assets/images/SecondaryButtonIdle.png b/examples/3d-air-hockey/assets/images/SecondaryButtonIdle.png new file mode 100644 index 000000000..a7d0566de Binary files /dev/null and b/examples/3d-air-hockey/assets/images/SecondaryButtonIdle.png differ diff --git a/examples/3d-air-hockey/assets/images/SecondaryButtonPressed.png b/examples/3d-air-hockey/assets/images/SecondaryButtonPressed.png new file mode 100644 index 000000000..6a3b6766a Binary files /dev/null and b/examples/3d-air-hockey/assets/images/SecondaryButtonPressed.png differ diff --git a/examples/3d-air-hockey/assets/images/SkyBack.png b/examples/3d-air-hockey/assets/images/SkyBack.png new file mode 100644 index 000000000..7d42d51c6 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/SkyBack.png differ diff --git a/examples/3d-air-hockey/assets/images/SkyBottom.png b/examples/3d-air-hockey/assets/images/SkyBottom.png new file mode 100644 index 000000000..a98f69f6d Binary files /dev/null and b/examples/3d-air-hockey/assets/images/SkyBottom.png differ diff --git a/examples/3d-air-hockey/assets/images/SkyFront.png b/examples/3d-air-hockey/assets/images/SkyFront.png new file mode 100644 index 000000000..af866a51c Binary files /dev/null and b/examples/3d-air-hockey/assets/images/SkyFront.png differ diff --git a/examples/3d-air-hockey/assets/images/SkyLeft.png b/examples/3d-air-hockey/assets/images/SkyLeft.png new file mode 100644 index 000000000..b6e567344 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/SkyLeft.png differ diff --git a/examples/3d-air-hockey/assets/images/SkyRight.png b/examples/3d-air-hockey/assets/images/SkyRight.png new file mode 100644 index 000000000..42dbe70b7 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/SkyRight.png differ diff --git a/examples/3d-air-hockey/assets/images/SkyTop.png b/examples/3d-air-hockey/assets/images/SkyTop.png new file mode 100644 index 000000000..f2c6ba8c8 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/SkyTop.png differ diff --git a/examples/3d-air-hockey/assets/images/StadiumSky.png b/examples/3d-air-hockey/assets/images/StadiumSky.png new file mode 100644 index 000000000..57350af1d Binary files /dev/null and b/examples/3d-air-hockey/assets/images/StadiumSky.png differ diff --git a/examples/3d-air-hockey/assets/images/TileHovered.png b/examples/3d-air-hockey/assets/images/TileHovered.png new file mode 100644 index 000000000..9613c150d Binary files /dev/null and b/examples/3d-air-hockey/assets/images/TileHovered.png differ diff --git a/examples/3d-air-hockey/assets/images/TileIdle.png b/examples/3d-air-hockey/assets/images/TileIdle.png new file mode 100644 index 000000000..81c20a55c Binary files /dev/null and b/examples/3d-air-hockey/assets/images/TileIdle.png differ diff --git a/examples/3d-air-hockey/assets/images/TileOpponent.png b/examples/3d-air-hockey/assets/images/TileOpponent.png new file mode 100644 index 000000000..fb320628c Binary files /dev/null and b/examples/3d-air-hockey/assets/images/TileOpponent.png differ diff --git a/examples/3d-air-hockey/assets/images/TilePressed.png b/examples/3d-air-hockey/assets/images/TilePressed.png new file mode 100644 index 000000000..3139a7313 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/TilePressed.png differ diff --git a/examples/3d-air-hockey/assets/images/TileSelected.png b/examples/3d-air-hockey/assets/images/TileSelected.png new file mode 100644 index 000000000..847271ed4 Binary files /dev/null and b/examples/3d-air-hockey/assets/images/TileSelected.png differ diff --git a/examples/3d-air-hockey/assets/models/FlagBelgium.glb b/examples/3d-air-hockey/assets/models/FlagBelgium.glb new file mode 100644 index 000000000..68ecc7ce0 Binary files /dev/null and b/examples/3d-air-hockey/assets/models/FlagBelgium.glb differ diff --git a/examples/3d-air-hockey/assets/models/FlagCanada.glb b/examples/3d-air-hockey/assets/models/FlagCanada.glb new file mode 100644 index 000000000..49b00bf47 Binary files /dev/null and b/examples/3d-air-hockey/assets/models/FlagCanada.glb differ diff --git a/examples/3d-air-hockey/assets/models/FlagFrance.glb b/examples/3d-air-hockey/assets/models/FlagFrance.glb new file mode 100644 index 000000000..22c116ae6 Binary files /dev/null and b/examples/3d-air-hockey/assets/models/FlagFrance.glb differ diff --git a/examples/3d-air-hockey/assets/models/FlagGermany.glb b/examples/3d-air-hockey/assets/models/FlagGermany.glb new file mode 100644 index 000000000..974318bcd Binary files /dev/null and b/examples/3d-air-hockey/assets/models/FlagGermany.glb differ diff --git a/examples/3d-air-hockey/assets/models/FlagSpain.glb b/examples/3d-air-hockey/assets/models/FlagSpain.glb new file mode 100644 index 000000000..199da8ad1 Binary files /dev/null and b/examples/3d-air-hockey/assets/models/FlagSpain.glb differ diff --git a/examples/3d-air-hockey/assets/models/FlagUSA.glb b/examples/3d-air-hockey/assets/models/FlagUSA.glb new file mode 100644 index 000000000..b8db7f54a Binary files /dev/null and b/examples/3d-air-hockey/assets/models/FlagUSA.glb differ diff --git a/examples/3d-air-hockey/assets/models/Goal.glb b/examples/3d-air-hockey/assets/models/Goal.glb new file mode 100644 index 000000000..1318fc0da Binary files /dev/null and b/examples/3d-air-hockey/assets/models/Goal.glb differ diff --git a/examples/3d-air-hockey/assets/models/MalletBelgium.glb b/examples/3d-air-hockey/assets/models/MalletBelgium.glb new file mode 100644 index 000000000..e0501b82f Binary files /dev/null and b/examples/3d-air-hockey/assets/models/MalletBelgium.glb differ diff --git a/examples/3d-air-hockey/assets/models/MalletBody.glb b/examples/3d-air-hockey/assets/models/MalletBody.glb new file mode 100644 index 000000000..7164e4064 Binary files /dev/null and b/examples/3d-air-hockey/assets/models/MalletBody.glb differ diff --git a/examples/3d-air-hockey/assets/models/MalletCanada.glb b/examples/3d-air-hockey/assets/models/MalletCanada.glb new file mode 100644 index 000000000..315d199ab Binary files /dev/null and b/examples/3d-air-hockey/assets/models/MalletCanada.glb differ diff --git a/examples/3d-air-hockey/assets/models/MalletFrance.glb b/examples/3d-air-hockey/assets/models/MalletFrance.glb new file mode 100644 index 000000000..f2a186f2c Binary files /dev/null and b/examples/3d-air-hockey/assets/models/MalletFrance.glb differ diff --git a/examples/3d-air-hockey/assets/models/MalletGermany.glb b/examples/3d-air-hockey/assets/models/MalletGermany.glb new file mode 100644 index 000000000..9c36904ce Binary files /dev/null and b/examples/3d-air-hockey/assets/models/MalletGermany.glb differ diff --git a/examples/3d-air-hockey/assets/models/MalletSpain.glb b/examples/3d-air-hockey/assets/models/MalletSpain.glb new file mode 100644 index 000000000..c797f4efa Binary files /dev/null and b/examples/3d-air-hockey/assets/models/MalletSpain.glb differ diff --git a/examples/3d-air-hockey/assets/models/MalletUSA.glb b/examples/3d-air-hockey/assets/models/MalletUSA.glb new file mode 100644 index 000000000..2c18f23d9 Binary files /dev/null and b/examples/3d-air-hockey/assets/models/MalletUSA.glb differ diff --git a/examples/3d-air-hockey/assets/models/Puck.glb b/examples/3d-air-hockey/assets/models/Puck.glb new file mode 100644 index 000000000..328bbdd89 Binary files /dev/null and b/examples/3d-air-hockey/assets/models/Puck.glb differ diff --git a/examples/3d-air-hockey/assets/models/Stadium.glb b/examples/3d-air-hockey/assets/models/Stadium.glb new file mode 100644 index 000000000..401ff53fd Binary files /dev/null and b/examples/3d-air-hockey/assets/models/Stadium.glb differ diff --git a/examples/3d-air-hockey/assets/models/Table.glb b/examples/3d-air-hockey/assets/models/Table.glb new file mode 100644 index 000000000..8f75b8004 Binary files /dev/null and b/examples/3d-air-hockey/assets/models/Table.glb differ diff --git a/examples/3d-air-hockey/assets/sounds/Ambient1.mp3 b/examples/3d-air-hockey/assets/sounds/Ambient1.mp3 new file mode 100644 index 000000000..8c50d42fc Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/Ambient1.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/Ambient2.mp3 b/examples/3d-air-hockey/assets/sounds/Ambient2.mp3 new file mode 100644 index 000000000..73bbacc9e Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/Ambient2.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/Ambient3.mp3 b/examples/3d-air-hockey/assets/sounds/Ambient3.mp3 new file mode 100644 index 000000000..a341e0ff3 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/Ambient3.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/AnthemBelgium.mp3 b/examples/3d-air-hockey/assets/sounds/AnthemBelgium.mp3 new file mode 100644 index 000000000..383d4c14e Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/AnthemBelgium.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/AnthemCanada.mp3 b/examples/3d-air-hockey/assets/sounds/AnthemCanada.mp3 new file mode 100644 index 000000000..c5a05a737 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/AnthemCanada.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/AnthemFrance.mp3 b/examples/3d-air-hockey/assets/sounds/AnthemFrance.mp3 new file mode 100644 index 000000000..8b32a9415 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/AnthemFrance.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/AnthemGermany.mp3 b/examples/3d-air-hockey/assets/sounds/AnthemGermany.mp3 new file mode 100644 index 000000000..f59357e0a Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/AnthemGermany.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/AnthemSpain.mp3 b/examples/3d-air-hockey/assets/sounds/AnthemSpain.mp3 new file mode 100644 index 000000000..30a6793c1 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/AnthemSpain.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/AnthemUSA.mp3 b/examples/3d-air-hockey/assets/sounds/AnthemUSA.mp3 new file mode 100644 index 000000000..0074eaa50 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/AnthemUSA.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/Applause.mp3 b/examples/3d-air-hockey/assets/sounds/Applause.mp3 new file mode 100644 index 000000000..05ab49dcc Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/Applause.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/ButtonClick.mp3 b/examples/3d-air-hockey/assets/sounds/ButtonClick.mp3 new file mode 100644 index 000000000..4048bf285 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/ButtonClick.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/CrowdNearMiss.mp3 b/examples/3d-air-hockey/assets/sounds/CrowdNearMiss.mp3 new file mode 100644 index 000000000..cd747faf7 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/CrowdNearMiss.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/GoalOpponent.aac b/examples/3d-air-hockey/assets/sounds/GoalOpponent.aac new file mode 100644 index 000000000..3679caee5 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/GoalOpponent.aac differ diff --git a/examples/3d-air-hockey/assets/sounds/MatchMusic.aac b/examples/3d-air-hockey/assets/sounds/MatchMusic.aac new file mode 100644 index 000000000..a020808aa Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/MatchMusic.aac differ diff --git a/examples/3d-air-hockey/assets/sounds/PowerUpPickup.aac b/examples/3d-air-hockey/assets/sounds/PowerUpPickup.aac new file mode 100644 index 000000000..ac303bc89 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/PowerUpPickup.aac differ diff --git a/examples/3d-air-hockey/assets/sounds/PowerUpSpawn.aac b/examples/3d-air-hockey/assets/sounds/PowerUpSpawn.aac new file mode 100644 index 000000000..88a7e0172 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/PowerUpSpawn.aac differ diff --git a/examples/3d-air-hockey/assets/sounds/PuckHit.aac b/examples/3d-air-hockey/assets/sounds/PuckHit.aac new file mode 100644 index 000000000..ebc3e2055 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/PuckHit.aac differ diff --git a/examples/3d-air-hockey/assets/sounds/WallBounce.aac b/examples/3d-air-hockey/assets/sounds/WallBounce.aac new file mode 100644 index 000000000..f7482125f Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/WallBounce.aac differ diff --git a/examples/3d-air-hockey/assets/sounds/Whistle.aac b/examples/3d-air-hockey/assets/sounds/Whistle.aac new file mode 100644 index 000000000..c2e8f2e65 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/Whistle.aac differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/README.md b/examples/3d-air-hockey/assets/sounds/voice/README.md new file mode 100644 index 000000000..294a91fce --- /dev/null +++ b/examples/3d-air-hockey/assets/sounds/voice/README.md @@ -0,0 +1,33 @@ +# Voice lines + +`default/` holds the recordings used for every language. Each file is numbered so its name is unique: `01_good_game.mp3` ... `18_yikes.mp3`. + +## Add a language +1. Create a folder named after the two-letter code, e.g. `fr/`. +2. Put the translated recordings in it with the SAME file names as `default/`. +3. In GDevelop, declare each file as an audio resource named `voice//.mp3` (e.g. `voice/fr/01_good_game.mp3`). +4. In the `Commentator` external events, group "Commentator voice": add an `if Commentator.Language = ""` branch to each line event, playing `voice//.mp3` (sound actions need a fixed file name, so one branch per line). + +The language is the scene variable `Commentator.Language`: `"fr"` plays `voice/fr/`, anything else (empty by default) plays `voice/default/` (English). The browser language is not read (no JavaScript). + +## Commentator processing +Every file in `default/` and `fr/` has a broadcast commentator treatment (ffmpeg: band 180 Hz-6 kHz, +6 dB at 2.8 kHz, -3 dB at 350 Hz, compressor 6:1, soft clip, short echo, loudnorm -14 LUFS). `fr/` is also pitched up 6 % before it (`asetrate=44100*1.06,aresample=44100,atempo=0.9434`, same duration). The untreated recordings are kept outside the game folder, in `Sources/voice/_originals//` at the project root (`Sources/voice/fr/_originals/` is the voice-dubber backup of `fr/`): re-apply the treatment from there, never on an already treated file. Encode the result as mono MP3 80 kbps, 44.1 kHz (`VOICE_MP3` in `tools/audio_encoding.py`, applied by `tools/optimize_sounds.py`). + +## When each line plays (external events `Commentator`) +| Line | Moment | +|---|---| +| 01_good_game | End of the match, player wins | +| 02_goooooal, 06_lets_gooo | Player goal (random) | +| 03_go_go_go | First kickoff (0-0) | +| 03_go_go_go, 05_here_we_go_again, 06_lets_gooo | Puck nearly still for 2 s (random, then at least 10 s before the next one) | +| 04_great, 14_thats_great | Strong player hit (random, chance + cooldown) | +| 05_here_we_go_again | Kickoff after an opponent goal | +| 07_nice, 17_yeahh | Ordinary player hit (random, low chance + cooldown) | +| 08_nice | Player save near their own goal | +| 09_nooo, 18_yikes | Opponent shot hits the end wall right next to the player's goal (random) | +| 10_nothing_but_net | Player goal with no wall bounce since the player's touch | +| 11_not_bad | Defeat, player scored 3+ | +| 12_oh_noo | Defeat, player scored 0 | +| 13_scored | Player goal after a rally of 3+ player touches | +| 15_thats_terrible | Player shot hits the goal frame without scoring; opponent scores twice in a row; full-speed player swing that passes the puck without touching it | +| 16_what_was_the_plan | Defeat, player scored 1-2 | diff --git a/examples/3d-air-hockey/assets/sounds/voice/default/01_good_game.mp3 b/examples/3d-air-hockey/assets/sounds/voice/default/01_good_game.mp3 new file mode 100644 index 000000000..f3c029dce Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/default/01_good_game.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/default/02_goooooal.mp3 b/examples/3d-air-hockey/assets/sounds/voice/default/02_goooooal.mp3 new file mode 100644 index 000000000..4ff9cc7cf Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/default/02_goooooal.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/default/03_go_go_go.mp3 b/examples/3d-air-hockey/assets/sounds/voice/default/03_go_go_go.mp3 new file mode 100644 index 000000000..98badbc25 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/default/03_go_go_go.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/default/04_great.mp3 b/examples/3d-air-hockey/assets/sounds/voice/default/04_great.mp3 new file mode 100644 index 000000000..015b5bbe6 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/default/04_great.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/default/05_here_we_go_again.mp3 b/examples/3d-air-hockey/assets/sounds/voice/default/05_here_we_go_again.mp3 new file mode 100644 index 000000000..290535846 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/default/05_here_we_go_again.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/default/06_lets_gooo.mp3 b/examples/3d-air-hockey/assets/sounds/voice/default/06_lets_gooo.mp3 new file mode 100644 index 000000000..a0dedaabf Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/default/06_lets_gooo.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/default/07_nice.mp3 b/examples/3d-air-hockey/assets/sounds/voice/default/07_nice.mp3 new file mode 100644 index 000000000..d56f2bb12 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/default/07_nice.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/default/08_nice.mp3 b/examples/3d-air-hockey/assets/sounds/voice/default/08_nice.mp3 new file mode 100644 index 000000000..f86e7d72a Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/default/08_nice.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/default/09_nooo.mp3 b/examples/3d-air-hockey/assets/sounds/voice/default/09_nooo.mp3 new file mode 100644 index 000000000..d9e8ad0ed Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/default/09_nooo.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/default/10_nothing_but_net.mp3 b/examples/3d-air-hockey/assets/sounds/voice/default/10_nothing_but_net.mp3 new file mode 100644 index 000000000..99f5507b9 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/default/10_nothing_but_net.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/default/11_not_bad.mp3 b/examples/3d-air-hockey/assets/sounds/voice/default/11_not_bad.mp3 new file mode 100644 index 000000000..3ceecd120 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/default/11_not_bad.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/default/12_oh_noo.mp3 b/examples/3d-air-hockey/assets/sounds/voice/default/12_oh_noo.mp3 new file mode 100644 index 000000000..7bdd9fbd3 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/default/12_oh_noo.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/default/13_scored.mp3 b/examples/3d-air-hockey/assets/sounds/voice/default/13_scored.mp3 new file mode 100644 index 000000000..a037f8f7d Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/default/13_scored.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/default/14_thats_great.mp3 b/examples/3d-air-hockey/assets/sounds/voice/default/14_thats_great.mp3 new file mode 100644 index 000000000..59369523d Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/default/14_thats_great.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/default/15_thats_terrible.mp3 b/examples/3d-air-hockey/assets/sounds/voice/default/15_thats_terrible.mp3 new file mode 100644 index 000000000..13cac1140 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/default/15_thats_terrible.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/default/16_what_was_the_plan.mp3 b/examples/3d-air-hockey/assets/sounds/voice/default/16_what_was_the_plan.mp3 new file mode 100644 index 000000000..b945c7ebf Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/default/16_what_was_the_plan.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/default/17_yeahh.mp3 b/examples/3d-air-hockey/assets/sounds/voice/default/17_yeahh.mp3 new file mode 100644 index 000000000..30b4d943e Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/default/17_yeahh.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/default/18_yikes.mp3 b/examples/3d-air-hockey/assets/sounds/voice/default/18_yikes.mp3 new file mode 100644 index 000000000..5e3e4022d Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/default/18_yikes.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/fr/01_good_game.mp3 b/examples/3d-air-hockey/assets/sounds/voice/fr/01_good_game.mp3 new file mode 100644 index 000000000..69d8fc9ba Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/fr/01_good_game.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/fr/02_goooooal.mp3 b/examples/3d-air-hockey/assets/sounds/voice/fr/02_goooooal.mp3 new file mode 100644 index 000000000..455b4315f Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/fr/02_goooooal.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/fr/03_go_go_go.mp3 b/examples/3d-air-hockey/assets/sounds/voice/fr/03_go_go_go.mp3 new file mode 100644 index 000000000..9959968a2 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/fr/03_go_go_go.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/fr/04_great.mp3 b/examples/3d-air-hockey/assets/sounds/voice/fr/04_great.mp3 new file mode 100644 index 000000000..b9fe0ffab Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/fr/04_great.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/fr/05_here_we_go_again.mp3 b/examples/3d-air-hockey/assets/sounds/voice/fr/05_here_we_go_again.mp3 new file mode 100644 index 000000000..b54685a5f Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/fr/05_here_we_go_again.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/fr/06_lets_gooo.mp3 b/examples/3d-air-hockey/assets/sounds/voice/fr/06_lets_gooo.mp3 new file mode 100644 index 000000000..d2db76261 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/fr/06_lets_gooo.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/fr/07_nice.mp3 b/examples/3d-air-hockey/assets/sounds/voice/fr/07_nice.mp3 new file mode 100644 index 000000000..b4e8fba28 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/fr/07_nice.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/fr/08_nice.mp3 b/examples/3d-air-hockey/assets/sounds/voice/fr/08_nice.mp3 new file mode 100644 index 000000000..698fcef79 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/fr/08_nice.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/fr/09_nooo.mp3 b/examples/3d-air-hockey/assets/sounds/voice/fr/09_nooo.mp3 new file mode 100644 index 000000000..c4c0570b9 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/fr/09_nooo.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/fr/10_nothing_but_net.mp3 b/examples/3d-air-hockey/assets/sounds/voice/fr/10_nothing_but_net.mp3 new file mode 100644 index 000000000..0c8a95f59 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/fr/10_nothing_but_net.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/fr/11_not_bad.mp3 b/examples/3d-air-hockey/assets/sounds/voice/fr/11_not_bad.mp3 new file mode 100644 index 000000000..8bc4d06a8 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/fr/11_not_bad.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/fr/12_oh_noo.mp3 b/examples/3d-air-hockey/assets/sounds/voice/fr/12_oh_noo.mp3 new file mode 100644 index 000000000..97a02055e Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/fr/12_oh_noo.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/fr/13_scored.mp3 b/examples/3d-air-hockey/assets/sounds/voice/fr/13_scored.mp3 new file mode 100644 index 000000000..bddc155a4 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/fr/13_scored.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/fr/14_thats_great.mp3 b/examples/3d-air-hockey/assets/sounds/voice/fr/14_thats_great.mp3 new file mode 100644 index 000000000..dda799549 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/fr/14_thats_great.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/fr/15_thats_terrible.mp3 b/examples/3d-air-hockey/assets/sounds/voice/fr/15_thats_terrible.mp3 new file mode 100644 index 000000000..5378f800a Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/fr/15_thats_terrible.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/fr/16_what_was_the_plan.mp3 b/examples/3d-air-hockey/assets/sounds/voice/fr/16_what_was_the_plan.mp3 new file mode 100644 index 000000000..ce90496d6 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/fr/16_what_was_the_plan.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/fr/17_yeahh.mp3 b/examples/3d-air-hockey/assets/sounds/voice/fr/17_yeahh.mp3 new file mode 100644 index 000000000..96a2d7970 Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/fr/17_yeahh.mp3 differ diff --git a/examples/3d-air-hockey/assets/sounds/voice/fr/18_yikes.mp3 b/examples/3d-air-hockey/assets/sounds/voice/fr/18_yikes.mp3 new file mode 100644 index 000000000..d7f16176b Binary files /dev/null and b/examples/3d-air-hockey/assets/sounds/voice/fr/18_yikes.mp3 differ diff --git a/examples/3d-air-hockey/preview.png b/examples/3d-air-hockey/preview.png new file mode 100644 index 000000000..361d5d293 Binary files /dev/null and b/examples/3d-air-hockey/preview.png differ