From 9d38ffff1d9155bea9cc11499fbd0576b90a18f8 Mon Sep 17 00:00:00 2001 From: Ben Allfree Date: Sun, 16 Jan 2022 09:45:45 -0800 Subject: [PATCH] Local sandbox (#193) * gatsby-mdx-codesandbox package --- .gitignore | 3 +- .prettierignore | 3 +- .prettierrc | 16 + package.json | 5 +- packages/gatsby-mdx-codesandbox/.gitignore | 2 + packages/gatsby-mdx-codesandbox/README.md | 5 + packages/gatsby-mdx-codesandbox/package.json | 36 + .../.codesandbox/workspace.json | 0 .../src}/codesandbox-template/.prettierrc | 0 .../src}/codesandbox-template/package.json | 2 +- .../src}/codesandbox-template/src/App.tsx | 0 .../src}/codesandbox-template/src/index.tsx | 0 .../src}/codesandbox-template/src/styles.css | 0 .../src}/codesandbox-template/tsconfig.json | 0 packages/gatsby-mdx-codesandbox/src/index.ts | 370 ++ .../gatsby-mdx-codesandbox/src/mdast.d.ts | 371 ++ packages/gatsby-mdx-codesandbox/tsconfig.json | 107 + packages/react-codesandbox-viewer/.gitignore | 2 + .../.storybook/main.js | 5 + .../.storybook/preview.js | 9 + .../react-codesandbox-viewer/package.json | 52 + packages/react-codesandbox-viewer/src/App.jsx | 126 + packages/react-codesandbox-viewer/src/App.tsx | 145 + .../src/Demo.stories.tsx | 76 + .../react-codesandbox-viewer/src/Demo.tsx | 209 + .../src/cookieHook.ts | 38 + .../react-codesandbox-viewer/src/index.ts | 1 + .../react-codesandbox-viewer/tsconfig.json | 107 + packages/static/.eslintrc.json | 25 +- packages/static/.prettierignore | 1 + packages/static/.prettierrc | 1 - .../1-react-boiler-plate/HelloReact.tsx | 5 + .../index.mdx} | 10 +- .../FullImperitive.tsx} | 105 +- .../WithHooks.tsx | 57 + .../index.mdx | 40 + .../3-react-with-declarative-babylonjs.mdx | 69 - .../BasicScene.tsx | 19 + .../Declarative.tsx | 36 + .../index.mdx | 99 + .../Colorful.tsx} | 39 +- .../4-adding-animation-and-color/index.mdx | 8 + packages/static/gatsby-config.js | 12 +- packages/static/package.json | 8 +- packages/static/src/components/index.js | 4 +- .../src/components/mdxComponents/ReactDemo.js | 21 - .../src/components/mdxComponents/Sandbox.js | 23 - .../src/components/mdxComponents/Sandbox.tsx | 25 + .../src/components/mdxComponents/index.js | 2 - .../static/src/components/sidebar/index.js | 1 + packages/static/tsconfig.json | 100 + packages/storybook-static/.gitignore | 3 + packages/storybook-static/.storybook/main.js | 24 + .../.storybook/manager-head.html | 1 + .../storybook-static/.storybook/manager.js | 25 + .../.storybook/preview-head.html | 3 + .../storybook-static/.storybook/preview.js | 14 + packages/storybook-static/package.json | 40 + .../babylonjs/Basic/animation.stories.js | 98 + .../babylonjs/Basic/babylonBasic.stories.js | 45 + .../babylonjs/Basic/contextBridge.stories.js | 52 + .../babylonjs/Basic/customMeshes.stories.js | 76 + .../babylonjs/Basic/dynamicTerrain.stories.js | 45 + .../babylonjs/Basic/edgesRendering.stories.js | 36 + .../babylonjs/Basic/engineView.stories.js | 102 + .../babylonjs/Basic/fromInstance.stories.js | 56 + .../stories/babylonjs/Basic/gizmo.stories.js | 30 + .../babylonjs/Basic/gizmoManager.stories.js | 54 + .../babylonjs/Basic/instances.stories.js | 90 + .../stories/babylonjs/Basic/portal.stories.js | 54 + .../stories/babylonjs/Basic/shapes.stories.js | 97 + .../stories/babylonjs/Basic/skybox.stories.js | 59 + .../Basic/snippetMaterial.stories.js | 96 + .../babylonjs/Basic/toggleMesh.stories.js | 72 + .../babylonjs/Basic/toggleScene.stories.js | 90 + .../babylonjs/Basic/transformNode.stories.js | 67 + .../babylonjs/Basic/viewport.stories.js | 98 + .../babylonjs/Behaviors/dragNdrop.stories.js | 72 + .../Behaviors/pointerDragBehavior.stories.js | 42 + .../stories/babylonjs/GUI/grid.stories.js | 79 + .../stories/babylonjs/GUI/gui.stories.js | 146 + .../stories/babylonjs/GUI/html.stories.js | 64 + .../babylonjs/GUI/with2DGUI.stories.js | 248 + .../stories/babylonjs/Hooks/hooks.stories.js | 109 + .../babylonjs/Hooks/more-hooks.stories.js | 53 + .../Hooks/useAssetManager.stories.js | 111 + .../babylonjs/Hooks/useClick.stories.js | 51 + .../babylonjs/Hooks/useHover.stories.js | 70 + .../stories/babylonjs/Integrations/Tunnel.tsx | 81 + .../Integrations/chromaJS.stories.js | 140 + .../babylonjs/Integrations/gsap.stories.js | 82 + .../Integrations/pixi-demo/VaporWave.js | 47 + .../babylonjs/Integrations/pixi-demo/block.js | 64 + .../Integrations/pixi-demo/pixi-styles.js | 31 + .../Integrations/pixi-demo/shaders/index.js | 306 + .../babylonjs/Integrations/pixi-demo/slide.js | 126 + .../babylonjs/Integrations/pixi-demo/store.js | 78 + .../Integrations/pixi-demo/styles.css | 29 + .../Integrations/pixi-render.stories.js | 142 + .../Integrations/reactSpring.stories.js | 273 + .../babylonjs/Integrations/tunnel.stories.js | 151 + .../Materials/grid-material.stories.js | 99 + .../babylonjs/Models/model-loader.stories.js | 94 + .../babylonjs/Models/model-lookat.stories.js | 59 + .../stories/babylonjs/Models/model.stories.js | 105 + .../NonDeclarative/nonDeclarative.stories.js | 132 + .../babylonjs/Physics/physics.stories.js | 89 + .../PostProcess/imagePostProcess.stories.js | 80 + .../babylonjs/PostProcess/pipeline.stories.js | 22 + .../babylonjs/ScaledModelWithProgress.js | 42 + .../babylonjs/SpecialFX/glow-layer.stories.js | 85 + .../SpecialFX/highlight-layer.stories.js | 65 + .../SpecialFX/multi-glow-layer.stories.js | 144 + .../Textures/fire-procedural.stories.js | 53 + .../Textures/fresnelparameters.stories.js | 150 + .../Textures/image-texture.stories.js | 91 + .../Textures/pbr-configuration.stories.js | 122 + .../stories/babylonjs/Textures/pbr.stories.js | 95 + .../stories/babylonjs/VR/withVr.stories.js | 103 + packages/storybook-static/stories/style.css | 25 + .../assets/images/building.jpeg | Bin 0 -> 321865 bytes .../storyboard-site/assets/images/ph1.jpg | Bin 0 -> 208054 bytes .../storyboard-site/assets/images/ph3.jpg | Bin 0 -> 234298 bytes .../photo-1515036551567-bf1198cccc35.jpeg | Bin 0 -> 246790 bytes .../photo-1516245266743-983948b98d53.jpeg | Bin 0 -> 164631 bytes .../photo-1519608487953-e999c86e7455.jpeg | Bin 0 -> 237162 bytes .../photo-1533577116850-9cc66cad8a9b.jpeg | Bin 0 -> 535613 bytes .../images/photo-1548191265-cc70d3d45ba1.jpeg | Bin 0 -> 467412 bytes .../storyboard-site/assets/kitti/000000.bin | Bin 0 -> 1846144 bytes .../storyboard-site/assets/models/atom.glb | Bin 0 -> 220564 bytes .../assets/textures/LateSunset.3dl | 4916 +++++++++++++++++ .../assets/textures/SpecularHDR.dds | Bin 0 -> 16777376 bytes .../assets/textures/TropicalSunnyDay_nx.jpg | Bin 0 -> 657906 bytes .../assets/textures/TropicalSunnyDay_ny.jpg | Bin 0 -> 228116 bytes .../assets/textures/TropicalSunnyDay_nz.jpg | Bin 0 -> 758742 bytes .../assets/textures/TropicalSunnyDay_px.jpg | Bin 0 -> 630110 bytes .../assets/textures/TropicalSunnyDay_py.jpg | Bin 0 -> 656687 bytes .../assets/textures/TropicalSunnyDay_pz.jpg | Bin 0 -> 677425 bytes .../assets/textures/albedo.png | Bin 0 -> 601160 bytes .../assets/textures/environment.dds | Bin 0 -> 1048736 bytes .../storyboard-site/assets/textures/grass.png | Bin 0 -> 633903 bytes .../assets/textures/reflectivity.png | Bin 0 -> 96458 bytes .../storyboard-site/favicon.ico | Bin 0 -> 1150 bytes .../storyboard-site/manifest.json | 15 + yarn.lock | 3175 ++++++++++- 145 files changed, 15617 insertions(+), 566 deletions(-) create mode 100644 .prettierrc create mode 100644 packages/gatsby-mdx-codesandbox/.gitignore create mode 100644 packages/gatsby-mdx-codesandbox/README.md create mode 100644 packages/gatsby-mdx-codesandbox/package.json rename packages/{static => gatsby-mdx-codesandbox/src}/codesandbox-template/.codesandbox/workspace.json (100%) rename packages/{static => gatsby-mdx-codesandbox/src}/codesandbox-template/.prettierrc (100%) rename packages/{static => gatsby-mdx-codesandbox/src}/codesandbox-template/package.json (94%) rename packages/{static => gatsby-mdx-codesandbox/src}/codesandbox-template/src/App.tsx (100%) rename packages/{static => gatsby-mdx-codesandbox/src}/codesandbox-template/src/index.tsx (100%) rename packages/{static => gatsby-mdx-codesandbox/src}/codesandbox-template/src/styles.css (100%) rename packages/{static => gatsby-mdx-codesandbox/src}/codesandbox-template/tsconfig.json (100%) create mode 100644 packages/gatsby-mdx-codesandbox/src/index.ts create mode 100644 packages/gatsby-mdx-codesandbox/src/mdast.d.ts create mode 100644 packages/gatsby-mdx-codesandbox/tsconfig.json create mode 100644 packages/react-codesandbox-viewer/.gitignore create mode 100644 packages/react-codesandbox-viewer/.storybook/main.js create mode 100644 packages/react-codesandbox-viewer/.storybook/preview.js create mode 100644 packages/react-codesandbox-viewer/package.json create mode 100644 packages/react-codesandbox-viewer/src/App.jsx create mode 100644 packages/react-codesandbox-viewer/src/App.tsx create mode 100644 packages/react-codesandbox-viewer/src/Demo.stories.tsx create mode 100644 packages/react-codesandbox-viewer/src/Demo.tsx create mode 100644 packages/react-codesandbox-viewer/src/cookieHook.ts create mode 100644 packages/react-codesandbox-viewer/src/index.ts create mode 100644 packages/react-codesandbox-viewer/tsconfig.json create mode 100644 packages/static/content/3-hello-react-babylonjs/1-react-boiler-plate/HelloReact.tsx rename packages/static/content/3-hello-react-babylonjs/{1-react-boiler-plate.mdx => 1-react-boiler-plate/index.mdx} (65%) rename packages/static/content/3-hello-react-babylonjs/{2-react-with-imperitive-babylonjs.mdx => 2-react-with-imperitive-babylonjs/FullImperitive.tsx} (51%) create mode 100644 packages/static/content/3-hello-react-babylonjs/2-react-with-imperitive-babylonjs/WithHooks.tsx create mode 100644 packages/static/content/3-hello-react-babylonjs/2-react-with-imperitive-babylonjs/index.mdx delete mode 100644 packages/static/content/3-hello-react-babylonjs/3-react-with-declarative-babylonjs.mdx create mode 100644 packages/static/content/3-hello-react-babylonjs/3-react-with-declarative-babylonjs/BasicScene.tsx create mode 100644 packages/static/content/3-hello-react-babylonjs/3-react-with-declarative-babylonjs/Declarative.tsx create mode 100644 packages/static/content/3-hello-react-babylonjs/3-react-with-declarative-babylonjs/index.mdx rename packages/static/content/3-hello-react-babylonjs/{4-adding-animation-and-color.mdx => 4-adding-animation-and-color/Colorful.tsx} (55%) create mode 100644 packages/static/content/3-hello-react-babylonjs/4-adding-animation-and-color/index.mdx delete mode 100644 packages/static/src/components/mdxComponents/ReactDemo.js delete mode 100644 packages/static/src/components/mdxComponents/Sandbox.js create mode 100644 packages/static/src/components/mdxComponents/Sandbox.tsx create mode 100644 packages/static/tsconfig.json create mode 100644 packages/storybook-static/.gitignore create mode 100644 packages/storybook-static/.storybook/main.js create mode 100644 packages/storybook-static/.storybook/manager-head.html create mode 100644 packages/storybook-static/.storybook/manager.js create mode 100644 packages/storybook-static/.storybook/preview-head.html create mode 100644 packages/storybook-static/.storybook/preview.js create mode 100644 packages/storybook-static/package.json create mode 100644 packages/storybook-static/stories/babylonjs/Basic/animation.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Basic/babylonBasic.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Basic/contextBridge.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Basic/customMeshes.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Basic/dynamicTerrain.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Basic/edgesRendering.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Basic/engineView.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Basic/fromInstance.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Basic/gizmo.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Basic/gizmoManager.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Basic/instances.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Basic/portal.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Basic/shapes.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Basic/skybox.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Basic/snippetMaterial.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Basic/toggleMesh.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Basic/toggleScene.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Basic/transformNode.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Basic/viewport.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Behaviors/dragNdrop.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Behaviors/pointerDragBehavior.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/GUI/grid.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/GUI/gui.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/GUI/html.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/GUI/with2DGUI.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Hooks/hooks.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Hooks/more-hooks.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Hooks/useAssetManager.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Hooks/useClick.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Hooks/useHover.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Integrations/Tunnel.tsx create mode 100644 packages/storybook-static/stories/babylonjs/Integrations/chromaJS.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Integrations/gsap.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/VaporWave.js create mode 100644 packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/block.js create mode 100644 packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/pixi-styles.js create mode 100644 packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/shaders/index.js create mode 100644 packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/slide.js create mode 100644 packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/store.js create mode 100644 packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/styles.css create mode 100644 packages/storybook-static/stories/babylonjs/Integrations/pixi-render.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Integrations/reactSpring.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Integrations/tunnel.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Materials/grid-material.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Models/model-loader.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Models/model-lookat.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Models/model.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/NonDeclarative/nonDeclarative.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Physics/physics.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/PostProcess/imagePostProcess.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/PostProcess/pipeline.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/ScaledModelWithProgress.js create mode 100644 packages/storybook-static/stories/babylonjs/SpecialFX/glow-layer.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/SpecialFX/highlight-layer.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/SpecialFX/multi-glow-layer.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Textures/fire-procedural.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Textures/fresnelparameters.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Textures/image-texture.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Textures/pbr-configuration.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/Textures/pbr.stories.js create mode 100644 packages/storybook-static/stories/babylonjs/VR/withVr.stories.js create mode 100644 packages/storybook-static/stories/style.css create mode 100755 packages/storybook-static/storyboard-site/assets/images/building.jpeg create mode 100644 packages/storybook-static/storyboard-site/assets/images/ph1.jpg create mode 100644 packages/storybook-static/storyboard-site/assets/images/ph3.jpg create mode 100755 packages/storybook-static/storyboard-site/assets/images/photo-1515036551567-bf1198cccc35.jpeg create mode 100755 packages/storybook-static/storyboard-site/assets/images/photo-1516245266743-983948b98d53.jpeg create mode 100755 packages/storybook-static/storyboard-site/assets/images/photo-1519608487953-e999c86e7455.jpeg create mode 100755 packages/storybook-static/storyboard-site/assets/images/photo-1533577116850-9cc66cad8a9b.jpeg create mode 100755 packages/storybook-static/storyboard-site/assets/images/photo-1548191265-cc70d3d45ba1.jpeg create mode 100644 packages/storybook-static/storyboard-site/assets/kitti/000000.bin create mode 100644 packages/storybook-static/storyboard-site/assets/models/atom.glb create mode 100644 packages/storybook-static/storyboard-site/assets/textures/LateSunset.3dl create mode 100644 packages/storybook-static/storyboard-site/assets/textures/SpecularHDR.dds create mode 100644 packages/storybook-static/storyboard-site/assets/textures/TropicalSunnyDay_nx.jpg create mode 100644 packages/storybook-static/storyboard-site/assets/textures/TropicalSunnyDay_ny.jpg create mode 100644 packages/storybook-static/storyboard-site/assets/textures/TropicalSunnyDay_nz.jpg create mode 100644 packages/storybook-static/storyboard-site/assets/textures/TropicalSunnyDay_px.jpg create mode 100644 packages/storybook-static/storyboard-site/assets/textures/TropicalSunnyDay_py.jpg create mode 100644 packages/storybook-static/storyboard-site/assets/textures/TropicalSunnyDay_pz.jpg create mode 100644 packages/storybook-static/storyboard-site/assets/textures/albedo.png create mode 100644 packages/storybook-static/storyboard-site/assets/textures/environment.dds create mode 100644 packages/storybook-static/storyboard-site/assets/textures/grass.png create mode 100644 packages/storybook-static/storyboard-site/assets/textures/reflectivity.png create mode 100644 packages/storybook-static/storyboard-site/favicon.ico create mode 100644 packages/storybook-static/storyboard-site/manifest.json diff --git a/.gitignore b/.gitignore index 28f1ba75..dd8ace40 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules -.DS_Store \ No newline at end of file +.DS_Store +.parcel-cache diff --git a/.prettierignore b/.prettierignore index 1a8daea8..524a0696 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,4 @@ dist storybook-static -.cache \ No newline at end of file +.cache +.parcel-cache \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..a2a24e02 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,16 @@ +{ + "printWidth": 100, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "es5", + "semi": false, + "overrides": [ + { + "files": ["*.md", "*.mdx"], + "options": { + "printWidth": 80, + "proseWrap": "always" + } + } + ] +} diff --git a/package.json b/package.json index 5e47daae..322e385e 100644 --- a/package.json +++ b/package.json @@ -12,10 +12,13 @@ "prepare": "husky install" }, "devDependencies": { + "@parcel/packager-ts": "^2.2.0", + "@parcel/transformer-typescript-types": "^2.2.0", "husky": ">=6", "lint-staged": ">=10", "prettier": "^2.5.1", - "prettier-plugin-organize-imports": "^2.3.4" + "prettier-plugin-organize-imports": "^2.3.4", + "typescript": ">=3.0.0" }, "lint-staged": { "*.{js,css,md,mdx,jsx,tsx,ts,json}": "prettier --write" diff --git a/packages/gatsby-mdx-codesandbox/.gitignore b/packages/gatsby-mdx-codesandbox/.gitignore new file mode 100644 index 00000000..76add878 --- /dev/null +++ b/packages/gatsby-mdx-codesandbox/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist \ No newline at end of file diff --git a/packages/gatsby-mdx-codesandbox/README.md b/packages/gatsby-mdx-codesandbox/README.md new file mode 100644 index 00000000..52173009 --- /dev/null +++ b/packages/gatsby-mdx-codesandbox/README.md @@ -0,0 +1,5 @@ +# gatsby-mdx-codesandbox + +`[code:HelloWorld.tsx]` will prettify and inline the code for the file named `HelloWorld.tsx` in the same directory as your `mdx` file. + +`[demo:HelloWorld.tsx]` will show a Codesandbox iframe using the template you have specified. When running on localhost, it will also show run the component locally, presumably using local packages. diff --git a/packages/gatsby-mdx-codesandbox/package.json b/packages/gatsby-mdx-codesandbox/package.json new file mode 100644 index 00000000..f8c1ed62 --- /dev/null +++ b/packages/gatsby-mdx-codesandbox/package.json @@ -0,0 +1,36 @@ +{ + "name": "gatsby-mdx-codesandbox", + "version": "0.0.1", + "source": "./src/index.ts", + "main": "dist/index.js", + "engines": { + "node": ">12" + }, + "types": "dist/index.d.ts", + "license": "MIT", + "scripts": { + "build": "parcel build", + "watch": "chokidar 'src/*' -c 'yarn build'" + }, + "dependencies": { + "@s-libs/micro-dash": "12", + "@types/prettier": "^2.4.3", + "codesandbox": "^2.2.3", + "prettier": "^2.5.1", + "remark-codesandbox": "^0.10.0", + "typescript": "^4.5.4", + "unist-util-visit": "2" + }, + "peerDependencies": { + "gatsby": "^4.0", + "react-codesandbox-viewer": "*" + }, + "devDependencies": { + "@babel/core": "^7.16.7", + "@types/prettier": "^2.4.3", + "babel-loader": "^8.2.3", + "parcel": "^2.2.0", + "type-fest": "^2.9.0", + "typescript": "^4.5.4" + } +} diff --git a/packages/static/codesandbox-template/.codesandbox/workspace.json b/packages/gatsby-mdx-codesandbox/src/codesandbox-template/.codesandbox/workspace.json similarity index 100% rename from packages/static/codesandbox-template/.codesandbox/workspace.json rename to packages/gatsby-mdx-codesandbox/src/codesandbox-template/.codesandbox/workspace.json diff --git a/packages/static/codesandbox-template/.prettierrc b/packages/gatsby-mdx-codesandbox/src/codesandbox-template/.prettierrc similarity index 100% rename from packages/static/codesandbox-template/.prettierrc rename to packages/gatsby-mdx-codesandbox/src/codesandbox-template/.prettierrc diff --git a/packages/static/codesandbox-template/package.json b/packages/gatsby-mdx-codesandbox/src/codesandbox-template/package.json similarity index 94% rename from packages/static/codesandbox-template/package.json rename to packages/gatsby-mdx-codesandbox/src/codesandbox-template/package.json index 8f4ae712..74b2d1f4 100644 --- a/packages/static/codesandbox-template/package.json +++ b/packages/gatsby-mdx-codesandbox/src/codesandbox-template/package.json @@ -1,5 +1,5 @@ { - "name": "react-babylonjs-codesandbox", + "name": "@react-babylonjs/codesandbox-demo", "version": "1.0.0", "description": "", "keywords": [], diff --git a/packages/static/codesandbox-template/src/App.tsx b/packages/gatsby-mdx-codesandbox/src/codesandbox-template/src/App.tsx similarity index 100% rename from packages/static/codesandbox-template/src/App.tsx rename to packages/gatsby-mdx-codesandbox/src/codesandbox-template/src/App.tsx diff --git a/packages/static/codesandbox-template/src/index.tsx b/packages/gatsby-mdx-codesandbox/src/codesandbox-template/src/index.tsx similarity index 100% rename from packages/static/codesandbox-template/src/index.tsx rename to packages/gatsby-mdx-codesandbox/src/codesandbox-template/src/index.tsx diff --git a/packages/static/codesandbox-template/src/styles.css b/packages/gatsby-mdx-codesandbox/src/codesandbox-template/src/styles.css similarity index 100% rename from packages/static/codesandbox-template/src/styles.css rename to packages/gatsby-mdx-codesandbox/src/codesandbox-template/src/styles.css diff --git a/packages/static/codesandbox-template/tsconfig.json b/packages/gatsby-mdx-codesandbox/src/codesandbox-template/tsconfig.json similarity index 100% rename from packages/static/codesandbox-template/tsconfig.json rename to packages/gatsby-mdx-codesandbox/src/codesandbox-template/tsconfig.json diff --git a/packages/gatsby-mdx-codesandbox/src/index.ts b/packages/gatsby-mdx-codesandbox/src/index.ts new file mode 100644 index 00000000..399fe34f --- /dev/null +++ b/packages/gatsby-mdx-codesandbox/src/index.ts @@ -0,0 +1,370 @@ +import { forEach } from '@s-libs/micro-dash' +import { existsSync, readFileSync } from 'fs' +import { basename, dirname, resolve } from 'path' +import prettier, { Options as PrettierOptions } from 'prettier' +import { env } from 'process' +import { CSSProperties } from 'react' +//@ts-ignore Can't figure out ambient module declaration for a subpackage +import codesandbox from 'remark-codesandbox/gatsby' +import { PartialDeep, SetOptional } from 'type-fest' +import * as ts from 'typescript' +import visit from 'unist-util-visit' +import type { Code, Content, Jsx, LinkReference, Parent, Tsx } from './mdast' + +type ShortcodeNames = 'demo' | 'code' + +const IS_DEVELOPMENT_MODE = env['NODE_ENV'] === 'development' + +type MaybeParent = SetOptional + +type CustomTemplate = { + extends: string + entry: string +} + +export type PluginOptions = { + development: { + style: CSSProperties + } + prettier: PrettierOptions + codesandbox: { + mode: 'iframe' | 'button' | 'meta' + defaultQuery: CodeSandBoxQuery + customTemplates: { + [_: string]: CustomTemplate + default: CustomTemplate + } + } +} + +type CodeSandBoxQuery = { + template: string + fontsize: string + hidenavigation: '0' | '1' + theme: 'dark' | 'light' + entry: string + module: string + style: string +} + +type MarkdownAST = Parent + +type GatsbyMdxNodeId = string + +type GatsbyMdxNode = { + id: GatsbyMdxNodeId + children: GatsbyMdxNode[] + parent: GatsbyMdxNodeId + internal: { + content: any + type: `Mdx` | 'File' + } + frontmatter: { + title: string + [key: string]: string + } + excerpt: string + exports: any + rawBody: string +} + +type GatsbyMdxFileNode = GatsbyMdxNode & { + internal: GatsbyMdxNode['internal'] & { + type: 'File' + } + fileAbsolutePath: string +} + +type GatsbyMdxPluginMeta = { + markdownAST: MarkdownAST + markdownNode: GatsbyMdxFileNode +} + +type GatsbyMdxPlugin = ( + meta: GatsbyMdxPluginMeta, + pluginOptions: PartialDeep +) => Promise + +const guid = (() => { + let id = +new Date() + return () => `g${++id}` +})() + +const plugin: GatsbyMdxPlugin = async (meta, pluginOptions) => { + const _options: PluginOptions = { + development: { + style: (pluginOptions?.development?.style as CSSProperties | undefined) || { + marginTop: '20px', + padding: '16px', + border: '15px solid rgb(245, 247, 249)', + backgroundColor: 'black', + color: 'white', + marginBottom: '20px', + }, + }, + prettier: { + jsxBracketSameLine: false, + singleQuote: true, + tabWidth: 2, + trailingComma: 'es5', + semi: false, + printWidth: 80, + proseWrap: 'always', + parser: 'typescript', + }, + codesandbox: { + mode: pluginOptions?.codesandbox?.mode || 'meta', + defaultQuery: { + template: 'default', + entry: 'src/App.tsx', + fontsize: '14px', + hidenavigation: '0', + theme: 'dark', + module: '', + style: '', + }, + customTemplates: { + //@ts-ignore + default: (pluginOptions.codesandbox?.customTemplates?.default as + | CustomTemplate + | undefined) || { + extends: `file:${__dirname}/../src/codesandbox-template`, + entry: 'src/App.tsx', + }, + ...pluginOptions.codesandbox?.customTemplates, + }, + }, + } + // console.log('options', _options) + const { markdownAST, markdownNode } = meta + + // Import the Demo component + { + const node: Content = { + type: 'import', + value: `import {Demo} from 'react-codesandbox-viewer'`, + } + markdownAST.children.unshift(node) + console.log(`Adding: ${node.value}`) + } + + const seen: { [_: string]: boolean } = {} + + const isCodeOrDemo = (type: string): type is ShortcodeNames => { + const shortcodeNames: ShortcodeNames[] = ['code', 'demo'] + return shortcodeNames.includes(type as ShortcodeNames) + } + + const isLinkReference = (node: Content): node is LinkReference => { + return node.type === 'linkReference' + } + + const isParent = (node: MaybeParent): node is Parent => { + return !!node.children + } + + const isSoloChild = (node: Parent) => { + return node.children.length === 1 + } + + const ALLOWED_EXT = ['tsx'] + const isAllowedExt = (ext: string): ext is Tsx['type'] => ALLOWED_EXT.includes(ext) + + const promises: Promise[] = [] + visit(markdownAST, 'paragraph', (paragraphNode: MaybeParent, idx) => { + promises.push( + (async () => { + // Only process paragraph nodes + if (!isParent(paragraphNode)) return + + // Only allow the shortcode by itself in a paragraph + if (!isSoloChild(paragraphNode)) return + + // The [shortcode] syntax shows up as a linkReference node - filter out all others + const [linkRefNode] = paragraphNode.children + if (!isLinkReference(linkRefNode)) return + + // The 'label' is the shortcode. Filter out any empty links + const { label } = linkRefNode + if (!label) return + + // Shortcode format: (demo|code):fname.ext[?params...] + const [shortCodeType, fnameWithQuery] = label.split(':') + const [fname, querystring] = fnameWithQuery.split('?') + const [moduleName, ext] = fname.split('.') + + // Filter out any shortcode that is not ours + if (!isCodeOrDemo(shortCodeType)) return + + // Error on any file type not currently supported + if (!isAllowedExt(ext)) { + throw new Error(`${fname} is not supported. Only jsx and tsx are supported.`) + } + + // Copy default values into query + const query = new URLSearchParams() + forEach(_options.codesandbox.defaultQuery, (v, k) => { + if (!!v) query.set(k, v) + }) + + // Calculate the template name + const parsed = new URLSearchParams(querystring) + const templateName = parsed.get('template') || query.get('template') + parsed.delete('template') + query.delete('template') + console.log(`Template name is ${templateName}`) + + // Overwrite defaults with tempalte defaults if available + const { customTemplates } = _options.codesandbox + if (templateName && customTemplates[templateName]) { + forEach(customTemplates[templateName], (v, k) => { + if (!!v) query.set(k, v) + }) + } + + // Overwrite default value union with values specified on querystring + parsed.forEach((v, k) => { + if (!!v) query.set(k, v) + }) + + // Compute the new querystring + const computedQuerystring = decodeURIComponent(query.toString()) + console.log(`full query: ${templateName}?${computedQuerystring}`) + + // Calculate the full path to the code file name and error out if it doesn't exist + const { fileAbsolutePath } = markdownNode + const absoluteDir = dirname(fileAbsolutePath) + const codeFileAbsolutePath = resolve(absoluteDir, fname) + if (!existsSync(codeFileAbsolutePath)) { + throw new Error(`${fname} was not found at ${codeFileAbsolutePath}.`) + } + console.log(codeFileAbsolutePath) + + // Read the source file + const source = readFileSync(codeFileAbsolutePath, { encoding: 'utf-8' }) + + // Prettify it so it displays nicely in the site + const lines = [ + `// ${basename(codeFileAbsolutePath)}`, + '', + ...(IS_DEVELOPMENT_MODE + ? [ + `/* `, + ` ********* WARNING ********`, + ` * THIS CODE WAS LAUNCHED FROM LOCALHOST.`, + ` * LOCAL PACKAGES MAY NOT MATCH THE DEPENDENCIES`, + ` * USED IN THIS SANDBOX.`, + ` * `, + ` * TEST SANDBOX FOR BACKWARD COMPATIBLITY IF DESIRED.`, + ` ********* WARNING ********`, + ` */`, + '', + ] + : []), + source, + ] + const unformattedTsx = lines.join('\n') + const formattedSourceTsx = prettier.format(unformattedTsx, _options.prettier) + + // Transpile to JS + const formattedSourceJsx = prettier.format( + ts.transpileModule(unformattedTsx, { + compilerOptions: { + strict: false, + esModuleInterop: true, + jsx: ts.JsxEmit.Preserve, + module: ts.ModuleKind.ESNext, + }, + }).outputText, + _options.prettier + ) + + // Generate the sandbox URL link + const codesandboxUrl = await (async () => { + const node: Code = { + type: 'code', + lang: 'tsx', + meta: `codesandbox=${templateName}?${computedQuerystring}`, + value: source, + } + await codesandbox({ ...meta, markdownAST: node }, _options.codesandbox) + + // console.log(JSON.stringify(node, null, 2)) + const url = (node.data?.hProperties as { dataCodesandboxUrl?: string }) + ?.dataCodesandboxUrl + if (!url) { + throw new Error(`Failed to create sandbox URL from ${node.meta}`) + } + // console.log(`converted node to sandbox url ${url}`) + return url + })() + + switch (shortCodeType) { + // The 'code' case is where we do normal inline code + case 'code': + { + // Typescript kung fu to convert to a Code node + ;((node: Code) => { + node.type = 'code' + node.lang = 'tsx' + // node.meta = `codesandbox=${templateName}?${computedQuerystring}` + node.value = formattedSourceTsx + console.log(`converted node to code`) + // console.log(JSON.stringify(node, null, 2)) + })(linkRefNode as unknown as Code) + } + break + + // The 'demo' case is a codesandbox and, if in dev/localhost mode, a working demo running aginst local code + case 'demo': + { + // Wire up demo harness + const importSymbol = `Component_${moduleName}` + + // Splice in a run container before the code listing, warn if in dev mode + const demoComponent = [ + ``, + ].join('\n') + console.log(demoComponent) + + // Typescript kung fu to convert to a Code node + ;((node: Jsx) => { + node.type = 'jsx' + node.value = demoComponent + console.log(`converted node to runtime container`) + // console.log(JSON.stringify(node, null, 2)) + })(linkRefNode as unknown as Jsx) + + // Insert an import if this component hasn't been seen yet + if (!seen[moduleName]) { + const node: Content = { + type: 'import', + value: `import ${importSymbol} from './${moduleName}'`, + } + markdownAST.children.unshift(node) + console.log(`Adding: ${node.value}`) + seen[moduleName] = true + } + } + break + } + })() + ) + }) + await Promise.all(promises) + + // console.log('calling codesandbox', _options.codesandbox) + + await codesandbox(meta, _options.codesandbox) + // console.log(JSON.stringify(markdownAST, null, 2)) + return markdownAST +} + +module.exports = plugin diff --git a/packages/gatsby-mdx-codesandbox/src/mdast.d.ts b/packages/gatsby-mdx-codesandbox/src/mdast.d.ts new file mode 100644 index 00000000..d3969ec8 --- /dev/null +++ b/packages/gatsby-mdx-codesandbox/src/mdast.d.ts @@ -0,0 +1,371 @@ +// Type definitions for Mdast 3.0 +// Project: https://github.com/syntax-tree/mdast, https://github.com/wooorm/mdast +// Definitions by: Christian Murphy +// Jun Lu +// Remco Haszing +// Titus Wormer +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 3.0 + +import { Literal as UnistLiteral, Node, Parent as UnistParent } from "unist"; + +export type AlignType = "left" | "right" | "center" | null; + +export type ReferenceType = "shortcut" | "collapsed" | "full"; + +/** + * This map registers all node types that may be used where markdown block content is accepted. + * + * These types are accepted inside block quotes, list items, footnotes, and roots. + * + * This interface can be augmented to register custom node types. + * + * @example + * declare module 'mdast' { + * interface BlockContentMap { + * // Allow using math nodes defined by `remark-math`. + * math: Math; + * } + * } + */ +export interface BlockContentMap { + tsx: Tsx; + jsx: Jsx; + import: Import; + paragraph: Paragraph; + heading: Heading; + thematicbreak: ThematicBreak; + blockquote: Blockquote; + list: List; + table: Table; + html: HTML; + code: Code; +} + +/** + * This map registers all frontmatter node types. + * + * This interface can be augmented to register custom node types. + * + * @example + * declare module 'mdast' { + * interface FrontmatterContentMap { + * // Allow using toml nodes defined by `remark-frontmatter`. + * toml: TOML; + * } + * } + */ +export interface FrontmatterContentMap { + yaml: YAML; +} + +/** + * This map registers all node definition types. + * + * This interface can be augmented to register custom node types. + * + * @example + * declare module 'mdast' { + * interface DefinitionContentMap { + * custom: Custom; + * } + * } + */ +export interface DefinitionContentMap { + definition: Definition; + footnoteDefinition: FootnoteDefinition; +} + +/** + * This map registers all node types that are acceptable in a static phrasing context. + * + * This interface can be augmented to register custom node types in a phrasing context, including links and link + * references. + * + * @example + * declare module 'mdast' { + * interface StaticPhrasingContentMap { + * mdxJsxTextElement: MDXJSXTextElement; + * } + * } + */ +export interface StaticPhrasingContentMap { + text: Text; + emphasis: Emphasis; + strong: Strong; + delete: Delete; + html: HTML; + inlinecode: InlineCode; + break: Break; + image: Image; + imagereference: ImageReference; + footnote: Footnote; + footnotereference: FootnoteReference; +} + +/** + * This map registers all node types that are acceptable in a (interactive) phrasing context (so not in links). + * + * This interface can be augmented to register custom node types in a phrasing context, excluding links and link + * references. + * + * @example + * declare module 'mdast' { + * interface PhrasingContentMap { + * custom: Custom; + * } + * } + */ +export interface PhrasingContentMap extends StaticPhrasingContentMap { + link: Link; + linkReference: LinkReference; +} + +/** + * This map registers all node types that are acceptable inside lists. + * + * This interface can be augmented to register custom node types that are acceptable inside lists. + * + * @example + * declare module 'mdast' { + * interface ListContentMap { + * custom: Custom; + * } + * } + */ +export interface ListContentMap { + listItem: ListItem; +} + +/** + * This map registers all node types that are acceptable inside tables (not table cells). + * + * This interface can be augmented to register custom node types that are acceptable inside tables. + * + * @example + * declare module 'mdast' { + * interface TableContentMap { + * custom: Custom; + * } + * } + */ +export interface TableContentMap { + tableRow: TableRow; +} + +/** + * This map registers all node types that are acceptable inside tables rows (not table cells). + * + * This interface can be augmented to register custom node types that are acceptable inside table rows. + * + * @example + * declare module 'mdast' { + * interface RowContentMap { + * custom: Custom; + * } + * } + */ +export interface RowContentMap { + tableCell: TableCell; +} + +export type Content = + | TopLevelContent + | ListContent + | TableContent + | RowContent + | PhrasingContent; + +export type TopLevelContent = + | BlockContent + | FrontmatterContent + | DefinitionContent; + +export type BlockContent = BlockContentMap[keyof BlockContentMap]; + +export type FrontmatterContent = + FrontmatterContentMap[keyof FrontmatterContentMap]; + +export type DefinitionContent = + DefinitionContentMap[keyof DefinitionContentMap]; + +export type ListContent = ListContentMap[keyof ListContentMap]; + +export type TableContent = TableContentMap[keyof TableContentMap]; + +export type RowContent = RowContentMap[keyof RowContentMap]; + +export type PhrasingContent = PhrasingContentMap[keyof PhrasingContentMap]; + +export type StaticPhrasingContent = + StaticPhrasingContentMap[keyof StaticPhrasingContentMap]; + +export interface Parent extends UnistParent { + children: Content[]; +} + +export interface Literal extends UnistLiteral { + value: string; +} + +export interface Root extends Parent { + type: "root"; +} + +export interface Tsx extends Literal { + type: "tsx"; +} +export interface Jsx extends Literal { + type: "jsx"; +} + +export interface Import extends Literal { + type: "import"; +} + +export interface Paragraph extends Parent { + type: "paragraph"; + children: PhrasingContent[]; +} + +export interface Heading extends Parent { + type: "heading"; + depth: 1 | 2 | 3 | 4 | 5 | 6; + children: PhrasingContent[]; +} + +export interface ThematicBreak extends Node { + type: "thematicBreak"; +} + +export interface Blockquote extends Parent { + type: "blockquote"; + children: Array; +} + +export interface List extends Parent { + type: "list"; + ordered?: boolean | null | undefined; + start?: number | null | undefined; + spread?: boolean | null | undefined; + children: ListContent[]; +} + +export interface ListItem extends Parent { + type: "listItem"; + checked?: boolean | null | undefined; + spread?: boolean | null | undefined; + children: Array; +} + +export interface Table extends Parent { + type: "table"; + align?: AlignType[] | null | undefined; + children: TableContent[]; +} + +export interface TableRow extends Parent { + type: "tableRow"; + children: RowContent[]; +} + +export interface TableCell extends Parent { + type: "tableCell"; + children: PhrasingContent[]; +} + +export interface HTML extends Literal { + type: "html"; +} + +export interface Code extends Literal { + type: "code"; + lang?: string | null | undefined; + meta?: string | null | undefined; +} + +export interface YAML extends Literal { + type: "yaml"; +} + +export interface Definition extends Node, Association, Resource { + type: "definition"; +} + +export interface FootnoteDefinition extends Parent, Association { + type: "footnoteDefinition"; + children: Array; +} + +export interface Text extends Literal { + type: "text"; +} + +export interface Emphasis extends Parent { + type: "emphasis"; + children: PhrasingContent[]; +} + +export interface Strong extends Parent { + type: "strong"; + children: PhrasingContent[]; +} + +export interface Delete extends Parent { + type: "delete"; + children: PhrasingContent[]; +} + +export interface InlineCode extends Literal { + type: "inlineCode"; +} + +export interface Break extends Node { + type: "break"; +} + +export interface Link extends Parent, Resource { + type: "link"; + children: StaticPhrasingContent[]; +} + +export interface Image extends Node, Resource, Alternative { + type: "image"; +} + +export interface LinkReference extends Parent, Reference { + type: "linkReference"; + children: StaticPhrasingContent[]; +} + +export interface ImageReference extends Node, Reference, Alternative { + type: "imageReference"; +} + +export interface Footnote extends Parent { + type: "footnote"; + children: PhrasingContent[]; +} + +export interface FootnoteReference extends Node, Association { + type: "footnoteReference"; +} + +// Mixin +export interface Resource { + url: string; + title?: string | null | undefined; +} + +export interface Association { + identifier: string; + label?: string | null | undefined; +} + +export interface Reference extends Association { + referenceType: ReferenceType; +} + +export interface Alternative { + alt?: string | null | undefined; +} diff --git a/packages/gatsby-mdx-codesandbox/tsconfig.json b/packages/gatsby-mdx-codesandbox/tsconfig.json new file mode 100644 index 00000000..34c569d9 --- /dev/null +++ b/packages/gatsby-mdx-codesandbox/tsconfig.json @@ -0,0 +1,107 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Projects */ + // "incremental": true, /* Enable incremental compilation */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + "jsx": "react" /* Specify what JSX code is generated. */, + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ + // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + + /* Modules */ + "module": "commonjs" /* Specify what module code is generated. */, + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [ + // "./src/@types", + // "./node_modules/@types", + // "../../node_modules/@types" + // ] /* Specify multiple folders that act like `./node_modules/@types`. */, + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "resolveJsonModule": true, /* Enable importing .json files */ + // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ + + /* Emit */ + "declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */, + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + "sourceMap": true /* Create source map files for emitted JavaScript files. */, + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./dist" /* Specify an output folder for all emitted files. */, + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ + // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ + // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + }, + "include": ["src"], + "exclude": ["src/codesandbox-template"] +} diff --git a/packages/react-codesandbox-viewer/.gitignore b/packages/react-codesandbox-viewer/.gitignore new file mode 100644 index 00000000..76add878 --- /dev/null +++ b/packages/react-codesandbox-viewer/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist \ No newline at end of file diff --git a/packages/react-codesandbox-viewer/.storybook/main.js b/packages/react-codesandbox-viewer/.storybook/main.js new file mode 100644 index 00000000..5ea17a0c --- /dev/null +++ b/packages/react-codesandbox-viewer/.storybook/main.js @@ -0,0 +1,5 @@ +module.exports = { + stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], + addons: ['@storybook/addon-links', '@storybook/addon-essentials'], + framework: '@storybook/react', +} diff --git a/packages/react-codesandbox-viewer/.storybook/preview.js b/packages/react-codesandbox-viewer/.storybook/preview.js new file mode 100644 index 00000000..750f637c --- /dev/null +++ b/packages/react-codesandbox-viewer/.storybook/preview.js @@ -0,0 +1,9 @@ +export const parameters = { + actions: { argTypesRegex: '^on[A-Z].*' }, + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/, + }, + }, +} diff --git a/packages/react-codesandbox-viewer/package.json b/packages/react-codesandbox-viewer/package.json new file mode 100644 index 00000000..a5bc93d5 --- /dev/null +++ b/packages/react-codesandbox-viewer/package.json @@ -0,0 +1,52 @@ +{ + "name": "react-codesandbox-viewer", + "version": "0.0.1", + "source": "src/index.ts", + "main": "dist/index.js", + "browserslist": "> 0.5%, last 2 versions, not dead", + "types": "dist/index.d.ts", + "license": "MIT", + "scripts": { + "build": "parcel build", + "watch": "chokidar 'src/*' -c 'yarn build'", + "storybook": "start-storybook -p 6006", + "build-storybook": "build-storybook" + }, + "dependencies": { + "@emotion/css": "^11.7.1", + "@emotion/react": "^11.7.1", + "@emotion/styled": "^11.6.0", + "@fontsource/roboto": "^4.5.1", + "@mui/icons-material": "^5.2.5", + "@mui/material": "^5.2.8", + "@s-libs/micro-dash": "12", + "@swc/helpers": "^0.3.2", + "@types/prettier": "^2.4.3", + "@types/react-tabs": "^2.3.4", + "bootstrap": "5.1.3", + "prettier": "^2.5.1", + "rc-slider": "^9.7.5", + "react-bootstrap": "^2.1.1", + "react-codesandbox-viewer": "*", + "react-cookie": "^4.1.1", + "react-icons": "^4.3.1", + "react-syntax-highlighter": "^15.4.5", + "react-tabs": "^3.2.3", + "remark-codesandbox": "^0.10.0" + }, + "peerDependencies": { + "@types/react": "^17.0", + "react": "^17.0" + }, + "devDependencies": { + "@babel/core": "^7.16.7", + "@storybook/addon-actions": "^6.4.13", + "@storybook/addon-essentials": "^6.4.13", + "@storybook/addon-links": "^6.4.13", + "@storybook/react": "^6.4.13", + "@types/prettier": "^2.4.3", + "babel-loader": "^8.2.3", + "parcel": "^2.2.0", + "typescript": "^4.5.4" + } +} diff --git a/packages/react-codesandbox-viewer/src/App.jsx b/packages/react-codesandbox-viewer/src/App.jsx new file mode 100644 index 00000000..cf7ce942 --- /dev/null +++ b/packages/react-codesandbox-viewer/src/App.jsx @@ -0,0 +1,126 @@ +// FullImperitive.tsx +var __assign = + (this && this.__assign) || + function () { + __assign = + Object.assign || + function (t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i] + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p] + } + return t + } + return __assign.apply(this, arguments) + } +var __rest = + (this && this.__rest) || + function (s, e) { + var t = {} + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p] + if (s != null && typeof Object.getOwnPropertySymbols === 'function') + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]] + } + return t + } +/* + ********* WARNING ******** + * THIS CODE WAS LAUNCHED FROM LOCALHOST. + * LOCAL PACKAGES MAY NOT MATCH THE DEPENDENCIES + * USED IN THIS SANDBOX. + * + * TEST SANDBOX FOR BACKWARD COMPATIBLITY IF DESIRED. + ********* WARNING ******** + */ +import { Engine, FreeCamera, HemisphericLight, MeshBuilder, Scene, Vector3 } from '@babylonjs/core' +import { useEffect, useRef } from 'react' +var SceneComponent = function (props) { + var reactCanvas = useRef(null) + var _props = __assign({ canvasId: 'babylonjs-canvas' }, props) + var canvasId = _props.canvasId, + antialias = _props.antialias, + engineOptions = _props.engineOptions, + adaptToDeviceRatio = _props.adaptToDeviceRatio, + sceneOptions = _props.sceneOptions, + onRender = _props.onRender, + onSceneReady = _props.onSceneReady, + rest = __rest(_props, [ + 'canvasId', + 'antialias', + 'engineOptions', + 'adaptToDeviceRatio', + 'sceneOptions', + 'onRender', + 'onSceneReady', + ]) + useEffect( + function () { + if (!reactCanvas.current) return + var engine = new Engine(reactCanvas.current, antialias, engineOptions, adaptToDeviceRatio) + var scene = new Scene(engine, sceneOptions) + if (scene.isReady()) { + onSceneReady(scene) + } else { + scene.onReadyObservable.addOnce(onSceneReady) + } + engine.runRenderLoop(function () { + onRender(scene) + scene.render() + }) + var resize = function () { + scene.getEngine().resize() + } + if (window) { + window.addEventListener('resize', resize) + } + return function () { + scene.getEngine().dispose() + if (window) { + window.removeEventListener('resize', resize) + } + } + }, + [antialias, engineOptions, adaptToDeviceRatio, sceneOptions, onRender, onSceneReady] + ) + return +} +var box +var onSceneReady = function (scene) { + // This creates and positions a free camera (non-mesh) + var camera = new FreeCamera('camera1', new Vector3(0, 5, -10), scene) + // This targets the camera to scene origin + camera.setTarget(Vector3.Zero()) + var canvas = scene.getEngine().getRenderingCanvas() + // This attaches the camera to the canvas + camera.attachControl(canvas, true) + // This creates a light, aiming 0,1,0 - to the sky (non-mesh) + var light = new HemisphericLight('light', new Vector3(0, 1, 0), scene) + // Default intensity is 1. Let's dim the light a small amount + light.intensity = 0.7 + // Our built-in 'box' shape. + box = MeshBuilder.CreateBox('box', { size: 2 }, scene) + // Move the box upward 1/2 its height + box.position.y = 1 + // Our built-in 'ground' shape. + MeshBuilder.CreateGround('ground', { width: 6, height: 6 }, scene) +} +/** + * Will run on every frame render. We are spinning the box on y-axis. + */ +var onRender = function (scene) { + if (box !== undefined) { + var deltaTimeInMillis = scene.getEngine().getDeltaTime() + var rpm = 10 + box.rotation.y += (rpm / 60) * Math.PI * 2 * (deltaTimeInMillis / 1000) + } +} +var App = function () { + return ( +
+ +
+ ) +} +export default App diff --git a/packages/react-codesandbox-viewer/src/App.tsx b/packages/react-codesandbox-viewer/src/App.tsx new file mode 100644 index 00000000..577beb85 --- /dev/null +++ b/packages/react-codesandbox-viewer/src/App.tsx @@ -0,0 +1,145 @@ +// FullImperitive.tsx + +/* + ********* WARNING ******** + * THIS CODE WAS LAUNCHED FROM LOCALHOST. + * LOCAL PACKAGES MAY NOT MATCH THE DEPENDENCIES + * USED IN THIS SANDBOX. + * + * TEST SANDBOX FOR BACKWARD COMPATIBLITY IF DESIRED. + ********* WARNING ******** + */ + +import { + Engine, + EngineOptions, + FreeCamera, + HemisphericLight, + Mesh, + MeshBuilder, + Scene, + SceneOptions, + Vector3, +} from '@babylonjs/core' +import { FC, useEffect, useRef } from 'react' +import { SetRequired } from 'type-fest' +type OnSceneReadyHandler = (scene: Scene) => void + +type OnRenderHandler = (scene: Scene) => void + +// import SceneComponent from 'babylonjs-hook'; // if you install 'babylonjs-hook' NPM. + +type SceneComponentProps = { + canvasId: string + antialias?: boolean + engineOptions?: EngineOptions + adaptToDeviceRatio?: boolean + sceneOptions?: SceneOptions + onRender: OnRenderHandler + onSceneReady: OnSceneReadyHandler +} + +type SceneComponentPropsIn = SetRequired, 'onRender' | 'onSceneReady'> + +const SceneComponent: FC = (props) => { + const reactCanvas = useRef(null) + const _props: SceneComponentProps = { + canvasId: 'babylonjs-canvas', + ...props, + } + + const { + canvasId, + antialias, + engineOptions, + adaptToDeviceRatio, + sceneOptions, + onRender, + onSceneReady, + ...rest + } = _props + + useEffect(() => { + if (!reactCanvas.current) return + const engine = new Engine(reactCanvas.current, antialias, engineOptions, adaptToDeviceRatio) + const scene = new Scene(engine, sceneOptions) + if (scene.isReady()) { + onSceneReady(scene) + } else { + scene.onReadyObservable.addOnce(onSceneReady) + } + + engine.runRenderLoop(() => { + onRender(scene) + scene.render() + }) + + const resize = () => { + scene.getEngine().resize() + } + + if (window) { + window.addEventListener('resize', resize) + } + + return () => { + scene.getEngine().dispose() + + if (window) { + window.removeEventListener('resize', resize) + } + } + }, [antialias, engineOptions, adaptToDeviceRatio, sceneOptions, onRender, onSceneReady]) + + return +} + +let box: Mesh + +const onSceneReady: OnSceneReadyHandler = (scene) => { + // This creates and positions a free camera (non-mesh) + var camera = new FreeCamera('camera1', new Vector3(0, 5, -10), scene) + + // This targets the camera to scene origin + camera.setTarget(Vector3.Zero()) + + const canvas = scene.getEngine().getRenderingCanvas() + + // This attaches the camera to the canvas + camera.attachControl(canvas, true) + + // This creates a light, aiming 0,1,0 - to the sky (non-mesh) + var light = new HemisphericLight('light', new Vector3(0, 1, 0), scene) + + // Default intensity is 1. Let's dim the light a small amount + light.intensity = 0.7 + + // Our built-in 'box' shape. + box = MeshBuilder.CreateBox('box', { size: 2 }, scene) + + // Move the box upward 1/2 its height + box.position.y = 1 + + // Our built-in 'ground' shape. + MeshBuilder.CreateGround('ground', { width: 6, height: 6 }, scene) +} + +/** + * Will run on every frame render. We are spinning the box on y-axis. + */ +const onRender: OnRenderHandler = (scene) => { + if (box !== undefined) { + var deltaTimeInMillis = scene.getEngine().getDeltaTime() + + const rpm = 10 + box.rotation.y += (rpm / 60) * Math.PI * 2 * (deltaTimeInMillis / 1000) + } +} + +const App: FC = () => ( +
+ +
+) + +export default App diff --git a/packages/react-codesandbox-viewer/src/Demo.stories.tsx b/packages/react-codesandbox-viewer/src/Demo.stories.tsx new file mode 100644 index 00000000..031342f9 --- /dev/null +++ b/packages/react-codesandbox-viewer/src/Demo.stories.tsx @@ -0,0 +1,76 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react' +import React from 'react' +import App from './App' +import { Demo } from './Demo' + +// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export +export default { + title: 'Demo', + component: Demo, + // More on argTypes: https://storybook.js.org/docs/react/api/argtypes + argTypes: { + backgroundColor: { control: 'color' }, + }, +} as ComponentMeta + +// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args +const Template: ComponentStory = (args) => + +export const Primary = Template.bind({}) + +// More on args: https://storybook.js.org/docs/react/writing-stories/args +Primary.args = { + prefix: `g${+new Date()}`, + isDevelopmentMode: true, + container: App, + typescript: `/** + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + + import React, { FC } from 'react' + + const App: FC = () =>
'hello world'
+ + export default App + + `, +} diff --git a/packages/react-codesandbox-viewer/src/Demo.tsx b/packages/react-codesandbox-viewer/src/Demo.tsx new file mode 100644 index 00000000..dde6c4d4 --- /dev/null +++ b/packages/react-codesandbox-viewer/src/Demo.tsx @@ -0,0 +1,209 @@ +import { css } from '@emotion/css' +import '@fontsource/roboto/300.css' +import '@fontsource/roboto/400.css' +import '@fontsource/roboto/500.css' +import '@fontsource/roboto/700.css' +import 'bootstrap/dist/css/bootstrap.min.css' +import { Options } from 'prettier' +import typescript from 'prettier/parser-typescript' +import prettier from 'prettier/standalone' +import Slider from 'rc-slider' +import 'rc-slider/assets/index.css' +import React, { ComponentType, FC, useMemo, useState } from 'react' +import Button from 'react-bootstrap/Button' +import ButtonGroup from 'react-bootstrap/ButtonGroup' +import Modal from 'react-bootstrap/Modal' +import { FaCog } from 'react-icons/fa' +import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter' +import { dark } from 'react-syntax-highlighter/dist/esm/styles/prism' +import { Tab, TabList, TabPanel, Tabs } from 'react-tabs' +import 'react-tabs/style/react-tabs.css' +import { createCookieHooker } from './cookieHook' + +const plugins = [typescript] + +const PRETTIER_OPTS: Options = { + parser: 'typescript', + plugins, + singleQuote: true, + semi: false, + printWidth: 100, + jsxBracketSameLine: false, + tabWidth: 2, + trailingComma: 'es5', +} + +const useRememberFontSize = createCookieHooker('fontsize') +const useRememberTabIdx = createCookieHooker('tabidx') +const useRememberLanguage = createCookieHooker<'ts' | 'js'>('language') +const useRememberWrapWidth = createCookieHooker('wrapwidth') + +export type DemoProps = { + isDevelopmentMode: boolean + container: ComponentType + typescript: string + javascript: string + codesandboxUrl: string + prefix: string +} + +export const Demo: FC> = (props) => { + const _props: DemoProps = { + container: () =>
Render me
, + javascript: `import React from 'react' + + const App = () =>
'hello world'
+ + export default App + `, + typescript: `import React, { FC } from 'react' + + const App: FC = () =>
'hello world'
+ + export default App + `, + codesandboxUrl: 'https://codesandbox.io', + isDevelopmentMode: false, + prefix: '', + ...props, + } + const { container, typescript, javascript, codesandboxUrl, isDevelopmentMode, prefix } = _props + + const [language, setLanguage] = useRememberLanguage('ts') + const [tabIdx, setTabIdx] = useRememberTabIdx(0, prefix) + const [fontSize, setFontSize] = useRememberFontSize(10) + const [printWidth, setPrintWidth] = useRememberWrapWidth(80) + const [showSettings, setShowSettings] = useState(false) + + const source = useMemo(() => { + return prettier.format(language === 'ts' ? typescript : javascript, { + ...PRETTIER_OPTS, + printWidth, + }) + }, [language, printWidth]) + + return ( +
+ {isDevelopmentMode && ( +
+ Development mode detected. Running local code against local packages. +
+ )} + + setTabIdx(idx)}> + + Demo + Code +
+ + + + +
+ + +
+ + {React.createElement(container)} + + + {source} + + +
+ setShowSettings(false)}> + + Editor Settings + + +
+ Font Size + setFontSize(v as number)} + /> +
+
+ Wrap Width + setPrintWidth(v as number)} + /> +
+
+
+
+ ) +} diff --git a/packages/react-codesandbox-viewer/src/cookieHook.ts b/packages/react-codesandbox-viewer/src/cookieHook.ts new file mode 100644 index 00000000..ed126b7b --- /dev/null +++ b/packages/react-codesandbox-viewer/src/cookieHook.ts @@ -0,0 +1,38 @@ +import { useCookies } from 'react-cookie' + +export const useRememberCookieState = ( + defaultValue: TValue, + key = '' +): [value: TValue, setValue: (value: TValue) => void] => { + const [cookies, setCookies] = useCookies() + + const _set = (value: TValue) => { + const save = { _v: value } + // console.log(key, 'setting', save) + setCookies(key, save) + } + + const _v = (() => { + const _v = cookies[key] + // console.log(key, 'get', 'existing', { _v }) + if (typeof _v === 'undefined') { + // console.log(key, 'get', 'default', defaultValue) + return defaultValue + } + return _v._v + })() + + return [_v, _set] +} +type CookieState = ( + defaultValue: TValue, + guid?: string +) => [TValue, (value: TValue) => void] +export const createCookieHooker = (name: string) => { + const useFunc: CookieState = (defaultValue, guid = '') => { + const [value, set] = useRememberCookieState(defaultValue, `${guid}_${name}`) + + return [value, set] + } + return useFunc +} diff --git a/packages/react-codesandbox-viewer/src/index.ts b/packages/react-codesandbox-viewer/src/index.ts new file mode 100644 index 00000000..46ea0af4 --- /dev/null +++ b/packages/react-codesandbox-viewer/src/index.ts @@ -0,0 +1 @@ +export * from './Demo' diff --git a/packages/react-codesandbox-viewer/tsconfig.json b/packages/react-codesandbox-viewer/tsconfig.json new file mode 100644 index 00000000..879726d1 --- /dev/null +++ b/packages/react-codesandbox-viewer/tsconfig.json @@ -0,0 +1,107 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Projects */ + // "incremental": true, /* Enable incremental compilation */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + "jsx": "react" /* Specify what JSX code is generated. */, + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ + // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + + /* Modules */ + "module": "commonjs" /* Specify what module code is generated. */, + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + "typeRoots": [ + "./src/@types", + "./node_modules/@types", + "../../node_modules/@types" + ] /* Specify multiple folders that act like `./node_modules/@types`. */, + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "resolveJsonModule": true, /* Enable importing .json files */ + // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ + + /* Emit */ + "declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */, + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + "sourceMap": true /* Create source map files for emitted JavaScript files. */, + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./dist" /* Specify an output folder for all emitted files. */, + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ + // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ + // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + }, + "include": ["src"], + "exclude": ["src/plugin/codesandbox-template"] +} diff --git a/packages/static/.eslintrc.json b/packages/static/.eslintrc.json index 074b9f85..60e17be5 100755 --- a/packages/static/.eslintrc.json +++ b/packages/static/.eslintrc.json @@ -1,11 +1,5 @@ { - "extends": [ - "eslint:recommended", - "plugin:import/errors", - "plugin:react/recommended", - "plugin:jsx-a11y/recommended", - "prettier" - ], + "extends": ["react-app", "prettier"], "plugins": ["react", "import", "jsx-a11y"], "settings": { "react": { @@ -23,19 +17,9 @@ "react/prop-types": 0, "react/react-in-jsx-scope": "off", "lines-between-class-members": ["error", "always"], - "padding-line-between-statements": [ - "error", - { "blankLine": "always", "prev": ["const", "let", "var"], "next": "*" }, - { - "blankLine": "always", - "prev": ["const", "let", "var"], - "next": ["const", "let", "var"] - }, - { "blankLine": "always", "prev": "directive", "next": "*" }, - { "blankLine": "any", "prev": "directive", "next": "directive" } - ] + "padding-line-between-statements": 0 }, - "parser": "babel-eslint", + "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": 10, "sourceType": "module", @@ -49,6 +33,7 @@ "node": true }, "globals": { - "graphql": false + "graphql": false, + "JSX": true } } diff --git a/packages/static/.prettierignore b/packages/static/.prettierignore index 16d3c4db..4849e0ab 100644 --- a/packages/static/.prettierignore +++ b/packages/static/.prettierignore @@ -1 +1,2 @@ .cache +public diff --git a/packages/static/.prettierrc b/packages/static/.prettierrc index 48bb2e78..a2a24e02 100644 --- a/packages/static/.prettierrc +++ b/packages/static/.prettierrc @@ -1,6 +1,5 @@ { "printWidth": 100, - "jsxBracketSameLine": false, "singleQuote": true, "tabWidth": 2, "trailingComma": "es5", diff --git a/packages/static/content/3-hello-react-babylonjs/1-react-boiler-plate/HelloReact.tsx b/packages/static/content/3-hello-react-babylonjs/1-react-boiler-plate/HelloReact.tsx new file mode 100644 index 00000000..0a2cc268 --- /dev/null +++ b/packages/static/content/3-hello-react-babylonjs/1-react-boiler-plate/HelloReact.tsx @@ -0,0 +1,5 @@ +import { FC } from 'react' + +const App: FC = () =>
Hello, React!
+ +export default App diff --git a/packages/static/content/3-hello-react-babylonjs/1-react-boiler-plate.mdx b/packages/static/content/3-hello-react-babylonjs/1-react-boiler-plate/index.mdx similarity index 65% rename from packages/static/content/3-hello-react-babylonjs/1-react-boiler-plate.mdx rename to packages/static/content/3-hello-react-babylonjs/1-react-boiler-plate/index.mdx index afd5cb72..9deb4377 100644 --- a/packages/static/content/3-hello-react-babylonjs/1-react-boiler-plate.mdx +++ b/packages/static/content/3-hello-react-babylonjs/1-react-boiler-plate/index.mdx @@ -18,12 +18,4 @@ yarn create react-app my-app Once you have a project, you'll find a setup that looks a little like this: -```tsx codesandbox=rbjs?entry=./src/App.tsx -import { FC } from 'react' - -const App: FC = () => ( -
Hello, React!
-) - -export default App -``` +[demo:HelloReact.tsx] diff --git a/packages/static/content/3-hello-react-babylonjs/2-react-with-imperitive-babylonjs.mdx b/packages/static/content/3-hello-react-babylonjs/2-react-with-imperitive-babylonjs/FullImperitive.tsx similarity index 51% rename from packages/static/content/3-hello-react-babylonjs/2-react-with-imperitive-babylonjs.mdx rename to packages/static/content/3-hello-react-babylonjs/2-react-with-imperitive-babylonjs/FullImperitive.tsx index f3b21649..a71e2820 100644 --- a/packages/static/content/3-hello-react-babylonjs/2-react-with-imperitive-babylonjs.mdx +++ b/packages/static/content/3-hello-react-babylonjs/2-react-with-imperitive-babylonjs/FullImperitive.tsx @@ -1,17 +1,3 @@ ---- -title: 'Plain Old React + Babylon.js' -slug: 'react-with-imperitive-babylonjs' ---- - -Once you have a React project set up, you can program Babylon.js imperitively -just like they tell you in the -[official Babylon.js + React guide](https://doc.babylonjs.com/extensions/Babylon.js+ExternalLibraries/BabylonJS_and_ReactJS). - -Wow, it takes **almost 150 lines of code** to make a box show up on a screen! -But do not be scared. We are showing you how much coding it actually takes so -you'll fully appreciate the next section. - -```tsx codesandbox=rbjs?entry=./src/App.tsx import { Engine, EngineOptions, @@ -41,10 +27,7 @@ type SceneComponentProps = { onSceneReady: OnSceneReadyHandler } -type SceneComponentPropsIn = SetRequired< - Partial, - 'onRender' | 'onSceneReady' -> +type SceneComponentPropsIn = SetRequired, 'onRender' | 'onSceneReady'> const SceneComponent: FC = (props) => { const reactCanvas = useRef(null) @@ -66,12 +49,7 @@ const SceneComponent: FC = (props) => { useEffect(() => { if (!reactCanvas.current) return - const engine = new Engine( - reactCanvas.current, - antialias, - engineOptions, - adaptToDeviceRatio - ) + const engine = new Engine(reactCanvas.current, antialias, engineOptions, adaptToDeviceRatio) const scene = new Scene(engine, sceneOptions) if (scene.isReady()) { onSceneReady(scene) @@ -99,14 +77,7 @@ const SceneComponent: FC = (props) => { window.removeEventListener('resize', resize) } } - }, [ - antialias, - engineOptions, - adaptToDeviceRatio, - sceneOptions, - onRender, - onSceneReady, - ]) + }, [antialias, engineOptions, adaptToDeviceRatio, sceneOptions, onRender, onSceneReady]) return } @@ -160,73 +131,3 @@ const App: FC = () => ( ) export default App -``` - -Now to be completely fair, Babylon.js has created a helpful -[babylonjs-hook](https://www.npmjs.com/package/babylonjs-hook) package which -replaces `SceneComponent`. If you use this, you can get down to about **60 lines -of code**. But next, I'll show you how to do it in **under 30**. - -```tsx codesandbox=rbjs?entry=./src/App.tsx -import { - FreeCamera, - HemisphericLight, - Mesh, - MeshBuilder, - Scene, - Vector3, -} from '@babylonjs/core' -import SceneComponent from 'babylonjs-hook' - -type OnSceneReadyHandler = (scene: Scene) => void - -type OnRenderHandler = (scene: Scene) => void - -let box: Mesh - -const onSceneReady: OnSceneReadyHandler = (scene) => { - // This creates and positions a free camera (non-mesh) - var camera = new FreeCamera('camera1', new Vector3(0, 5, -10), scene) - - // This targets the camera to scene origin - camera.setTarget(Vector3.Zero()) - - const canvas = scene.getEngine().getRenderingCanvas() - - // This attaches the camera to the canvas - camera.attachControl(canvas, true) - - // This creates a light, aiming 0,1,0 - to the sky (non-mesh) - var light = new HemisphericLight('light', new Vector3(0, 1, 0), scene) - - // Default intensity is 1. Let's dim the light a small amount - light.intensity = 0.7 - - // Our built-in 'box' shape. - box = MeshBuilder.CreateBox('box', { size: 2 }, scene) - - // Move the box upward 1/2 its height - box.position.y = 1 - - // Our built-in 'ground' shape. - MeshBuilder.CreateGround('ground', { width: 6, height: 6 }, scene) -} - -/** - * Will run on every frame render. We are spinning the box on y-axis. - */ -const onRender: OnRenderHandler = (scene) => { - if (box !== undefined) { - var deltaTimeInMillis = scene.getEngine().getDeltaTime() - - const rpm = 10 - box.rotation.y += (rpm / 60) * Math.PI * 2 * (deltaTimeInMillis / 1000) - } -} - -export default () => ( -
- -
-) -``` diff --git a/packages/static/content/3-hello-react-babylonjs/2-react-with-imperitive-babylonjs/WithHooks.tsx b/packages/static/content/3-hello-react-babylonjs/2-react-with-imperitive-babylonjs/WithHooks.tsx new file mode 100644 index 00000000..8d72fb6c --- /dev/null +++ b/packages/static/content/3-hello-react-babylonjs/2-react-with-imperitive-babylonjs/WithHooks.tsx @@ -0,0 +1,57 @@ +import { FreeCamera, HemisphericLight, Mesh, MeshBuilder, Scene, Vector3 } from '@babylonjs/core' +import SceneComponent from 'babylonjs-hook' +import { FC } from 'react' + +type OnSceneReadyHandler = (scene: Scene) => void + +type OnRenderHandler = (scene: Scene) => void + +let box: Mesh + +const onSceneReady: OnSceneReadyHandler = (scene) => { + // This creates and positions a free camera (non-mesh) + var camera = new FreeCamera('camera1', new Vector3(0, 5, -10), scene) + + // This targets the camera to scene origin + camera.setTarget(Vector3.Zero()) + + const canvas = scene.getEngine().getRenderingCanvas() + + // This attaches the camera to the canvas + camera.attachControl(canvas, true) + + // This creates a light, aiming 0,1,0 - to the sky (non-mesh) + var light = new HemisphericLight('light', new Vector3(0, 1, 0), scene) + + // Default intensity is 1. Let's dim the light a small amount + light.intensity = 0.7 + + // Our built-in 'box' shape. + box = MeshBuilder.CreateBox('box', { size: 2 }, scene) + + // Move the box upward 1/2 its height + box.position.y = 1 + + // Our built-in 'ground' shape. + MeshBuilder.CreateGround('ground', { width: 6, height: 6 }, scene) +} + +/** + * Will run on every frame render. We are spinning the box on y-axis. + */ +const onRender: OnRenderHandler = (scene) => { + if (box !== undefined) { + var deltaTimeInMillis = scene.getEngine().getDeltaTime() + + const rpm = 10 + box.rotation.y += (rpm / 60) * Math.PI * 2 * (deltaTimeInMillis / 1000) + } +} + +const App: FC = () => ( +
+ +
+) + +export default App diff --git a/packages/static/content/3-hello-react-babylonjs/2-react-with-imperitive-babylonjs/index.mdx b/packages/static/content/3-hello-react-babylonjs/2-react-with-imperitive-babylonjs/index.mdx new file mode 100644 index 00000000..e4678986 --- /dev/null +++ b/packages/static/content/3-hello-react-babylonjs/2-react-with-imperitive-babylonjs/index.mdx @@ -0,0 +1,40 @@ +--- +title: 'Plain Old React + Babylon.js' +slug: 'react-with-imperitive-babylonjs' +--- + +Once you have a React project set up, you can program Babylon.js imperitively +just like they tell you in the +[official Babylon.js + React guide](https://doc.babylonjs.com/extensions/Babylon.js+ExternalLibraries/BabylonJS_and_ReactJS). + +[demo:FullImperitive.tsx] + +The demo above is produced using imperitive Typescript. Wow, it takes **almost +150 lines of code** to make a box show up on a screen! But do not be scared. We +are showing you how much work it actually takes so you'll fully appreciate the +power of `react-babylonjs`. + +As you review the code, notice everything happens in sequence and you are +responsible for re-running affected code when you change the input values. + +In a [reactive programming](https://en.wikipedia.org/wiki/Reactive_programming), +a change in the input values naturally cascades to affected code. There are many +benefits to a reactive programming style that we won't cover here. But speed, +efficiency, and ability to reason through complex state changes are among the +many benefits. + +Mixing imperitive programming with React is generally an antipattern because it +reduces the benefits of reactive programming. + +Therefore, this code is the least desirable way to use Babylon.js in React. + +Now to be completely fair, Babylon.js has created a helpful +[babylonjs-hook](https://www.npmjs.com/package/babylonjs-hook) package which +replaces `SceneComponent`. If you use this, you can get down to about **60 lines +of code**. But it's still imperitive programming, not declarative or reactive +programming. + +After this, I'll show you how to do the same thing in **under 50 lines of code +using real declarative programming**. + +[demo:WithHooks.tsx] diff --git a/packages/static/content/3-hello-react-babylonjs/3-react-with-declarative-babylonjs.mdx b/packages/static/content/3-hello-react-babylonjs/3-react-with-declarative-babylonjs.mdx deleted file mode 100644 index a0ccf54c..00000000 --- a/packages/static/content/3-hello-react-babylonjs/3-react-with-declarative-babylonjs.mdx +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: 'Under 50 Lines of Code: react-babylonjs' -slug: 'react-with-declarative-babylonjs' ---- - -In previous sections, we saw how to: - -- Create a boilerplate React app -- Instantiate a Babylon.js scene imperitively -- Shoehorn the above into React in about 150 lines of code, still not "reactive" - or declarative -- Reduce 150 lines of code to 60 by moving some of it into a 3rd party package, - but still not reactive or declarative - -But now, we'll see how to do the exact same thing in **just under 50 lines of -code using a true reactive/declarative approach**. - -We also learn how to make custom Babylon React components, and how to use some -helpful hooks like `useScene`, `useBeforeRender`. - -```tsx codesandbox=rbjs?entry=./src/App.tsx -import { Vector3 } from '@babylonjs/core' -import { FC, useRef } from 'react' -import { Engine, Scene, useBeforeRender, useScene } from 'react-babylonjs' - -const RPM = 5 - -const MovingBox: FC = (props) => { - // access Babylon Scene - const scene = useScene() - // access refs to Babylon objects in scene like DOM nodes - const boxRef = useRef(null) - - useBeforeRender(() => { - if (!boxRef.current?.rotation) return - if (!scene) return - const deltaTimeInMillis = scene.getEngine().getDeltaTime() - boxRef.current.rotation.y += - (RPM / 60) * Math.PI * 2 * (deltaTimeInMillis / 1000) - }) - - return ( - - ) -} - -const App: FC = () => ( -
- - - - - - - - -
-) - -export default App -``` diff --git a/packages/static/content/3-hello-react-babylonjs/3-react-with-declarative-babylonjs/BasicScene.tsx b/packages/static/content/3-hello-react-babylonjs/3-react-with-declarative-babylonjs/BasicScene.tsx new file mode 100644 index 00000000..20f37d75 --- /dev/null +++ b/packages/static/content/3-hello-react-babylonjs/3-react-with-declarative-babylonjs/BasicScene.tsx @@ -0,0 +1,19 @@ +import { Vector3 } from '@babylonjs/core' +import { FC } from 'react' +import { Engine, Scene } from 'react-babylonjs' + +const v3 = (x = 0, y = 0, z = 0) => new Vector3(x, y, z) + +const App: FC = () => ( +
+ + + + + + + +
+) + +export default App diff --git a/packages/static/content/3-hello-react-babylonjs/3-react-with-declarative-babylonjs/Declarative.tsx b/packages/static/content/3-hello-react-babylonjs/3-react-with-declarative-babylonjs/Declarative.tsx new file mode 100644 index 00000000..14906dba --- /dev/null +++ b/packages/static/content/3-hello-react-babylonjs/3-react-with-declarative-babylonjs/Declarative.tsx @@ -0,0 +1,36 @@ +import { Vector3 } from '@babylonjs/core' +import { FC, useRef } from 'react' +import { Engine, Scene, useBeforeRender, useScene } from 'react-babylonjs' + +const RPM = 5 + +const MovingBox: FC = () => { + // access Babylon Scene + const scene = useScene() + // access refs to Babylon objects in scene like DOM nodes + const boxRef = useRef(null) + + useBeforeRender(() => { + if (!boxRef.current?.rotation) return + if (!scene) return + const deltaTimeInMillis = scene.getEngine().getDeltaTime() + boxRef.current.rotation.y += (RPM / 60) * Math.PI * 2 * (deltaTimeInMillis / 1000) + }) + + return +} + +const App: FC = () => ( +
+ + + + + + + + +
+) + +export default App diff --git a/packages/static/content/3-hello-react-babylonjs/3-react-with-declarative-babylonjs/index.mdx b/packages/static/content/3-hello-react-babylonjs/3-react-with-declarative-babylonjs/index.mdx new file mode 100644 index 00000000..c90aab3b --- /dev/null +++ b/packages/static/content/3-hello-react-babylonjs/3-react-with-declarative-babylonjs/index.mdx @@ -0,0 +1,99 @@ +--- +title: 'Under 50 Lines of Code: react-babylonjs' +slug: 'react-with-declarative-babylonjs' +--- + +In previous sections, we saw how to: + +- Create a boilerplate React app +- Instantiate a Babylon.js scene imperitively +- Shoehorn the above into React in about 150 lines of code, still not "reactive" + or declarative +- Reduce 150 lines of code to 60 by moving some of it into a 3rd party package, + but still not reactive or declarative + +But now, we'll see how to do the exact same thing in **just under 50 lines of +code using a true reactive/declarative approach**. + +We also learn how to make custom Babylon React components, and how to use some +helpful hooks like `useScene`, `useBeforeRender`. + +First, let's take a look at what a basic React structure looks like: + +```tsx +import { Engine, Scene } from 'react-babylonjs' + +const BasicScene: FC = ({ children }) => ( + + {children} + +) +``` + +The above code introduces the `Engine` and `Scene` tags of `react-bablylonjs`. +These perform boilerplate initialization. Everything you might like to add to a +scene will go inside the `Scene` tag. + +Next, we are going to define a camera, some light, and a ground surface. At this +point, it's important to understand a Typescript concept known as +[intrinsic JSX](https://www.typescriptlang.org/docs/handbook/jsx.html#intrinsic-elements). +Where we had to explicitly import `Egnine` and `Scene`, there are many tags +related to Babylon.js that are already known to React. We will use `freeCamera`, +`hemisphericLight`, and `ground`. + +First, let's make a little helper function. Babylon.js defines a `Vector3` class +which is used very frequently. We'll make a helper for it. When you see `v3` +anywhere, it's coming from this: + +```tsx +import { Vector3 } from '@babylonjs/core' + +const v3 = (x = 0, y = 0, z = 0) => new Vector3(x, y, z) +``` + +Now with that in place, here's how we can add a camera, light, and ground to our +scene. + +```tsx + + + + + +``` + +Here's the final result of that basic scene: + +[demo:BasicScene.tsx] + +Now that we have a basic scene in place, let's make that spinning box like we +did before, but this time, do it React style. + +```tsx + +``` + +```tsx +const RPM = 5 + +const MovingBox: FC = () => { + // access Babylon Scene + const scene = useScene() + // access refs to Babylon objects in scene like DOM nodes + const boxRef = useRef(null) + + useBeforeRender(() => { + if (!boxRef.current?.rotation) return + if (!scene) return + const deltaTimeInMillis = scene.getEngine().getDeltaTime() + boxRef.current.rotation.y += + (RPM / 60) * Math.PI * 2 * (deltaTimeInMillis / 1000) + }) + + return ( + + ) +} +``` + +[demo:Declarative.tsx] diff --git a/packages/static/content/3-hello-react-babylonjs/4-adding-animation-and-color.mdx b/packages/static/content/3-hello-react-babylonjs/4-adding-animation-and-color/Colorful.tsx similarity index 55% rename from packages/static/content/3-hello-react-babylonjs/4-adding-animation-and-color.mdx rename to packages/static/content/3-hello-react-babylonjs/4-adding-animation-and-color/Colorful.tsx index d0b85d38..9f41cc96 100644 --- a/packages/static/content/3-hello-react-babylonjs/4-adding-animation-and-color.mdx +++ b/packages/static/content/3-hello-react-babylonjs/4-adding-animation-and-color/Colorful.tsx @@ -1,11 +1,3 @@ ---- -title: 'Adding More Animation and Color' -slug: 'react-babylonjs-with-animation' ---- - -Let's take a look at how to spice up this 3D scene a bit. - -```tsx codesandbox=rbjs?entry=./src/App.tsx import { Color3, Vector3 } from '@babylonjs/core' import { FC, useRef } from 'react' import { Engine, Scene, useBeforeRender, useScene } from 'react-babylonjs' @@ -34,11 +26,7 @@ const MovingBox: FC = (props) => { return ( - + ) } @@ -47,30 +35,13 @@ const App: FC = () => (
- - - - + + + +
) export default App -``` diff --git a/packages/static/content/3-hello-react-babylonjs/4-adding-animation-and-color/index.mdx b/packages/static/content/3-hello-react-babylonjs/4-adding-animation-and-color/index.mdx new file mode 100644 index 00000000..cdd65e17 --- /dev/null +++ b/packages/static/content/3-hello-react-babylonjs/4-adding-animation-and-color/index.mdx @@ -0,0 +1,8 @@ +--- +title: 'Adding More Animation and Color' +slug: 'react-babylonjs-with-animation' +--- + +Let's take a look at how to spice up this 3D scene a bit. + +[demo:Colorful.tsx] diff --git a/packages/static/gatsby-config.js b/packages/static/gatsby-config.js index 18c351a2..15ac80cc 100755 --- a/packages/static/gatsby-config.js +++ b/packages/static/gatsby-config.js @@ -36,16 +36,8 @@ const plugins = [ resolve: 'gatsby-remark-copy-linked-files', }, { - resolve: 'remark-codesandbox/gatsby', - options: { - mode: 'iframe', - customTemplates: { - rbjs: { - extends: 'file:./codesandbox-template', - entry: './src/App.tsx', - }, - }, - }, + resolve: 'gatsby-mdx-codesandbox', + options: {}, }, ], extensions: ['.mdx', '.md'], diff --git a/packages/static/package.json b/packages/static/package.json index 822c46c1..bb53209a 100755 --- a/packages/static/package.json +++ b/packages/static/package.json @@ -1,5 +1,5 @@ { - "name": "react-babylonjs-docs", + "name": "@react-babylonjs/docs", "private": true, "description": "react-babylonjs Documentation", "version": "0.0.1", @@ -22,6 +22,7 @@ "emotion-server": "^11.0.0", "gatsby": "^4.0.0", "gatsby-link": "^4.0.0", + "gatsby-mdx-codesandbox": "*", "gatsby-plugin-algolia": "^0.19.0", "gatsby-plugin-emotion": "^7.0.0", "gatsby-plugin-gtag": "^1.0.13", @@ -52,7 +53,8 @@ "react-instantsearch-dom": "^6.11.0", "react-live": "^2.2.3", "react-loadable": "^5.5.0", - "styled-components": "^5.3.0" + "styled-components": "^5.3.0", + "type-fest": "^2.9.0" }, "license": "MIT", "scripts": { @@ -82,6 +84,6 @@ "prettier": "^2.5.1", "prettier-plugin-organize-imports": "^2.3.4", "prism-react-renderer": "^1.2.0", - "remark-codesandbox": "^0.10.0" + "typescript": "^4.5.4" } } diff --git a/packages/static/src/components/index.js b/packages/static/src/components/index.js index 216a425a..a6122a09 100644 --- a/packages/static/src/components/index.js +++ b/packages/static/src/components/index.js @@ -1,6 +1,8 @@ +// organize-imports-ignore export * from './theme' // eslint-disable-line -export { mdxComponents, ThemeProvider, Layout, Link } import Layout from './layout' import Link from './link' import mdxComponents from './mdxComponents' import ThemeProvider from './theme/themeProvider' + +export { mdxComponents, ThemeProvider, Layout, Link } diff --git a/packages/static/src/components/mdxComponents/ReactDemo.js b/packages/static/src/components/mdxComponents/ReactDemo.js deleted file mode 100644 index fe9b473b..00000000 --- a/packages/static/src/components/mdxComponents/ReactDemo.js +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react' - -const ReactDemo = (props) => { - const { children } = props - - return ( -
- {children} -
- ) -} - -export default ReactDemo diff --git a/packages/static/src/components/mdxComponents/Sandbox.js b/packages/static/src/components/mdxComponents/Sandbox.js deleted file mode 100644 index 34b8210a..00000000 --- a/packages/static/src/components/mdxComponents/Sandbox.js +++ /dev/null @@ -1,23 +0,0 @@ -import React from 'react' - -const Sandbox = (props) => { - const { name } = props - - return ( - - ) -} - -export default Sandbox diff --git a/packages/static/src/components/mdxComponents/Sandbox.tsx b/packages/static/src/components/mdxComponents/Sandbox.tsx new file mode 100644 index 00000000..ee8ca072 --- /dev/null +++ b/packages/static/src/components/mdxComponents/Sandbox.tsx @@ -0,0 +1,25 @@ +import { FC } from 'react' + +const Sandbox: FC<{ name: string }> = (props) => { + return
{JSON.stringify(props, null, 2)}
+ + // const { name } = props + + // return ( + // + // ) +} + +export default Sandbox diff --git a/packages/static/src/components/mdxComponents/index.js b/packages/static/src/components/mdxComponents/index.js index 330e53fb..8abf1c73 100644 --- a/packages/static/src/components/mdxComponents/index.js +++ b/packages/static/src/components/mdxComponents/index.js @@ -2,7 +2,6 @@ import styled from '@emotion/styled' import * as React from 'react' import AnchorTag from './anchor' import CodeBlock from './codeBlock' -import ReactDemo from './ReactDemo' import Sandbox from './Sandbox' import Stats from './Stats' @@ -79,7 +78,6 @@ export default { code: CodeBlock, a: AnchorTag, Sandbox, - ReactDemo, Stats, // TODO add `img` // TODO add `blockquote` diff --git a/packages/static/src/components/sidebar/index.js b/packages/static/src/components/sidebar/index.js index cc7a57a3..a479c7e3 100644 --- a/packages/static/src/components/sidebar/index.js +++ b/packages/static/src/components/sidebar/index.js @@ -107,6 +107,7 @@ const SidebarLayout = ({ location }) => ( } `} render={({ allMdx }) => { + console.log({ allMdx }) return ( {config.sidebar.title ? ( diff --git a/packages/static/tsconfig.json b/packages/static/tsconfig.json new file mode 100644 index 00000000..2f7aa534 --- /dev/null +++ b/packages/static/tsconfig.json @@ -0,0 +1,100 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Projects */ + // "incremental": true, /* Enable incremental compilation */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es5" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + "jsx": "preserve" /* Specify what JSX code is generated. */, + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ + // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + + /* Modules */ + "module": "commonjs" /* Specify what module code is generated. */, + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "resolveJsonModule": true, /* Enable importing .json files */ + // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ + // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ + // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/packages/storybook-static/.gitignore b/packages/storybook-static/.gitignore new file mode 100644 index 00000000..82d94d38 --- /dev/null +++ b/packages/storybook-static/.gitignore @@ -0,0 +1,3 @@ +node_modules +storybook-static +yarn.lock \ No newline at end of file diff --git a/packages/storybook-static/.storybook/main.js b/packages/storybook-static/.storybook/main.js new file mode 100644 index 00000000..4f1e33d1 --- /dev/null +++ b/packages/storybook-static/.storybook/main.js @@ -0,0 +1,24 @@ +const path = require('path'); + +module.exports = { + "stories": [ + "../stories/**/*.stories.mdx", + "../stories/**/*.stories.@(js|jsx|ts|tsx)" + ], + addons: [ + //'@storybook/addon-actions/register', + //'@storybook/addon-links', + '@storybook/addon-storysource' + // '@storybook/addon-notes/register', + ], + webpackFinal: async (config, { configType }) => { + // config.module.rules.push({ + // test: /\.stories\.jsx?$/, + // loaders: [require.resolve('@storybook/source-loader')], + // enforce: 'pre', + // }); + // console.log(`added source loader to '${configType}' webpack config`); + // Return the altered config + return config; + }, +}; diff --git a/packages/storybook-static/.storybook/manager-head.html b/packages/storybook-static/.storybook/manager-head.html new file mode 100644 index 00000000..29b03efa --- /dev/null +++ b/packages/storybook-static/.storybook/manager-head.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/storybook-static/.storybook/manager.js b/packages/storybook-static/.storybook/manager.js new file mode 100644 index 00000000..dcc94918 --- /dev/null +++ b/packages/storybook-static/.storybook/manager.js @@ -0,0 +1,25 @@ +import { addons } from '@storybook/addons'; +import { themes } from '@storybook/theming'; + +addons.setConfig({ + isFullscreen: false, + showNav: true, + showPanel: true, + panelPosition: 'right', + enableShortcuts: true, + isToolshown: true, + theme: themes.dark, + selectedPanel: 'story', + initialActive: 'sidebar', + sidebar: { + showRoots: false, + collapsedRoots: ['other'], + }, + toolbar: { + title: { hidden: false, }, + zoom: { hidden: false, }, + eject: { hidden: false, }, + copy: { hidden: false, }, + fullscreen: { hidden: false, }, + }, +}); \ No newline at end of file diff --git a/packages/storybook-static/.storybook/preview-head.html b/packages/storybook-static/.storybook/preview-head.html new file mode 100644 index 00000000..e7f048fd --- /dev/null +++ b/packages/storybook-static/.storybook/preview-head.html @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/packages/storybook-static/.storybook/preview.js b/packages/storybook-static/.storybook/preview.js new file mode 100644 index 00000000..21377b6c --- /dev/null +++ b/packages/storybook-static/.storybook/preview.js @@ -0,0 +1,14 @@ +export const parameters = { + actions: { argTypesRegex: "^on[A-Z].*" }, + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/, + }, + }, + options: { + storySort: (a, b) => { + return a[1].kind === b[1].kind ? 0 : a[1].id.localeCompare(b[1].id, { numeric: true }); + } + }, +}; \ No newline at end of file diff --git a/packages/storybook-static/package.json b/packages/storybook-static/package.json new file mode 100644 index 00000000..8777d1ee --- /dev/null +++ b/packages/storybook-static/package.json @@ -0,0 +1,40 @@ +{ + "name": "react-babylonjs-storybook-static", + "private": "true", + "version": "0.0.1", + "description": "stories for react-babylonjs", + "main": "index.js", + "scripts": { + "lint": "echo noop", + "lint:fix": "echo noop", + "start": "start-storybook -p 6006 -s ./storyboard-site", + "build-storybook": "build-storybook -o storybook-static -s ./storyboard-site" + }, + "devDependencies": { + "@babel/core": "^7.16.0", + "@babylonjs/inspector": "^4.2.0", + "@babylonjs/loaders": "^4.2.0", + "@babylonjs/materials": "^4.2.0", + "@babylonjs/procedural-textures": "^4.2.0", + "@inlet/react-pixi": "^6.6.5", + "@storybook/addon-storysource": "^6.3.12", + "@storybook/react": "^6.3.12", + "@storybook/theming": "^6.3.12", + "babel-loader": "8.2.3", + "cannon": "^0.6.2", + "chroma-js": "^2.1.0", + "earcut": "^2.2.2", + "gsap": "^3.6.1", + "honeycomb-grid": "^3.1.7", + "lerp": "^1.0.3", + "pixi-projection": "^0.4.2", + "pixi.js": "^6.1.2", + "react-babylon-spring": "^1.0.2", + "zustand": "^3.6.4" + }, + "dependencies": { + "react": "^17.0.2", + "react-babylonjs": "*", + "react-dom": "^17.0.2" + } +} diff --git a/packages/storybook-static/stories/babylonjs/Basic/animation.stories.js b/packages/storybook-static/stories/babylonjs/Basic/animation.stories.js new file mode 100644 index 00000000..c56251e3 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Basic/animation.stories.js @@ -0,0 +1,98 @@ +import React, { useEffect, useRef } from 'react' +import { Vector3, Animation } from '@babylonjs/core'; +import { Engine, Scene, useScene } from 'react-babylonjs' +import '../../style.css'; + +export default { title: 'Babylon Basic' }; + +/** + * This is for optimizing animation when first mount application. + * But this story works well,Animation is smooth。 + */ +function WithAnimation() { + // console.time('Timing'); + + const groupRef = useRef(null); + const scene = useScene(); + + const position = Vector3.Zero(); + + const playAnimation = () => { + if (groupRef.current) { + const group = groupRef.current; + const animations = getSlideUpAnimation(position, -2); + const animatable = scene.beginDirectAnimation(group, animations, 0, 120, true); + // console.timeLog('Timing', 'beginAnimation'); + } + }; + + useEffect(_ => { + // console.timeLog('Timing', 'useEffect'); + playAnimation(); + }, []); + + const onCreated = _ => { + // console.timeLog('Timing', 'onCreated'); + }; + + const spheres = getSpheres(10); + + return ( + + {spheres} + + ) +} + +function getSpheres(count) { + const results = []; + + for (let i = -count / 2; i < count / 2; i++) { + for (let j = -count / 2; j < count / 2; j++) { + const key = `sphere-${i}-${j}`; + results.push( + + ) + } + } + + return results; +} + +function getSlideUpAnimation(position, offsetY) { + const { y } = position; + + const keys = [{ + frame: 0, + value: y + offsetY, + }, { + frame: 60, + value: y + }, { + frame: 120, + value: y + offsetY + }]; + + const animation = new Animation( + 'animation', "position.y", + 60, 0, 1 + ); + animation.setKeys(keys); + + return [animation]; +} + + +export const Animations = () => ( +
+ + + + + + + +
+) diff --git a/packages/storybook-static/stories/babylonjs/Basic/babylonBasic.stories.js b/packages/storybook-static/stories/babylonjs/Basic/babylonBasic.stories.js new file mode 100644 index 00000000..a569cf95 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Basic/babylonBasic.stories.js @@ -0,0 +1,45 @@ +import React, { useEffect, useRef } from 'react'; +import { Engine, Scene, useScene } from 'react-babylonjs'; +import { Color3 } from '@babylonjs/core/Maths/math.color'; +import { Vector3 } from '@babylonjs/core/Maths/math.vector'; +import '../../style.css' + +export default { title: 'Babylon Basic' }; + +const rpm = 5; +const MovingBox = (props) => { + // access Babylon Scene + const scene = useScene(); + // access refs to Babylon objects in scene like DOM nodes + const boxRef = useRef(null); + + // there is also a built-in hook called useBeforeRender that does will do this: + useEffect(() => { + if (boxRef.current) { + const handler = scene.registerBeforeRender(() => { + let deltaTimeInMillis = scene.getEngine().getDeltaTime(); + boxRef.current.rotation[props.rotationAxis] += ((rpm / 60) * Math.PI * 2 * (deltaTimeInMillis / 1000)) + }) + return (() => { + scene.unregisterBeforeRender(handler); + }) + } + }, [boxRef.current]); + + return ( + + ); +} + +export const DefaultPlayground = () => ( +
+ + + + + + + + +
+) diff --git a/packages/storybook-static/stories/babylonjs/Basic/contextBridge.stories.js b/packages/storybook-static/stories/babylonjs/Basic/contextBridge.stories.js new file mode 100644 index 00000000..4eec3d87 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Basic/contextBridge.stories.js @@ -0,0 +1,52 @@ +import React from 'react' +import { Engine, Scene } from 'react-babylonjs' +import { Vector3, Color3 } from '@babylonjs/core/Maths/math' +import '../../style.css' + +export default { title: 'Babylon Basic' }; + +const ThemeContext = React.createContext({ + color: Color3.Red(), + posigion: Vector3.Zero(), + name: 'default context' +}); + +const ThemedBox = () => { + const ctx = React.useContext(ThemeContext); + return ( + + + + ); + }; + +const EngineScene = () => ( +
+ + {value => ( + + + + + + + + + + + )} + +
+) + +export const BridgedContext = () => ( + + + +); \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/Basic/customMeshes.stories.js b/packages/storybook-static/stories/babylonjs/Basic/customMeshes.stories.js new file mode 100644 index 00000000..e7b81fb1 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Basic/customMeshes.stories.js @@ -0,0 +1,76 @@ +import React, { useState } from 'react' +import { Engine, Scene, useScene } from 'react-babylonjs' +import { Mesh, VertexData, Vector3 } from '@babylonjs/core'; +import '../../style.css' + +export default { title: 'Babylon Basic' }; + +const CustomMesh = (props) => { + const scene = useScene(); + + const [customMesh] = useState(() => { + const meshInstance = new Mesh(props.name, scene); + + //Set arrays for positions and indices + var positions = [-5, 2, -3, -7, -2, -3, -3, -2, -3, 5, 2, 3, 7, -2, 3, 3, -2, 3]; + var indices = [0, 1, 2, 3, 4, 5]; + var colors = [1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1]; + + //Empty array to contain calculated values + var normals = []; + + var vertexData = new VertexData(); + VertexData.ComputeNormals(positions, indices, normals); + + //Assign positions, indices and normals to vertexData + vertexData.positions = positions; + vertexData.indices = indices; + vertexData.normals = normals; + vertexData.colors = colors; + + //Apply vertexData to custom mesh + vertexData.applyToMesh(meshInstance); + + return meshInstance; + }) + + return ( + + + + ) +} + +export const CustomMeshes = () => { + const [displayLast, setDisplayLast] = useState(true); + const toggleDisplay = () => { + setDisplayLast(cur => !cur); + }; + return ( + <> +
+ +
+
+ + + + + + + + { displayLast && + + } + + +
+ + ) +} diff --git a/packages/storybook-static/stories/babylonjs/Basic/dynamicTerrain.stories.js b/packages/storybook-static/stories/babylonjs/Basic/dynamicTerrain.stories.js new file mode 100644 index 00000000..916415da --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Basic/dynamicTerrain.stories.js @@ -0,0 +1,45 @@ +import React from 'react' +import { Engine, Scene } from 'react-babylonjs' +import { Vector3, Color3, Color4 } from '@babylonjs/core/Maths/math' +import '../../style.css' + +export default { title: 'Babylon Basic' }; + +const xSize = 500 +const zSize = 500 +const subSize = 100 + +const getMapData = () => { + let mapSubX = xSize + let mapSubZ = zSize + + // map creation + let mapData = new Float32Array(mapSubX * mapSubZ * 3) + for (var l = 0; l < mapSubZ; l++) { + for (var w = 0; w < mapSubX; w++) { + mapData[3 * (l * mapSubX + w)] = (w - mapSubX * 0.5) * 2.0 + mapData[3 * (l * mapSubX + w) + 1] = w / (l + 1) * Math.sin((l + 1) / 2) * Math.cos(w / 2) * 2.0 + mapData[3 * (l * mapSubX + w) + 2] = (l - mapSubZ * 0.5) * 2.0 + } + } + return mapData +} + +const WithDynamicTerrain = () => ( + + + + + + + + + +) + + +export const DynamicTerrain = () => ( +
+ +
+) diff --git a/packages/storybook-static/stories/babylonjs/Basic/edgesRendering.stories.js b/packages/storybook-static/stories/babylonjs/Basic/edgesRendering.stories.js new file mode 100644 index 00000000..a6b07372 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Basic/edgesRendering.stories.js @@ -0,0 +1,36 @@ +import React from 'react' +import { Vector3, Color4 } from '@babylonjs/core'; +import '@babylonjs/core/Rendering/edgesRenderer' // You this need for side-effects +import { Engine, Scene } from 'react-babylonjs' +import '../../style.css'; + +export default { title: 'Babylon Basic' }; + +/** + * https://www.babylonjs-playground.com/#TYAHX#10 + */ +export const EdgesRendering = () => ( +
+ + + + + box.enableEdgesRendering()} + edgesWidth={4} + size={2} + position={new Vector3(0, 1.2, 0)} + edgesColor={new Color4(0, 0, 1, 1)} + /> + g.enableEdgesRendering()} + edgesWidth={3} + width={6} + height={6} + subdivisions={1} + /> + + +
+) diff --git a/packages/storybook-static/stories/babylonjs/Basic/engineView.stories.js b/packages/storybook-static/stories/babylonjs/Basic/engineView.stories.js new file mode 100644 index 00000000..ed26f597 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Basic/engineView.stories.js @@ -0,0 +1,102 @@ +import React, { useRef } from 'react' +import '@babylonjs/inspector' +import { Engine, Scene } from 'react-babylonjs' +import { Vector3, Color3 } from '@babylonjs/core/Maths/math' +import '../../style.css' + +export default { title: 'Babylon Basic' }; + +const size = 2; +const shade = 0; + +const BoxWithArrows = ({ position }) => { + return ( + + + + + ) +} + +const MultiCanvas = ({secondCanvas}) => { + const freeCameraRef = useRef(undefined); + return ( + <> + + + + + + + + + {(secondCanvas && secondCanvas.current !== null) && + + } + + ) +} + +export const EngineView = () => { + const secondCanvasRef = useRef(null); + return ( +
+
+ + + + + +
+
+ +
+
+ ); +} diff --git a/packages/storybook-static/stories/babylonjs/Basic/fromInstance.stories.js b/packages/storybook-static/stories/babylonjs/Basic/fromInstance.stories.js new file mode 100644 index 00000000..2cf6c24a --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Basic/fromInstance.stories.js @@ -0,0 +1,56 @@ +import React, { useState, useMemo } from 'react' +import { Engine, Scene, useScene } from 'react-babylonjs' +import { Vector3, Color3, MeshBuilder } from '@babylonjs/core' +import '../../style.css' + +export default { title: 'Babylon Basic' }; + +const MyMesh = (props) => { + const [mesh, setMesh] = useState(null); + const scene = useScene(); + useMemo(() => { + console.log('creating a box with scene', scene); + setMesh(MeshBuilder.CreateBox('test', { size: 1 }, scene)); + }, []); + + return ( + <> + {mesh && + + + + } + + ) +} + +export const FromInstance = () => { + const [rotation, setRotation] = useState(new Vector3(0, 0, 0)); + const addRotation = () => { + setRotation((state) => new Vector3(0, rotation.y + Math.PI / 4, 0)); + }; + + return ( +
+ + + + + + + + +
+ ); +} diff --git a/packages/storybook-static/stories/babylonjs/Basic/gizmo.stories.js b/packages/storybook-static/stories/babylonjs/Basic/gizmo.stories.js new file mode 100644 index 00000000..f51917dd --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Basic/gizmo.stories.js @@ -0,0 +1,30 @@ +import React from 'react'; +import { Engine, Scene } from 'react-babylonjs'; +import { Color3 } from '@babylonjs/core/Maths/math.color'; +import { Vector3 } from '@babylonjs/core/Maths/math.vector'; +import '../../style.css' + +// export default { title: 'Babylon Basic' }; + +const GizmoBox = ({position, color} = props) => ( + + + + +) + +// broken in 4.2 - works in 5.0 +const Gizmo = () => ( +
+ + + + + + + + + + +
+) diff --git a/packages/storybook-static/stories/babylonjs/Basic/gizmoManager.stories.js b/packages/storybook-static/stories/babylonjs/Basic/gizmoManager.stories.js new file mode 100644 index 00000000..68602277 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Basic/gizmoManager.stories.js @@ -0,0 +1,54 @@ +import React, { useEffect, useState } from 'react'; +import { Engine, Scene, useScene } from 'react-babylonjs'; +import { Color3 } from '@babylonjs/core/Maths/math.color'; +import { Vector3 } from '@babylonjs/core/Maths/math.vector'; +import '../../style.css' + +// export default { title: 'Babylon Basic' }; + +const Inspector = () => { + const scene = useScene(); + scene.debugLayer.show(); + return null; +} + +// broken in 4.2 - works in 5.0 +const GizmoManager = () => { + const [lightRef, setLightRef] = useState(undefined); + + useEffect(() => { + console.log('light has been set', lightRef); + }, [lightRef]) + return ( +
+ + + + + + + + + + + + + + + + + + + + + +
+ ) +} \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/Basic/instances.stories.js b/packages/storybook-static/stories/babylonjs/Basic/instances.stories.js new file mode 100644 index 00000000..35b1687b --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Basic/instances.stories.js @@ -0,0 +1,90 @@ +import React, { useState, useCallback } from 'react' +import { Engine, Scene } from 'react-babylonjs' +import { Vector3, Color3, Color4 } from '@babylonjs/core' +import { defineGrid, extendHex } from 'honeycomb-grid' +import '../../style.css' + +export default { title: 'Babylon Basic' }; + +const GRID_WIDTH = 60; +const GRID_HEIGHT = 40; +const HOVER_COLOR = new Color4(0.8, 0.8, 0.8, 1); + +export const Instances = () => { + const [_, setState] = useState(false); + const createUpdate = () => { + setState((state) => !state); + }; + + // const hexRef = useRef>(null); + const [hexMesh, setHexMesh] = useState(null); + const hexRef = useCallback((node) => { + if (node) { + const mesh = node; + mesh.registerInstancedBuffer("color", 4); + setHexMesh(mesh); + } + }, []); + + const Hex = extendHex({ + size: 1, // default: 1 + orientation: 'flat', // default: 'pointy' + color: new Color4(0, 0.68, 1), + hovered: false + }) + + // create a Grid factory that uses the Hex factory: + const Grid = defineGrid(Hex) + + // create a rectangle grid with each tile assigned a random color: + const grid = Grid.rectangle({ width: GRID_WIDTH, height: GRID_HEIGHT, onCreate: (hex) => { + hex.color = new Color4(Math.random(), Math.random(), Math.random(), 1); + hex.isHovered = Math.random() < 0.1; + } }) + + return ( +
+ + + + + + + {hexMesh && + Array.from(grid.entries()).map(entry => { + const [i, tile] = entry; + const {x, y} = tile.toPoint(); + console.log(`${i}->{${x},${y}} (${tile.width()})`) + return ( + + ) + }) + } + + +
+ ); + } diff --git a/packages/storybook-static/stories/babylonjs/Basic/portal.stories.js b/packages/storybook-static/stories/babylonjs/Basic/portal.stories.js new file mode 100644 index 00000000..4fbbf87d --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Basic/portal.stories.js @@ -0,0 +1,54 @@ +import React, { useEffect, useRef, useState } from 'react'; +import '@babylonjs/inspector'; +import { Engine, Scene, useBeforeRender, createPortal } from '../../../../dist/react-babylonjs'; +import { Vector3 } from '@babylonjs/core/Maths/math.vector'; +import { Color3 } from '@babylonjs/core/Maths/math.color'; +import '../../style.css' + +export default { title: 'Babylon Basic' }; + +const rpm = 5; + +function WithCreatePortal() { + const transformNodeRef = useRef(null); + const [_, setReady] = useState(false); + + useBeforeRender((scene) => { + if (transformNodeRef.current !== null) { + const deltaTimeInMillis = scene.getEngine().getDeltaTime(); + transformNodeRef.current.rotation.y += ((rpm / 60) * Math.PI * 2 * (deltaTimeInMillis / 1000)); + } + }) + + useEffect(() => { + console.log('trigger re-render when transform node is set.'); + setReady(true); + }, [transformNodeRef.current]) + + return ( + <> + {(transformNodeRef.current) && + createPortal( + + , transformNodeRef.current['__rb_createdInstance']) + } + + + + + ) +} + +export const CreatePortal = () => ( +
+ + + + + + + + +
+) diff --git a/packages/storybook-static/stories/babylonjs/Basic/shapes.stories.js b/packages/storybook-static/stories/babylonjs/Basic/shapes.stories.js new file mode 100644 index 00000000..9a45b8d9 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Basic/shapes.stories.js @@ -0,0 +1,97 @@ +import React, { useCallback } from 'react' +import '@babylonjs/inspector' +import { Engine, Scene } from 'react-babylonjs' +import { Vector3, Color3, CSG, Mesh, MeshBuilder, StandardMaterial } from '@babylonjs/core' +import * as Earcut from 'earcut'; +import "@babylonjs/core/Meshes/meshBuilder"; +import '../../style.css' + +export default { title: 'Babylon Basic' }; + +//Polygon shape in XoZ plane +var starPath = [ + new Vector3(4, 0, -4), + new Vector3(2, 0, 0), + new Vector3(5, 0, 2), + new Vector3(1, 0, 2), + new Vector3(-5, 0, 5), + new Vector3(-3, 0, 1), + new Vector3(-4, 0, -4), + new Vector3(-2, 0, -3), + new Vector3(2, 0, -3) +]; + +//Holes in XoZ plane +var holes = [ + [ + new Vector3(1, 0, -1), + new Vector3(1.5, 0, 0), + new Vector3(1.4, 0, 1), + new Vector3(0.5, 0, 1.5) + ], [ + new Vector3(0, 0, -2), + new Vector3(0.5, 0, -1), + new Vector3(0.4, 0, 0), + new Vector3(-1.5, 0, 0.5) + ] +]; + +let scene = null; +const onSceneMounted = (sceneEventArgs) => { + scene = sceneEventArgs.scene; +} + +const Shapes = () => { + const ref = useCallback(node => { + if (node) { + const csg = CSG.FromMesh(node); + console.log('csg:', csg); + const sphere = MeshBuilder.CreateSphere('circle', { + diameter: 3 + }, scene); + sphere.position.x -= 2 + let res = csg.subtract(CSG.FromMesh(sphere)) + + let csgMeshMaterial = new StandardMaterial('material01', scene); + csgMeshMaterial.diffuseColor = Color3.Yellow() + csgMeshMaterial.specularColor = Color3.Black() + let mesh = res.toMesh('base', csgMeshMaterial, scene, false); + mesh.position.y += 4; + sphere.dispose() + } + }, []); + + return ( + + + + + + + + + + ) +} + +export const ExtrudeShapesPlusCSG = () => ( +
+ +
+) + +ExtrudeShapesPlusCSG.story = { + name: 'Extrude (+CSG)', + parameters: + { + notes: 'Extrude Shape and *Constructive Solid Geometry* (CSG). There are no plans to integrate CSG declaratively yet.' + } +} \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/Basic/skybox.stories.js b/packages/storybook-static/stories/babylonjs/Basic/skybox.stories.js new file mode 100644 index 00000000..f6d6af17 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Basic/skybox.stories.js @@ -0,0 +1,59 @@ +import React, { useState } from 'react' +import '@babylonjs/inspector' +import { Engine, Scene, Skybox } from 'react-babylonjs' +import { Vector3 } from '@babylonjs/core/Maths/math' +import '../../style.css' + +export default { title: 'Babylon Basic' }; + +let globalIndex = 0 // due to closure and how observables are assigned. +const SkyboxScenes = [{ + name: 'sunny day', + texture: `assets/textures/TropicalSunnyDay` +}, { + name: 'specular HDR', + texture: `assets/textures/SpecularHDR.dds` +}] + +function WithSkybox () { + const [skyboxIndex, setIndex] = useState(0) + globalIndex = skyboxIndex + + return ( + + + + + + + + { + Array.from(new Array(50), (_, index) => index).map(number => { + return ( + setIndex(globalIndex + 1)} + /> + ) + }) + } + + + + + ) +} + +export const Skybox3D = () => ( +
+ +
+) + +Skybox3D.story = { + name: 'Skybox 3D' +} diff --git a/packages/storybook-static/stories/babylonjs/Basic/snippetMaterial.stories.js b/packages/storybook-static/stories/babylonjs/Basic/snippetMaterial.stories.js new file mode 100644 index 00000000..25e7723e --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Basic/snippetMaterial.stories.js @@ -0,0 +1,96 @@ +import React, { useState, useCallback, useEffect } from 'react' +import { Vector3, NodeMaterial, Color3 } from '@babylonjs/core'; +import { Texture } from "@babylonjs/core/Materials/Textures/texture"; +import '@babylonjs/core/Rendering/edgesRenderer' // You this need for side-effects +import { Engine, Scene, useScene } from 'react-babylonjs' + +import '../../style.css'; + +export default { title: 'Babylon Basic' }; + +const setBlockValue = ( + name, + value, + material +) => { + if (value instanceof Texture) { + let textureBlock = material.getTextureBlocks().find((b) => b.name === name); + if (textureBlock !== undefined) { + textureBlock.texture = value; + } + } else { + let block = material.getInputBlockByPredicate((b) => b.name === name); + if (block !== null) { + block.value = value; + } + } +}; + +const SnippetMaterialById = ({ snippetId, name, blockValues, freeze }) => { + const scene = useScene(); + const [material, setMaterial] = useState(null); + const parseMaterial = useCallback(async () => { + NodeMaterial.ParseFromSnippetAsync(snippetId, scene).then( + (nodeMaterial) => { + if (material !== null && freeze === true) { + material.freeze(); + } + setMaterial(nodeMaterial); + } + ); + }, [snippetId, scene]); + + useEffect(() => { + if (material) { + if (freeze === true && material.isFrozen) { + material.unfreeze(); + } + blockValues.forEach((entry) => { + setBlockValue(entry.name, entry.value, material) + }) + if (freeze === true) { + material.freeze(); + } + } + }, [blockValues]); + + useEffect(() => { + parseMaterial(); + }, [parseMaterial]); + + return material === null ? null : ( + + ); +}; + +const colors = ["Red", "Green", "Yellow"] + +export const SnippetMaterial = () => { + const [selectedColor, setSelectedColor] = useState("Green"); + const onChange = (e) => { + setSelectedColor(e.target.value); + } + return ( + <> +
+ +
+
+ + + + + + + + + + +
+ + ) +} diff --git a/packages/storybook-static/stories/babylonjs/Basic/toggleMesh.stories.js b/packages/storybook-static/stories/babylonjs/Basic/toggleMesh.stories.js new file mode 100644 index 00000000..c6f20fae --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Basic/toggleMesh.stories.js @@ -0,0 +1,72 @@ +import React, { useState } from 'react' +import { Engine, Scene } from 'react-babylonjs' +import { Vector3 } from '@babylonjs/core/Maths/math' +import '../../style.css' +import { Color3 } from "@babylonjs/core"; +import ScaledModelWithProgress from "../ScaledModelWithProgress"; + +export default { title: 'Babylon Basic' }; + +/** + * To fix two bugs when toggle meshes: + * 1. model's mesh can't be destroyed. + * 2. `removeChildFromContainer()` only destroy babylon instance. + * The model is rootAbstractMesh's and Parent's child. + * `container.rootInstance.children` will be very large after few toggles. + */ + + +function WithToggleMesh() { + const [isShown, toggleShown] = useState(true); + + const onClick = () => { + console.log('toggle clicked:', isShown); + toggleShown(isShown => !isShown) + }; + + return ( + <> + {isShown && + + + + + + + + } + + + + + + + + + + + + ) +} + +export const ToggleMesh = () => ( +
+ + + + + + + +
+) diff --git a/packages/storybook-static/stories/babylonjs/Basic/toggleScene.stories.js b/packages/storybook-static/stories/babylonjs/Basic/toggleScene.stories.js new file mode 100644 index 00000000..991d399e --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Basic/toggleScene.stories.js @@ -0,0 +1,90 @@ +import React, {useState} from 'react' +import {Engine, Scene, useScene} from 'react-babylonjs' +import {Vector3} from '@babylonjs/core/Maths/math' +import '../../style.css' +import {Color3} from "@babylonjs/core"; + +export default { title: 'Babylon Basic' }; + +const FullScreenButton = (props) => { + const [currentShape, setCurrentShape] = props.shapeState; + const scene = useScene(); + scene.debugLayer.show(); + const onClick = _ => { + setCurrentShape(currentShape => { + console.log('toggling current shape', currentShape); + return currentShape === 'spheres' ? 'squares' : 'spheres'; + }) + }; + + return ( + + + + + + + + + + ) +} + +const SphereScene = (props) => ( + + + + + {[-4,-2,0,2,4].map(number => ( + + )) + } + +) + +const SquareScene = (props) => ( + + + + + {[-4,-2,0,2,4].map(number => ( + + )) + } + +) + +export const ToggleScene = () => { + const shapeState = useState('spheres'); + + return ( +
+ + {(shapeState[0] === 'spheres') && + + } + {(shapeState[0] === 'squares') && + + } + +
+ ); +} diff --git a/packages/storybook-static/stories/babylonjs/Basic/transformNode.stories.js b/packages/storybook-static/stories/babylonjs/Basic/transformNode.stories.js new file mode 100644 index 00000000..7f3eabfc --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Basic/transformNode.stories.js @@ -0,0 +1,67 @@ +import React, {useEffect, useState} from 'react' +import '@babylonjs/inspector' +import {Engine, Scene} from 'react-babylonjs' +import {Vector3} from '@babylonjs/core/Maths/math' +import '../../style.css' + +export default { title: 'Babylon Basic' }; + +let lastTime = Date.now(); + +function WithTransformNode() { + const [position, setPosition] = useState(Vector3.Zero()); + const [rotation, setRotation] = useState(Vector3.Zero()); + + let timer; + let direction = 1; + + const animate = _ => { + if (position.x > 1) { + direction = -1; + } else if (position.x < -1) { + direction = 1; + } + + const velocity = 0.005 * direction; + position.x += velocity; + const rpm = 10; + const now = Date.now() + const deltaTimeInMillis = now - lastTime; + lastTime = now; + const rotationRads = ((rpm / 60) * Math.PI * 2 * (deltaTimeInMillis / 1000)); + rotation.y += rotationRads; + setPosition(position.clone()); + setRotation(rotation.clone()); + timer = requestAnimationFrame(animate); + }; + + useEffect(() => { + timer = requestAnimationFrame(animate); + return () => cancelAnimationFrame(timer); + }, []); + + return ( + + + + + + + + + + + + + + ) +} + +export const TransformNode = () => ( +
+ +
+) diff --git a/packages/storybook-static/stories/babylonjs/Basic/viewport.stories.js b/packages/storybook-static/stories/babylonjs/Basic/viewport.stories.js new file mode 100644 index 00000000..a3cf51b2 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Basic/viewport.stories.js @@ -0,0 +1,98 @@ +import React from 'react' +import '@babylonjs/inspector' +import { Engine, Scene, useScene } from 'react-babylonjs' +import { Vector3, Color3 } from '@babylonjs/core/Maths/math' +import '../../style.css' + +export default { title: 'Babylon Basic' }; + +const size = 2; +const shade = 0; + +const BoxWithArrows = ({ position }) => { + return ( + + + + + ) +} + +const MultiViewport = () => { + const scene = useScene(); + + const alwaysActive = (camera) => { + scene.activeCameras = [...(scene.activeCameras || []), camera]; + } + return ( + <> + + + + + + + + + + + + + ) +} + +export const Viewport = () => ( +
+ + + + + +
+) diff --git a/packages/storybook-static/stories/babylonjs/Behaviors/dragNdrop.stories.js b/packages/storybook-static/stories/babylonjs/Behaviors/dragNdrop.stories.js new file mode 100644 index 00000000..5b28aea2 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Behaviors/dragNdrop.stories.js @@ -0,0 +1,72 @@ +import React, { useEffect, useState, useRef } from 'react' +import { Engine, Scene } from 'react-babylonjs' +import { Vector3, Color3 } from '@babylonjs/core/Maths/math' +import '../../style.css' + +export default { title: 'Behaviors' }; + +// insipiration demo: https://www.babylonjs.com/demos/dragndrop/dragdrop.js +const GROUND_SIZE = 1000; +const validateDrag = (targetPosition) => { + return Math.max(Math.abs(targetPosition.x), Math.abs(targetPosition.z)) <= (GROUND_SIZE / 2) - 10; // should be -15 for torus +} + +export const DragNDrop = () => { + const red = useRef(0); + const [pointLightDiffuse, setPointLightDiffuse] = useState(new Color3(red.current, 0.5, 0.5)); + + useEffect(() => { + const handle = setInterval(() => { + red.current = (red.current + 0.1) % 1; + setPointLightDiffuse(new Color3(red.current, 0.5, 0.5)); + }, 1000); + return () => clearInterval(handle); + }, []) + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) +} + +DragNDrop.story = { + name: "Drag 'n' Drop", + parameters: { + notes: { + markdown: `Often the declarative version can be much simpler! + + Here is the reference playground: [link](https://www.babylonjs.com/demos/dragndrop/dragdrop.js)` + } + } +} \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/Behaviors/pointerDragBehavior.stories.js b/packages/storybook-static/stories/babylonjs/Behaviors/pointerDragBehavior.stories.js new file mode 100644 index 00000000..74804369 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Behaviors/pointerDragBehavior.stories.js @@ -0,0 +1,42 @@ +import React from 'react' +import {Engine, Scene} from 'react-babylonjs' +import {Vector3} from '@babylonjs/core/Maths/math' +import '../../style.css' + +export default { title: 'Behaviors' }; + +/** + * official demo: + * https://www.babylonjs-playground.com/#YEZPVT + * + * TODO: camera autoAttaching? + */ + +function WithPointerDragBehavior() { + return ( + <> + + console.log('dragStart')} + onDragObservable={_ => console.log('drag')} + onDragEndObservable={_ => console.log('dragEnd')}/> + + + + ) +} + +export const PointerDragBehavior = () => ( +
+ + + + + + + +
+) diff --git a/packages/storybook-static/stories/babylonjs/GUI/grid.stories.js b/packages/storybook-static/stories/babylonjs/GUI/grid.stories.js new file mode 100644 index 00000000..4150eac2 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/GUI/grid.stories.js @@ -0,0 +1,79 @@ +import React, { useEffect, useState } from 'react'; +import { Vector3 } from '@babylonjs/core'; +import { Engine, Scene, useScene } from 'react-babylonjs'; + +import '../../style.css'; +import { ValueAndUnit } from '@babylonjs/gui/2D/valueAndUnit'; + +export default { title: 'GUI' }; + +const FullScreen = () => { + // should run on latest alphas of BabylonJS 5.0 alpha 63+ + // https://github.com/BabylonJS/Babylon.js/pull/11569 + // https://playground.babylonjs.com/#0ZVTMY + // const direction = useRef(1); + // const [low, setLow] = useState(0.5); + + // useEffect(() => { + // const handle = setInterval(() => { + // setLow(cur => { + // const next = cur + (0.1 * direction.current); + // console.log('next:', next); + // if (next < 0.1 || next > 0.9) { + // direction.current *= -1; + // } + // return next; + // }) + // }, 1000); + + // return () => { + // clearInterval(handle); + // } + // }, []) + + const [background, setBackground] = useState('black'); + useEffect(() => { + const handle = setInterval(() => { + setBackground(cur => cur === 'black' ? '#222222' : 'black') + }, 1000); + + return () => { + clearInterval(handle); + } + }, []) + + + return ( + + + + + + + + + + + + + + + + ) +} + +export const Grid = () => ( +
+ + + + + + + +
+) + +Grid.story = { + name: "Grid" +} \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/GUI/gui.stories.js b/packages/storybook-static/stories/babylonjs/GUI/gui.stories.js new file mode 100644 index 00000000..f4e932b7 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/GUI/gui.stories.js @@ -0,0 +1,146 @@ +import React, { useRef, useCallback } from 'react' +import '@babylonjs/inspector' +import {Engine, Scene} from 'react-babylonjs' +import {Vector3} from '@babylonjs/core/Maths/math' +import '../../style.css' +import {Control} from '@babylonjs/gui'; + +export default { title: 'GUI' }; + + +/** + * official example + * https://www.babylonjs-playground.com/#3VMTI9#0 + */ + +/** + * TODO: other gui、mesh link、 + */ + +/** + * 2d GUI demos + * @return {*} + * @constructor + */ +function WithGUI() { + // const lineRef = useRef(null) + const sphere1Ref = useRef(null); + const label1Ref = useRef(null); + const sphere2Ref = useRef(null); + const label2Ref = useRef(null); + const sphere3Ref = useRef(null); + const label3Ref = useRef(null); + const sphere4Ref = useRef(null); + const label4Ref = useRef(null); + const sphere5Ref = useRef(null); + const label5Ref = useRef(null); + const sphere6Ref = useRef(null); + const label6Ref = useRef(null); + const sphere7Ref = useRef(null); + const lineRef = useRef(null); + const label7Ref = useRef(null); + + const refLookup = { + '1': { + sphere: sphere1Ref, + label: label1Ref + }, + '2': { + sphere: sphere2Ref, + label: label2Ref + }, + '3': { + sphere: sphere3Ref, + label: label3Ref + }, + '4': { + sphere: sphere4Ref, + label: label4Ref + }, + '5': { + sphere: sphere5Ref, + label: label5Ref + }, + '6': { + sphere: sphere6Ref, + label: label6Ref + }, + '7': { + sphere: sphere7Ref, + label: label7Ref + } + } + + const onFullScreenRef = useCallback(ref => { + const line = lineRef.current + + try { + line.linkWithMesh(sphere7Ref.current); + line.connectedControl = label7Ref.current; + + + [1,2,3,4,5,6].forEach((i) => { + const lookup = refLookup[i.toString()]; + lookup.label.current.linkWithMesh(lookup.sphere.current) + }) + } catch (e) { + console.error(e) + } + }); + + return ( + + + + + + + + + + + + + + + + {/**/} + {/* */} + + {/**/} + + {[1,2,3,4,5,6,7].map((i) => + + + + ) + + } + + + + + + + ) +} + +export const GUIFullScreen = () => ( +
+ +
+) diff --git a/packages/storybook-static/stories/babylonjs/GUI/html.stories.js b/packages/storybook-static/stories/babylonjs/GUI/html.stories.js new file mode 100644 index 00000000..c57d02b0 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/GUI/html.stories.js @@ -0,0 +1,64 @@ +import React, { useEffect, useState } from 'react'; +import { Engine, Scene, Html } from 'react-babylonjs'; +import { Vector3 } from '@babylonjs/core/Maths/math'; +import '../../style.css'; + +export default { title: 'GUI' }; + +let lastTime = Date.now(); + +function WithHtmlText() { + const [position, setPosition] = useState(Vector3.Zero()); + const [rotation, setRotation] = useState(Vector3.Zero()); + + let timer; + let direction = 1; + + const animate = _ => { + if (position.x > 1) { + direction = -1; + } else if (position.x < -1) { + direction = 1; + } + + const velocity = 0.005 * direction; + position.x += velocity; + const rpm = 10; + const now = Date.now() + const deltaTimeInMillis = now - lastTime; + lastTime = now; + const rotationRads = ((rpm / 60) * Math.PI * 2 * (deltaTimeInMillis / 1000)); + rotation.y += rotationRads; + setPosition(position.clone()); + setRotation(rotation.clone()); + timer = requestAnimationFrame(animate); + }; + + useEffect(() => { + timer = requestAnimationFrame(animate); + return () => cancelAnimationFrame(timer); + }, []); + + return ( + + + + {
Text
} + +
+
+ ) +} + +export const HtmlText = () => ( +
+ + + + + + + +
+) diff --git a/packages/storybook-static/stories/babylonjs/GUI/with2DGUI.stories.js b/packages/storybook-static/stories/babylonjs/GUI/with2DGUI.stories.js new file mode 100644 index 00000000..cc9ea5b7 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/GUI/with2DGUI.stories.js @@ -0,0 +1,248 @@ +import React, { Component } from 'react' +import { Vector3, Color3, Color4, Animation, ExponentialEase, EasingFunction, Texture } from '@babylonjs/core' +import { Control } from '@babylonjs/gui' +import { Engine, Scene } from 'react-babylonjs' + +import '../../style.css' + +export default { title: 'GUI' }; + +const DEFAULT_BOXES = [{ + name: 'red', + position: new Vector3(-2.5, 1, 0), + color: Color3.Red(), + index: 1 +}, { + name: 'green', + position: new Vector3(2.5, 1, 0), + color: Color3.Green(), + index: 2 +}, { + name: 'blue', + position: new Vector3(0, 1, 0), + color: Color3.Blue(), + index: 3 +}]; + +class UIComponent extends Component { + constructor() { + super() + + this.state = { + plane: undefined, + showModal: false, + clickMeshName: undefined, + boxes: DEFAULT_BOXES, + sceneClearColor: new Color4(0.5, 0.5, 0.5, 0.5) + } + + this.meshPicked = this.meshPicked.bind(this); + this.setPlane = this.setPlane.bind(this); + this.deleteSelectedMesh = this.deleteSelectedMesh.bind(this); + // TODO: fix that bind() is needed on assignment on button pointerDown handlers + } + + meshPicked(mesh) { + const matchingBox = this.state.boxes.find(box => box.name === mesh.name); + if (matchingBox !== undefined) { + const clickedMeshName = mesh.name + let clickedMeshColor = matchingBox.color.toHexString(); + let sceneClearColor = Color4.FromColor3(matchingBox.color, 0.5); + + this.setState((state) => ({ + ...state, + showModal: true, + clickedMeshName, + clickedMeshColor, + sceneClearColor, + })) + } else { + console.log('ignoring clicks on:', mesh.name, this.state) + } + } + + deleteSelectedMesh() { + const newBoxes = this.state.boxes.filter(box => box.name !== this.state.clickedMeshName) + this.setState((state) => ({ + ...state, + sceneClearColor: new Color4(0.5, 0.5, 0.5, 0.5), + boxes: newBoxes + })) + + // They're all 'deleted'. Recreate them after a delay. + if (newBoxes.length === 0) { + console.log('recreating boxes in 2.5 seconds'); + let that = this; + window.setTimeout(() => { + that.setState((state) => ({ + ...state, + boxes: DEFAULT_BOXES + })) + }, 2500); + } + + this.hideModal() + } + + hideModal() { + let { plane } = this.state; + if (!plane) { + return; + } + + let keys = [] + keys.push({ frame: 0, value: 1 }); + keys.push({ frame: 10, value: 0 }); + + var animationClose = new Animation( + 'tv-off-1984', + 'scaling.x', + 10, + Animation.ANIMATIONTYPE_FLOAT, + Animation.ANIMATIONLOOPMODE_CONSTANT + ); + animationClose.setKeys(keys); + + let easingFunction = new ExponentialEase(9.7); // BABYLON.QuarticEase() + easingFunction.setEasingMode(EasingFunction.EASINGMODE_EASEINOUT); + animationClose.setEasingFunction(easingFunction); + + plane.animations.push(animationClose); + plane._scene.beginAnimation(plane, 0, 100, false, 1, () => { + plane.dispose(); + this.setState((state) => ({ + ...state, + showModal: false, + plane: undefined, + sceneClearColor: new Color4(0.5, 0.5, 0.5, 0.5) + })) + }); + } + + setPlane(plane) { + this.setState((state) => ({ + ...state, + plane + })) + + if (plane._scene && plane._scene.activeCamera) { + let { activeCamera } = plane._scene + + window.setTimeout(() => { + // we only need this hack because of storybook? + let forwardRayDirection = activeCamera.getForwardRay().direction + plane.position = activeCamera.position.add(forwardRayDirection.scale(1.5 / activeCamera.fov /* * forwardRay.length */)) + plane.lookAt(activeCamera.position, 0, Math.PI, Math.PI) + }, 10); + } + } + + render() { + let dialogWidth = 3 + let dialogHeight = 1 + + // (for testing insertBefore in react-reconciler - and put in a hosted element like the light). + // boxes.sort((a, b) => a.index - b.index); + + return ( + + + { + let { plane } = this.state + + if (plane) { + let forwardRay = camera.getForwardRay() + plane.position = camera.position.clone().add(forwardRay.direction.scale(1.5 / camera.fov /* * forwardRay.length */)) + plane.lookAt(camera.position, 0, Math.PI, Math.PI) + } + }} + /> + + {this.state.boxes.map(box => ( + + + + )) + } + + {this.state.showModal === true && + + + + + + + + + + + + + + + + { + this.state.boxes.map(box => ( + + )) + } + + + + + + + + + + + + + + + } + + + + ) + } +} + +export const With2DUI = () => ( +
+ +
+) + +With2DUI.story = { + name: "2D UI" +} \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/Hooks/hooks.stories.js b/packages/storybook-static/stories/babylonjs/Hooks/hooks.stories.js new file mode 100644 index 00000000..914ea21f --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Hooks/hooks.stories.js @@ -0,0 +1,109 @@ +import React, { useContext, useRef } from 'react' +import { Engine, Scene, EngineCanvasContext , SceneContext, useBeforeRender } from 'react-babylonjs' +import { Vector3, Color3 } from '@babylonjs/core/Maths/math' +import '../../style.css' + +export default { title: 'Hooks' }; + +const ContextLogger = (props, context) => { + console.log('Direct access to context depending on where declared yields different results. Using hooks directly useScene, useEngine, useCanvas is easier.'); + const ctx = useContext(EngineCanvasContext) + console.log(`ctx-logger "${props.id}" BabylonJSContext is:`, ctx) + + const ctx2 = useContext(SceneContext) + console.log(`ctx-logger "${props.id}" SceneContext is:`, ctx2) + return null; +} + +const size = 2; +const shade = 0; +const rpm = 10; + +const RotatingBox = ({position}) => { + const centerTransform = useRef(null); + useBeforeRender((scene) => { + if (centerTransform.current !== null) { + const deltaTimeInMillis = scene.getEngine().getDeltaTime(); + centerTransform.current.rotation.y += ((rpm / 60) * Math.PI * 2 * (deltaTimeInMillis / 1000)); + } + }) + + return ( + + + + + ) +} + +const RotatingBoxScene = (props) => ( + <> + + + + + + +) + +export const RenderHooksStory = () => ( +
+ + + + + + + +
+) + +RenderHooksStory.story = { + name: 'useBeforeRender' +} \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/Hooks/more-hooks.stories.js b/packages/storybook-static/stories/babylonjs/Hooks/more-hooks.stories.js new file mode 100644 index 00000000..1c44c44c --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Hooks/more-hooks.stories.js @@ -0,0 +1,53 @@ +import React from 'react'; +import { Engine, Scene, useEngine, useCanvas, useScene } from 'react-babylonjs' +import { Vector3 } from '@babylonjs/core' + +export default { title: 'Hooks' }; + +const MyScene = () => { + const engine = useEngine(); + const canvas = useCanvas(); + const scene = useScene(); + + // engine and canvas were null. Although not currently "bridged", the hooks check contexts on each side of renderer. + // https://github.com/konvajs/react-konva/issues/188#issuecomment-478302062 + console.log('MyScene', { engine, canvas, scene }) + + return ( + <> + + + + + ) +} + +const EngineChild = () => { + const engine = useEngine(); + const canvas = useCanvas(); + + console.log('EngineChild', { engine, canvas}); + return null; +} + +const RenderHooks = () => { + return ( + + + + + + + ) +} + +export const ConvenienceHooks = () => ( +
+
Look at console.
+ +
+) + +ConvenienceHooks.story = { + name: 'engine/canvas/scene' +} \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/Hooks/useAssetManager.stories.js b/packages/storybook-static/stories/babylonjs/Hooks/useAssetManager.stories.js new file mode 100644 index 00000000..43bccf05 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Hooks/useAssetManager.stories.js @@ -0,0 +1,111 @@ +import React, { Suspense, useState, useMemo, useRef, useLayoutEffect } from 'react'; +import { Engine, Scene, useAssetManager, TaskType, useBeforeRender } from 'react-babylonjs'; +import { Vector3, Color4, Color3 } from '@babylonjs/core'; +import '../../style.css'; + +export default { title: 'Hooks' }; + +// redeclaring array will force load the asset (not deep equality check on by reference) +const pointCloudAssets = [{ taskType: TaskType.Binary, url: 'assets/kitti/000000.bin', name: 'Velodyne-kitt-dataset' }]; + +const MyPCS = () => { + const pcsRef = useRef(null); + const result = useAssetManager(pointCloudAssets); + const [pcs, setPcs] = useState(null); + const [pcsMesh, setPcsMesh] = useState(null); + + useLayoutEffect(() => { + if (pcsRef.current) { // only loaded after suspend returns + setPcs(pcsRef.current); + } + }, [pcsRef]); + + useMemo(() => { + if (result && pcs) { + const floats = new Float32Array(result.tasks[0].data); + const POINTS_PER_FLOAT = 4; + const numPoints = floats.length / POINTS_PER_FLOAT; + + // particle is the current particle, the i-th one in the PCS and the s-th one in its group + const particleFunc = (particle, i, s) => { + // KITTI-formatted PCD + const x = floats[POINTS_PER_FLOAT * i] + const y = floats[POINTS_PER_FLOAT * i + 1] + const z = floats[POINTS_PER_FLOAT * i + 2] + // ignore the reflectance value + // const r = floats[POINTS_PER_FLOAT * i + 3] + particle.position = new Vector3(x, y, z) + particle.color = Color4.FromColor3(Color3.White()) + } + + // NOTE: you can do with useRef/useState + // but you don't know WHEN the reconciler will commit those changes and add the points... + pcs.addPoints(numPoints, particleFunc); + pcs.buildMeshAsync(() => { + setPcsMesh(pcs.mesh); + }) + } + }, [result, pcsRef.current]) + + return + {pcsMesh && + + } + +} + +const MyFallback = () => { + const boxRef = useRef(); + useBeforeRender((scene) => { + if (boxRef.current) { + var deltaTimeInMillis = scene.getEngine().getDeltaTime(); + + const rpm = 10; + boxRef.current.rotation.x = Math.PI / 4; + boxRef.current.rotation.y += ((rpm / 60) * Math.PI * 2 * (deltaTimeInMillis / 1000)); + } + }) + + return +} + +export const UseAssetManager = () => ( +
+ + + + + }> + + + + +
+); + +UseAssetManager.story = { + name: 'useAssetManager', + parameters: { + notes: { + markdown: `## Citation + + ./storybook-static/assets/kitti/000000.bin is retrieved from [the original KITTI website](http://www.cvlibs.net/datasets/kitti/index.php), + and redistributed under the [Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License](http://creativecommons.org/licenses/by-nc-sa/3.0/). + + References + + [1] Andreas Geiger, Philip Lenz, and Raquel Urtasun. [Are we ready for Autonomous Driving? The KITTI Vision Benchmark Suite](http://www.cvlibs.net/publications/Geiger2012CVPR.pdf). + In Conference on Computer Vision and Pattern Recognition (CVPR), 2012. + + [2] Andreas Geiger, Philip Lenz, Christoph Stiller, and Raquel Urtasun. [Vision meets Robotics: The KITTI Dataset](http://www.cvlibs.net/publications/Geiger2013IJRR.pdf). + International Journal of Robotics Research (IJRR), 2013. + ` + } + } +} \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/Hooks/useClick.stories.js b/packages/storybook-static/stories/babylonjs/Hooks/useClick.stories.js new file mode 100644 index 00000000..f0f2cdf9 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Hooks/useClick.stories.js @@ -0,0 +1,51 @@ +import React, {useState} from 'react' +import {Engine, Scene, useClick} from 'react-babylonjs' +import {Vector3} from '@babylonjs/core/Maths/math' +import '../../style.css' +import {Color3} from "@babylonjs/core/Maths/math.color"; + +export default {title: 'Hooks'}; + +const getRandomColor = (function () { + // const Colors = ['#4F86EC', '#D9503F', '#F2BD42', '#58A55C']; + const Colors = [[0.31, 0.53, 0.93, 1], [0.85, 0.31, 0.25, 1], [0.95, 0.74, 0.26, 1], [0.35, 0.65, 0.36, 1]]; + + let i = 0; + return () => { + i++; + return Colors[i % Colors.length]; + } +})(); + +const initialColor = Color3.FromArray(getRandomColor()); + +function WithUseClick() { + const [color, setColor] = useState(initialColor); + const [ref] = useClick(_ => { + const color = getRandomColor(); + setColor(Color3.FromArray(color)) + }); + + return + + +} + +export const UseClickEvent = () => ( +
+ + + + + + + + +
+); + +UseClickEvent.story = { + name: 'useClick' +} \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/Hooks/useHover.stories.js b/packages/storybook-static/stories/babylonjs/Hooks/useHover.stories.js new file mode 100644 index 00000000..c27ded80 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Hooks/useHover.stories.js @@ -0,0 +1,70 @@ +import React, {useState} from 'react' +import {Engine, Scene, useHover} from 'react-babylonjs' +import {Vector3} from '@babylonjs/core/Maths/math' +import {Control} from '@babylonjs/gui/2D/controls/control'; +import { TextWrapping} from '@babylonjs/gui/2D/controls' +import '../../style.css' + +export default {title: 'Hooks'}; + +function WithUseHover() { + const [scaling, setScaling] = useState(new Vector3(1, 1, 1)); + const [ref] = useHover( + _ => setScaling(new Vector3(1.5, 1.5, 1.5)), + _ => setScaling(new Vector3(1, 1, 1)) + ); + + return + +} + +const WithUseHoverGui = () => { + + const [color, setColor] = useState('white'); + const [isHovered, setIsHovered] = useState(false); + const [rectRef] = useHover( + _ => { + setColor('yellow'); + setIsHovered(true); + }, + _ => { + setColor('white'); + setIsHovered(false) + } + ); + + return + + + + + + + + +} + +export const UseHoverEvent = () => ( +
+ + + + + + + + + +
+); + +UseHoverEvent.story = { + name: 'useHover' +} \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/Integrations/Tunnel.tsx b/packages/storybook-static/stories/babylonjs/Integrations/Tunnel.tsx new file mode 100644 index 00000000..d1d798fe --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Integrations/Tunnel.tsx @@ -0,0 +1,81 @@ +import React, { useEffect, ReactElement, Fragment} from 'react'; +import create from "zustand" + + +type Store = { + store: {[key:string]: ReactElement}, + add:(key: string, el:ReactElement)=>void, + remove:(key: string)=>void +} + +/** + * A tunnel allows to render components of one renderer inside another. + * I.e. babylonjs components normally need to live within Engine component. + * A tunnel entrance allows to position components in a different renderer, such as ReactDOM + * and move it to the tunnel exit, that must exist within Engine component. + * + * The nice thing is, even refs can be used outside of Engine context. + * + * The createTunnel function creates a tunnel entrance and exit component. + * The tunnel works one-directional. + * TunnelEntrance only accepts components that are allowed to live within the renderer of TunnelExit. + * Multiple entrances and exits are possible. + * + * If components need to be rendererd the other way around, a second Tunnel is needed. + * + */ +const createTunnel = () => { + + const useStore = create((set, get)=> ({ + store: {}, + add: (key, el) => set((state)=>{ + return {...state, store: {...state.store, [key]: el}}}), + remove: (key) => set((state)=>{ + if(key in state.store){ + delete state.store[key] + } + return {...state, store: {...state.store}}}) + })) + + /** + * Tunnel Entrance + * @param uid a unique identifier - similar to key. if same uid exists in app, only one tunnel entrance will end in tunnel exit + * @returns nothing + */ + const TunnelEntrance = ({uid, children}: {uid: string,children: ReactElement}) => { + const add = useStore(state => state.add) + const remove = useStore(state => state.remove) + useEffect(()=>{ + add(uid, children); + return ()=> { + remove(uid) + } + },[children]) + + return <> + } + + /** + * Tunnel Exit + * @param uids optionally add uids of tunnel entrances to only show components of these entrances + * @returns Components of Tunnel Entrance + */ + const TunnelExit = ({uids}: {uids?: string[]}) => { + const state = useStore(state => state.store) + + + return <>{Object.keys(state) + .filter(key => uids ? uids.includes(key) : true) + .map((key) => { + return + {state[key]} + + }) + } + + } + + return {TunnelEntrance, TunnelExit}; +} + +export default createTunnel; \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/Integrations/chromaJS.stories.js b/packages/storybook-static/stories/babylonjs/Integrations/chromaJS.stories.js new file mode 100644 index 00000000..8b55b206 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Integrations/chromaJS.stories.js @@ -0,0 +1,140 @@ +import React from 'react' +import { Vector3, Color3 } from '@babylonjs/core'; +import { Control } from '@babylonjs/gui'; +import { Engine, Scene, PropChangeType, useCustomPropsHandler } from 'react-babylonjs' +import '../../style.css'; +import chroma, { Color } from 'chroma-js' + +export default { title: 'Integrations'}; + +class ChromajsColor3PropsHandler /* implements ICustomPropsHandler */ { + + get name() { return 'chroma-js:Color3'} + + get propChangeType() { + return PropChangeType.Color3; + } + + accept(newProp) { + return (typeof(newProp) === 'string' && chroma.valid(newProp)) || newProp instanceof Color; + } + + process(oldProp, newProp) { + let newColor; + // this doesn't work switching from 'string' <==> Color... + if (typeof(newProp) === 'string') { + if (oldProp === undefined || oldProp !== newProp) { + newColor = chroma(newProp).rgb(); + } + } else { + if (oldProp === undefined || (oldProp instanceof Color && oldProp.hex() !== newProp.hex)) { + newColor = newProp.rgb(); + } + } + + return { + processed: newColor !== undefined, + value: newColor === undefined + ? null + : Color3.FromInts(newColor[0], newColor[1], newColor[2]) + }; + } +} + +const SQUARES_PER_CIRCLE = 24; +const INNER_RADIUS = 1.5; + +/** + * Shortest distance (angular) between two angles. + * It will be in range [0, 180]. + */ +const distance = (alpha, beta) => { + const phi = Math.abs(beta - alpha) % 360; // This is either the distance or 360 - distance + const distance = phi > 180 ? 360 - phi : phi; + return distance; +} + +/** + * This is for optimizing animation when first mount application. + * But this story works well,Animation is smooth。 + */ +function WithCustomColors(props) { + useCustomPropsHandler(new ChromajsColor3PropsHandler()); + const degreeIncrements = (360 / SQUARES_PER_CIRCLE); + + return ( + <> + + + + { + props.colors.map(colorName => { + const color = chroma(colorName); + // color.luminance() < 0.25 + const contrastColor = color.get('lab.l') > 45 ? 'black' : 'white'; + // console.log('checking:', colorName, color.get('lab.l'), color.luminance()); + return ( + + + + ) + }) + } + + + + { + props.colors.map((colorName, colorIndex) => { + + const whiteColorScaleFn = chroma.scale([colorName, 'white']); + const blackColorScaleFn = chroma.scale([colorName, 'black']); + const radius = (colorIndex * 1.05) + INNER_RADIUS; + const size = 0.75 * Math.tan(degreeIncrements * Math.PI/180) * radius; + + return [...Array(SQUARES_PER_CIRCLE).keys()].map(positionIndex => { + + const degrees = positionIndex * degreeIncrements; + const topDistance = distance(degrees, 270); + const bottomDistance = distance(degrees, 90); + const useWhiteColor = topDistance <= 90;// degrees from top > 90° + + const color = useWhiteColor + ? whiteColorScaleFn(1 - (topDistance / 90)) + : blackColorScaleFn((90 - bottomDistance) / 90); + + const angleRads = degrees * Math.PI / 180; + const x = radius * Math.cos(angleRads); + const z = radius * Math.sin(angleRads); + return ( + + + + )}) + }) + } + + ) +} + +export const ChromaJSProps = () => +
+ + + + + + + +
+ +ChromaJSProps.story = { + name: 'chroma-js' +} + diff --git a/packages/storybook-static/stories/babylonjs/Integrations/gsap.stories.js b/packages/storybook-static/stories/babylonjs/Integrations/gsap.stories.js new file mode 100644 index 00000000..8f94204a --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Integrations/gsap.stories.js @@ -0,0 +1,82 @@ +import '@babylonjs/inspector'; +import React, { Component } from 'react'; +import { TimelineLite } from 'gsap/all'; +import { Engine, Scene, Skybox } from 'react-babylonjs'; +import { Vector3, Color3, Color4 } from '@babylonjs/core'; +import { StandardMaterial, FresnelParameters } from '@babylonjs/core/Materials'; +import { CubeTexture } from '@babylonjs/core/Materials/Textures'; +import ScaledModelWithProgress from '../ScaledModelWithProgress'; +import '../../style.css'; + +export default { title: 'Integrations' }; + +class WithGSAP extends Component { + constructor () { + super() + + this.state = { + atomYPos: 0, + atomScaling: 3.0, + skyboxIndex: 0 + } + + this.onModelLoaded = this.onModelLoaded.bind(this) + this.logoTween = new TimelineLite({ paused: true }) + } + + + onModelLoaded = (model) => { + model.meshes.map((mesh, index) => { + const scene = mesh._scene; + let material = new StandardMaterial("kosh", scene); + material.reflectionTexture = new CubeTexture("assets/textures/TropicalSunnyDay", scene); + material.diffuseColor = new Color3(0, 0, 0); + material.emissiveColor = new Color3(0.5, 0.5, 0.5); + material.alpha = 0.2; + material.specularPower = 16; + + // Fresnel + material.reflectionFresnelParameters = new FresnelParameters(); + material.reflectionFresnelParameters.bias = 0.1; + + material.emissiveFresnelParameters = new FresnelParameters(); + material.emissiveFresnelParameters.bias = 0.6; + material.emissiveFresnelParameters.power = 4; + material.emissiveFresnelParameters.leftColor = Color3.White(); + material.emissiveFresnelParameters.rightColor = Color3.Black(); + + material.opacityFresnelParameters = new FresnelParameters(); + material.opacityFresnelParameters.leftColor = Color3.White(); + material.opacityFresnelParameters.rightColor = Color3.Black(); + if(index === 0){ + this.logoTween.to(mesh.scaling, 2, { x: 4, y: 4, z: 4 }) + this.logoTween.to(mesh.scaling, 2, { x: 2, y: 2, z: 2 }) + this.logoTween.to(mesh.rotation, 1, { x: 1, y: 1, z: 1 }) + this.logoTween.play(); + } + mesh.material = material; + }) + } + + render () { + return ( + + + + + + + + + ) + } +} + +export const GSAPTimeline = () => ( +
+ +
+) \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/VaporWave.js b/packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/VaporWave.js new file mode 100644 index 00000000..4864766f --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/VaporWave.js @@ -0,0 +1,47 @@ + +import React, { useEffect } from 'react'; +import { Vector2, Mesh } from '@babylonjs/core'; +import { useScene } from 'react-babylonjs'; +import './shaders'; +let customProceduralTexture = null; +let time = 0; + +const onCustomProceduralTextureCreated = (cpt) => { + customProceduralTexture = cpt; // assigning to reflection/refraction of mirrorball +} + +const VaporWave = (props) => { + const scene = useScene(); + useEffect(() => { + const observable = scene.onBeforeRenderObservable.add((scene) => { + if (scene !== null && customProceduralTexture !== null) { + time += scene.getEngine().getDeltaTime(); + customProceduralTexture.setFloat("time", time); + } + }) + return () => { + scene.onBeforeRenderObservable.remove(observable); + } + }) + + return (<> + + + + + + ) +} + +export default VaporWave \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/block.js b/packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/block.js new file mode 100644 index 00000000..7a1547b3 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/block.js @@ -0,0 +1,64 @@ +import React, { createContext, useRef, useContext } from "react" +import { useBeforeRender } from 'react-babylonjs' +import { Vector3, } from '@babylonjs/core'; +import lerp from "lerp" +import state from "./store" + +const offsetContext = createContext(0) + +function Block({ children, offset, factor, ...props }) { + const { offset: parentOffset, sectionHeight } = useBlock() + offset = offset !== undefined ? offset : parentOffset + const ref = useRef() + useBeforeRender((scene) => { + if(ref.current && ref.current.position){ + const curY = ref.current.position.y; + const curTop = state.top.current; + ref.current.position.y = lerp(curY, (curTop / state.zoom) * factor, 0.1); + } + }); + + return ( + + + {children} + + + ) +} + +function useBlock() { + const { sections, pages, zoom } = state + const viewPortSize = { + width: window.innerWidth, + height: window.innerHeight, + } + const size = viewPortSize; + const viewport = viewPortSize; + const offset = useContext(offsetContext) + const viewportWidth = viewport.width + const viewportHeight = viewport.height + const canvasWidth = viewportWidth / zoom + const canvasHeight = viewportHeight / zoom + const mobile = size.width < 700 + const margin = canvasWidth * (mobile ? 0.2 : 0.1) + const contentMaxWidth = canvasWidth * (mobile ? 0.8 : 0.6) + const sectionHeight = canvasHeight * ((pages - 1) / (sections - 1)) + const offsetFactor = (offset + 1.0) / sections + + return { + viewport, + offset, + viewportWidth, + viewportHeight, + canvasWidth, + canvasHeight, + mobile, + margin, + contentMaxWidth, + sectionHeight, + offsetFactor + } +} + +export { Block, useBlock } \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/pixi-styles.js b/packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/pixi-styles.js new file mode 100644 index 00000000..fc2289a4 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/pixi-styles.js @@ -0,0 +1,31 @@ +export const retroGoldGradient = { + fontFamily: "Press Start 2P", + fontSize: 36, + fontWeight: "bold", + fill: ["#fcb69f", "#f6d365"], // gradient + stroke: "#e6e9f0", + strokeThickness: 3, + dropShadow: true, + dropShadowColor: "#000000", + dropShadowBlur: 4, + dropShadowAngle: Math.PI / 6, + dropShadowDistance: 6, + wordWrap: true, + wordWrapWidth: 440 + } + + export const postSpectacularGradient = { + fontFamily: "Orbitron", + fontSize: 50, + fontWeight: "bold", + fill: ["#6a11cb", "#2575fc"], // gradient + stroke: "#4facfe", + strokeThickness: 2, + dropShadow: true, + dropShadowColor: "#000000", + dropShadowBlur: 4, + dropShadowAngle: Math.PI / 6, + dropShadowDistance: 6, + wordWrap: false, + wordWrapWidth: 440 + } \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/shaders/index.js b/packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/shaders/index.js new file mode 100644 index 00000000..0edba930 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/shaders/index.js @@ -0,0 +1,306 @@ +import {Effect} from "@babylonjs/core"; +// register shader toy fragment example +Effect.ShadersStore.vaporWavePixelShader = ` +uniform float time; + uniform vec2 mousePos; + uniform vec2 resolution; + varying vec2 vUV; + #define PI 3.1415926535 + #define STEPS 50 + mat2 rot( in float a ) { + float c = cos(a); + float s = sin(a); + return mat2(c,s,-s,c); + } + // noise function + float noise( in vec2 p ) { + p *= rot(1.941611); + return sin(p.x) * .25 + sin(p.y) * .25 + .50; + } + // get the 2 closest point with the projected height as z + void grid( in vec2 p, inout vec3 projClosest, inout vec3 projSecondClosest ) { + vec2 center = floor(p) + 0.5; + vec2 secondBestCenter = center; + float secondBestDist = 99999.9; + vec2 bestCenter = center; + float bestDist = 99999.9; + for (int y = -1 ; y <= 1 ; y++) + for (int x = -1 ; x <= 1 ; x++) { + vec2 currentCenter = center + vec2(x, y); + // vary each center a bit + currentCenter.x += noise( + time * vec2(0.5124, 0.5894) + + currentCenter * vec2(1.3124, 1.7894)) * 1.0 - 0.5; + currentCenter.y += noise( + time * vec2(0.5565, 0.5561) - + currentCenter * vec2(1.5124, 1.6053)) * 1.0 - 0.5; + vec2 delta = p - currentCenter; + float currentDist = dot(delta, delta)*0.5; + // use an analytical if to avoid the branch + float if1 = step(currentDist, bestDist); + float if1m = 1.0 - if1; + secondBestCenter = if1*bestCenter + if1m*secondBestCenter; + secondBestDist = if1*bestDist + if1m*secondBestDist; + bestCenter = if1*currentCenter + if1m*bestCenter; + bestDist = if1*currentDist + if1m*bestDist; + // else if + float if2 = step(currentDist, secondBestDist)*if1m; + float if2m = 1.0 - if2; + secondBestCenter = if2*currentCenter + if2m*secondBestCenter; + secondBestDist = if2*currentDist + if2m*secondBestDist; + } + projClosest = vec3(bestCenter, bestDist); + projSecondClosest = vec3(secondBestCenter, secondBestDist); + } + // normal function + vec3 normal( in vec3 p, in vec3 proj ) { + vec2 dir = proj.xy - p.xy; + vec3 tang = vec3(dir, proj.z*0.12); + vec3 nine = vec3(dir, 0).yxz; + nine.x = -nine.x; + return normalize(cross(nine, tang)); + } + // distance function + float de( in vec3 p, inout vec3 projClosest, inout vec3 projSecondClosest ) { + // get the closest points + grid(p.xy, projClosest, projSecondClosest); + float below = 0.0; + below -= sin(dot(p.xy, vec2(0.005, 0.051)) * 4.0 + time * 0.5) * 0.4 + 0.2; + below -= 1.0 - projClosest.z; + return max(0.0, p.z - below); + } + // return the sun color at this direction + vec4 getSunColor( in vec3 dir, inout float inside ) { + float dotp = dot(dir, vec3(-0.99, 0.0, 0.1)); + float sunHeight = smoothstep(0.01, 0.29, dir.z); + inside = smoothstep(0.977, 0.979, dotp); + float ytemp = abs(dir.y)*dir.y; + float sunWave = sin(dir.z*300.0+time*1.846+ + sin(ytemp*190.0+time*0.45)*1.3)*0.5+0.5; + float sunHeight2 = smoothstep(-0.1, 0.2, dir.z); + sunWave = sunWave * sunHeight2 + 1.0 - sunHeight2; + sunWave = (1.0-smoothstep(sunHeight2, 1.0, sunWave)) * (1.0 - sunHeight2) + sunHeight2; + float sun = inside * sunWave; + return vec4(mix(vec3(0.998, 0.108, 0.47), vec3(0.988, 0.769, 0.176), sunHeight), sun); + } + // get the space color + vec3 getSpaceColor( in vec3 dir ) { + float scanline = sin(dir.z * 700.0 - time * 5.1)*0.5+0.5; + scanline *= scanline; + vec3 color = mix(vec3(0.1, 0.16, 0.26), vec3(0.1), scanline); + vec2 uv = vec2(atan(dir.y, dir.x) / (2.0 * PI) + 0.5, mod(dir.z, 1.0)); + uv.x = mod(uv.x+2.0*PI, 1.0); + uv.x *= 100.0; + uv.y *= 15.00; + uv *= rot(1.941611+time*0.00155); + vec2 center = floor(uv) + 0.5; + center.x += noise(center*48.6613) * 0.8 - 0.4; + center.y += noise(center*-31.1577) * 0.8 - 0.4; + float radius = smoothstep(0.6, 1.0, noise(center*42.487+ + vec2(0.1514, 0.1355)*time)); + radius *= 0.01; + vec2 delta = uv-center; + float dist = dot(delta, delta); + float frac = 1.0-smoothstep(0.0, radius, dist); + float frac2 = frac; + frac2 *= frac2; frac2 *= frac2; frac2 *= frac2; + vec3 lightColor = mix(vec3(0.988, 0.769, 0.176), + vec3(0.988, 0.434, 0.875), noise(center*74.487)); + return mix(color, lightColor, frac) + vec3(1)*frac2; + } + // get the background color (ala cubemap) + vec3 getBackgroundColor( in vec3 dir ) { + float horizon = 1.0 - smoothstep(0.0, 0.02, dir.z); + // this is the background with the scanline + vec3 color = getSpaceColor(dir); + // get the sun + float inside = 0.0; + vec4 sun = getSunColor(dir, inside); + color = mix(color, vec3(0.1, 0.16, 0.26), inside); + color = mix(color, sun.rgb, sun.a); + // the horizon + color = mix(color, vec3(0.43, 0.77, 0.85), horizon * (1.0 - sun.a * 0.19)); + return color; + } + // the color gets more blue/white near edges of the voronoi cells + vec3 getWaveColor( in vec3 p, in vec3 projClosest, in vec3 projSecondClosest, + in vec3 dir, float dist, vec2 frag ) { + float distanceToEdge = abs(projClosest.z-projSecondClosest.z); + float distanceFrac = smoothstep(-10.0, 100.0, dist); + distanceFrac *= distanceFrac; distanceFrac *= distanceFrac; + float frac = smoothstep(0.0, 0.1+distanceFrac*0.9, distanceToEdge); + // get the reflection + vec3 norm = normal(p, projClosest); + vec3 color = getBackgroundColor(reflect(dir, norm)); + // add a screenspace scanline + frac *= (sin(frag.y/resolution.y*700.0)*0.5+0.5)*(1.0-distanceFrac); + return mix(vec3(0.43, 0.77, 0.85), color, frac); + } + void main( void ) { + vec2 uv = vUV.xy / resolution.xy * 2.0 - 1.0; + uv.y *= resolution.y / resolution.x; + vec3 from = vec3(0, 0, 0.2); + vec3 dir = normalize(vec3(uv.x*0.6, 1.0, uv.y*-0.6)); + dir.xy *= rot(PI*.5); + vec2 mouse=(mousePos.xy / resolution.xy - 0.5) * 0.5; + mouse *= step(1.0, mousePos.x); + dir.xz *= rot(3.16-(-mouse.y*1.5)+sin(time*0.785)*0.008); + dir.xy *= rot(-mouse.x*4.0+sin(time*0.416)*0.01); + dir.yz *= rot(sin(time*0.287)*0.009); + vec3 color = vec3(0); + if (dir.z > 0.0) { + color = getBackgroundColor(dir); + } else { + // project the starting position to z = 0 so we ccan lower the raymarch count + float totdist = from.z / -dir.z; + for (int steps = 0 ; steps < STEPS ; steps++) { + vec3 p = from + totdist * dir; + vec3 projClosest; + vec3 projSecondClosest; + p.x -= time * 2.7; + float dist = de(p, projClosest, projSecondClosest); + totdist += dist; + if ( dist < 0.01 || steps == STEPS-1 ) { + color = getWaveColor(p, projClosest, projSecondClosest, + dir, totdist, vUV); + break; + } + } + } + gl_FragColor = vec4(color, 1); + } +`; + +Effect.ShadersStore.seaCloudsPixelShader = ` +uniform float time; +uniform vec2 mousePos; +uniform vec2 resolution; +varying vec2 vUV; + + float hash( float n ) { + return fract(sin(n)*43758.5453); + } + + float noise( in vec3 x ) { + vec3 p = floor(x); + vec3 f = fract(x); + f = f*f*(3.0-2.0*f); + float n = p.x + p.y*57.0 + 113.0*p.z; + return mix(mix(mix( hash(n+ 0.0), hash(n+ 1.0),f.x), + mix( hash(n+ 57.0), hash(n+ 58.0),f.x),f.y), + mix(mix( hash(n+113.0), hash(n+114.0),f.x), + mix( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z); + } + + vec4 map( in vec3 p ) { + float d = 0.2 - p.y; + vec3 q = p - vec3(1.0,0.1,0.0)*time; + float f; + f = 0.5000*noise( q ); q = q*2.02; + f += 0.2500*noise( q ); q = q*2.03; + f += 0.1250*noise( q ); q = q*2.01; + f += 0.0625*noise( q ); + d += 3.0 * f; + d = clamp( d, 0.0, 1.0 ); + vec4 res = vec4( d ); + res.xyz = mix( 1.15*vec3(1.0,0.95,0.8), vec3(0.7,0.7,0.7), res.x ); + return res; + } + + vec3 sundir = vec3(-1.0,0.0,0.0); + + vec4 raymarch( in vec3 ro, in vec3 rd ) { + vec4 sum = vec4(0, 0, 0, 0); + float t = 0.0; + for(int i=0; i<64; i++) { + if( sum.a > 0.99 ) continue; + + vec3 pos = ro + t*rd; + vec4 col = map( pos ); + + #if 1 + float dif = clamp((col.w - map(pos+0.3*sundir).w)/0.6, 0.0, 1.0 ); + vec3 lin = vec3(0.65,0.68,0.7)*1.35 + 0.45*vec3(0.7, 0.5, 0.3)*dif; + col.xyz *= lin; + #endif + + col.a *= 0.35; + col.rgb *= col.a; + sum = sum + col*(1.0 - sum.a); + + #if 0 + t += 0.1; + #else + t += max(0.1,0.025*t); + #endif + } + + sum.xyz /= (0.001+sum.w); + return clamp( sum, 0.0, 1.0 ); + } + + void main(void) { + vec2 q = gl_FragCoord.xy / resolution.xy; + vec2 p = -1.0 + 2.0*q; + p.x *= resolution.x/ resolution.y; + vec2 mo = -1.0 + 2.0*mousePos.xy / resolution.xy; + + // camera + vec3 ro = 2.0*normalize(vec3(cos(2.75-3.0*mo.x), 0.7+(mo.y+1.0), sin(2.75-3.0*mo.x))); + vec3 ta = vec3(0.0, 1.0, 0.0); + vec3 ww = normalize( ta - ro); + vec3 uu = normalize(cross( vec3(0.0,1.0,0.0), ww )); + vec3 vv = normalize(cross(ww,uu)); + vec3 rd = normalize( p.x*uu + p.y*vv + 1.5*ww ); + + + vec4 res = raymarch( ro, rd ); + + float sun = clamp( dot(sundir,rd), 0.0, 1.0 ); + vec3 col = vec3(0.6,0.71,0.75) - rd.y*0.2*vec3(1.0,0.5,1.0) + 0.15*0.5; + col += 0.2*vec3(1.0,.6,0.1)*pow( sun, 8.0 ); + col *= 0.95; + col = mix( col, res.xyz, res.w ); + col += 0.1*vec3(1.0,0.4,0.2)*pow( sun, 3.0 ); + + gl_FragColor = vec4( col, 1.0 ); + } +`; + + +Effect.ShadersStore.shaderShiftRGBVertexShader = ` +attribute vec3 position; +attribute vec3 normal; +attribute vec2 uv; +uniform mat4 worldViewProjection; +uniform mat4 projection; +uniform float scale; +uniform float shift; +varying vec2 vUV; + +void main() { +vec3 pos = position; +pos.y = pos.y + ((sin(uv.x * 3.1415926535897932384626433832795) * shift * 5.0) * 0.125); +vUV = uv; +gl_Position = worldViewProjection * vec4(pos,1.); +}`; + +Effect.ShadersStore.shaderShiftRGBPixelShader = ` + uniform sampler2D textureSampler; + uniform float hasTexture; + uniform float shift; + uniform float scale; + uniform float opacity; + uniform vec3 color; + varying vec2 vUV; + void main() { + float angle = 1.55; + vec2 p = (vUV - vec2(0.5, 0.5)) * (1.0 - scale) + vec2(0.5, 0.5); + vec2 offset = shift / 4.0 * vec2(cos(angle), sin(angle)); + vec4 cr = texture2D(textureSampler, p + offset); + vec4 cga = texture2D(textureSampler, p); + vec4 cb = texture2D(textureSampler, p - offset); + if (hasTexture == 1.0) gl_FragColor = vec4(cr.r, cga.g, cb.b, cga.a); + else gl_FragColor = vec4(color, opacity); + } +`; diff --git a/packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/slide.js b/packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/slide.js new file mode 100644 index 00000000..f3758bb8 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/slide.js @@ -0,0 +1,126 @@ +import React, { useEffect, useRef } from "react" +import { Effect, Vector3, Mesh, Texture, Color3, ShaderMaterial } from '@babylonjs/core'; +import { Control } from '@babylonjs/gui' +import { useScene } from 'react-babylonjs' +import './shaders'; +import lerp from "lerp" +import { Block, useBlock } from "./block" +import state from "./store" +import VaporWave from './VaporWave' +let time = 0; + + +function CustomPlaneBlock(props){ + const {keyText, index, scaling, image} = props; + const { contentMaxWidth: w, viewportHeight, offsetFactor } = useBlock() + const scene = useScene(); + const planeRef = useRef(undefined) + let last = state.top.current; + useEffect(() => { + const observable = scene.onBeforeRenderObservable.add((scene) => { + if (scene !== null && planeRef !== null) { + time += scene.getEngine().getDeltaTime(); + const shMat = planeRef.current.material + shMat.setFloat("time", time); + const { pages, top } = state; + shMat.setFloat("scale", lerp(shMat._floats.scale, offsetFactor - top.current / ((pages - 1) * viewportHeight), 0.1)); + shMat.setFloat("shift", lerp(shMat._floats.shift, (top.current - last) / 150, 0.1)); + last = top.current + } + }) + return () => { + scene.onBeforeRenderObservable.remove(observable); + } + }) + + const onCustomProceduralTextureCreated = (e) => { + const options = { + attributes: ['position', 'normal', 'uv'], + samplers: ['textureSampler'], + uniforms: ['world', 'worldView', 'worldViewProjection', 'view', 'projection', 'scale', 'shift', 'color', 'opacity', 'hasTexture'] + } + const shMat = new ShaderMaterial(`shaderRGB`, scene, {vertexSource: Effect.ShadersStore.shaderShiftRGBVertexShader, fragmentSource: Effect.ShadersStore.shaderShiftRGBPixelShader }, options) + const _img = new Texture(image, scene); + _img.wrapU = Texture.CLAMP_ADDRESSMODE + _img.wrapV = Texture.CLAMP_ADDRESSMODE + shMat.backFaceCulling = false; + shMat.checkReadyOnEveryCall = true; + shMat.setTexture("textureSampler", _img); + shMat.setFloat("hasTexture", 1); + shMat.setFloat("scale", 0); + shMat.setFloat("shift", 0); + shMat.setFloat("opacity", 1); + shMat.setVector3("color", new Color3(0,0,0)); + e.material = shMat; + } + + return( + onCustomProceduralTextureCreated(e)}/> + ) +} + +function Paragraph({ image, index, offset, factor, header, aspect, text }) { + const keyText = text ? text.split(' ').join('') : Math.random() + '--rando'; + const { contentMaxWidth: w, mobile } = useBlock() + const size = aspect < 1 && !mobile ? 0.65 : 1 + const left = !(index % 2) + return ( + + + + + + + + + + + + + + + + ) +} + +function Content(mainProps) { + + return ( + <> + + + + {state.paragraphs.map((props, index) => { + return ( + + ) + })} + {state.stripes.map(({ offset, color, height, width }, index) => ( + + + + + + ))} + + ) +} + +function Slide(props) { + return +} + +export default Slide \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/store.js b/packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/store.js new file mode 100644 index 00000000..d0a5bfa7 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/store.js @@ -0,0 +1,78 @@ +import { createRef } from "react" +import { Vector3 } from "@babylonjs/core/Maths/math.vector"; +const state = { + sections: 9, + pages: 8, + zoom: 75, + paragraphs: [ + { + offset: 1, + factor: 1.05, + header: "District 4", + image: "/assets/images/photo-1515036551567-bf1198cccc35.jpeg", + aspect: 1.51, + text: "Two thousand pharmacologists and bio-chemists were subsidized. Six years later it was being produced commercially." + }, + { + offset: 2, + factor: 1.05, + header: "Diamond Road", + image: "/assets/images/photo-1519608487953-e999c86e7455.jpeg", + aspect: 1.5, + text: + "The man who comes back through the Door in the Wall will never be quite the same as the man who went out. He will be wiser but less sure, happier but less self-satisfied, humbler in acknowledging his ignorance yet better equipped to understand the relationship of words to things, of systematic reasoning to the unfathomable mystery which it tries, forever vainly, to comprehend." + }, + { + offset: 3, + factor: 1.05, + header: "Catalina", + image: "/assets/images/ph1.jpg", + aspect: 1.5037, + text: + "The substance can take you to heaven but it can also take you to hell. Or else to both, together or alternately. Or else (if you're lucky, or if you've made yourself ready) beyond either of them. And then beyond the beyond, back to where you started from — back to here, back to New Rotham sted, back to business as usual. Only now, of course, business as usual is completely different." + }, + { + offset: 4, + factor: 1.05, + header: "Building 21", + image: "/assets/images/ph3.jpg", + aspect: 0.665, + text: + "We’ve found that the people whose EEG doesn’t show any alpha-wave activity when they’re relaxed aren’t likely to respond significantly to the substance. That means that, for about fifteen percent of the population, we have to find other approaches to liberation." + }, + { + offset: 5, + factor: 1.05, + header: "Sector 8", + image: "/assets/images/photo-1533577116850-9cc66cad8a9b.jpeg", + aspect: 1.77, + text: + "By cultivating the state of mind that makes it possible for the dazzling ecstatic insights to become permanent and habitual illuminations. By getting to know oneself to the point where one won’t be compelled by one’s unconscious to do all the ugly, absurd, self-stultifying things that one so often finds oneself doing." + }, + { + offset: 7, + factor: 1.05, + header: "The Factory", + image: "/assets/images/photo-1548191265-cc70d3d45ba1.jpeg", + aspect: 1.77, + text: "Education and enlightenment." } + ], + stripes: [ + { offset: 2, color: "#E92efb", height: 700, width:17 }, + { offset: 6.3, color: "#Ff2079", height: 700, width:17 }, + { offset: 8.3, color: "#440BD4", height: 700, width:17 }, + ], + diamonds: [ + { x: 0, offset: 0.15, pos: new Vector3(), scale: 0.6, factor: 1.8 }, + { x: 2, offset: 1.1, pos: new Vector3(), scale: 0.8, factor: 2.1 }, + { x: -5, offset: 2, pos: new Vector3(), scale: 0.8, factor: 2.5 }, + { x: 0, offset: 3.2, pos: new Vector3(), scale: 0.8, factor: 1.75 }, + { x: 0, offset: 4, pos: new Vector3(), scale: 0.8, factor: 2.5 }, + { x: 2, offset: 5.5, pos: new Vector3(), scale: 1.25, factor: 0.85 }, + { x: -5, offset: 7, pos: new Vector3(), scale: 0.8, factor: 2 }, + { x: 0, offset: 8, pos: new Vector3(), scale: 1.5, factor: 6 } + ], + top: createRef() +} + +export default state \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/styles.css b/packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/styles.css new file mode 100644 index 00000000..4d66d755 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Integrations/pixi-demo/styles.css @@ -0,0 +1,29 @@ +.scrollArea { + position: absolute; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + overflow: auto; + } + +.slideContainer{ + + position: absolute; + z-index: 1; + display: flex; + bottom: 10px; + right: 10px; + color: #c6f200; + justify-content: center; + align-items: center; +} + +.btn{ + padding: 10px; + cursor: pointer; + margin: 10px; + background-color: #2d00f7; + border: solid 1px #f20089; + +} \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/Integrations/pixi-render.stories.js b/packages/storybook-static/stories/babylonjs/Integrations/pixi-render.stories.js new file mode 100644 index 00000000..86479cf0 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Integrations/pixi-render.stories.js @@ -0,0 +1,142 @@ + +import React, { useRef, useCallback, useState, useEffect } from 'react'; +import * as PIXI from 'pixi.js'; +import { Vector3, Color3 } from '@babylonjs/core'; +import { render as PixiRender, Text } from '@inlet/react-pixi' +import { Engine, Scene, useScene } from 'react-babylonjs'; +import '@babylonjs/inspector' +import {postSpectacularGradient} from './pixi-demo/pixi-styles'; +import './pixi-demo/shaders'; // side-effect of registering a pixel shader +import Slider from './pixi-demo/slide' +import state from "./pixi-demo/store" +import './pixi-demo/styles.css' +export default { title: 'Integrations' }; + +let customProceduralTexture = null; +let time = 0; + +function ScenePIXI(props) { + const beforeMount = useRef(false); + const pixiRefs = useRef(undefined); + const scene = useScene(); + scene.clearColor = Color3.FromHexString('#04005E'); + if (beforeMount.current === false) { + beforeMount.current = true; + const engine = scene.getEngine(); + scene.debugLayer.show(); + const options = { + autoStart: false, + clearBeforeRender: false, + context: engine._gl, // ._gl is public **hidden** + height: engine.getRenderHeight(), + // roundPixels: true, available PIXI < 5.0 + view: engine.getRenderingCanvas(), + width: engine.getRenderWidth() + } + + pixiRefs.current = { + renderer: new PIXI.Renderer(options), // use PIXI.WebGLRender <= PIXI v5.0 + stage: new PIXI.Container() + } + } + + useEffect(() => { + // NOTE: to render PIXI in the background (BabylonJS in foreground) do 2 things differently: + // 1. use onBeforeRenderLoopObservable() + // 2. scene.autoClear = false; + const observer = props.onEndRenderLoopObservable.add(engine => { + engine.wipeCaches(true); + const { renderer } = pixiRefs.current; + renderer.reset(); + renderer.render(pixiRefs.current.stage); + renderer.reset(); // need to reset again :) + }) + + return () => { + props.onEndRenderLoopObservable.remove(observer); + } + }) + + useEffect(() => { + const observable = scene.onBeforeRenderObservable.add((scene) => { + if (scene !== null && customProceduralTexture !== null) { + time += scene.getEngine().getDeltaTime(); + // 'time' is a uniform on the shader + customProceduralTexture.setFloat("time", time); + } + }) + + return () => { + scene.onBeforeRenderObservable.remove(observable); + } + }) + + // not "rendering" using a different reconciler! + PixiRender( + <> + {props.children} + + , + pixiRefs.current.stage + ); + + return null; +} + +const SceneBabylonJSSlider = (props) => <> + + + + + +const postText = "P05T 5P3CTACU1AR DEMOSCENE"; +let engine = undefined; + +const scrollToArea = (spot) => { + document.querySelector('.scrollArea').scrollTo({ + top: spot === 0 ? 0:spot * window.innerHeight, + left: 0, + behavior: 'smooth' + }) +} + +export const PIXIStory = ({ top, mouse }) => { + const [found, setFound] = useState(false); + const engineRef = useCallback(component => { + engine = component; + setFound(true); + }, []); + + const scrollArea = useRef() + const onScroll = e => { + return e.target && e.target.scrollTop ? state.top.current = e.target.scrollTop:false; + } + useEffect(() => void onScroll({ target: scrollArea.current }), []) + return ( +
+ + + + + + + + +
+ Slides: +
scrollToArea(0)}>1
+
scrollToArea(1.5)}>2
+
scrollToArea(2.2)}>3
+
scrollToArea(3.2)}>4
+
scrollToArea(4)}>5
+
+
+
+
+
+ ) +} + +PIXIStory.story = { + name: 'PixiJS v5' +} \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/Integrations/reactSpring.stories.js b/packages/storybook-static/stories/babylonjs/Integrations/reactSpring.stories.js new file mode 100644 index 00000000..cd2d7d5f --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Integrations/reactSpring.stories.js @@ -0,0 +1,273 @@ +import React from 'react' +import { + Engine, + Scene, + useHover, + CustomPropsHandler, + PropChangeType, +} from 'react-babylonjs' +import { Vector3, Color3 } from '@babylonjs/core/Maths/math'; +import { useSprings, useSpring, animated } from 'react-babylon-spring'; +import 'react-babylon-spring'; +import '../../style.css' + +export default {title: 'Integrations'}; + +/** + * Only need these Handlers or otherwise react-babylon-spring can export them. + * Copied from /src/customProps in that repo. + * The global resolution that used to work likely broke when not re-using the same Fiber host was fixed in issue #100 (new renderer creation). + */ +function parseRgbaString(rgba) { + const arr = rgba.replace(/[^\d,]/g, '').split(','); + return arr.map(num => parseInt(num, 10) / 255); +} + +const Key = 'react-babylon-spring'; + +class CustomColor3StringHandler { + get name() { + return `${Key}:Color3String` + } + + get propChangeType() { + return PropChangeType.Color3; + } + + accept(newProp) { + // console.log('accept Color3String?', newProp); + return typeof (newProp) === 'string'; + } + + process(oldProp, newProp) { + if (oldProp !== newProp) { + return { + processed: true, + value: Color3.FromArray(parseRgbaString(newProp)) + }; + } + + return {processed: false, value: null}; + } +} + +class CustomColor3ArrayHandler { + get name() { + return `${Key}:Color3Array` + } + + get propChangeType() { + return PropChangeType.Color3; + } + + accept(newProp) { + // console.log('accept Color3Array?:', Array.isArray(newProp), newProp); + return Array.isArray(newProp); + } + + process(oldProp, newProp) { + if (oldProp === undefined || oldProp.length !== newProp.length) { + console.log(`found diff length (${oldProp?.length}/${newProp?.length}) Color3Array new? ${oldProp === undefined}`) + return { + processed: true, + value: Color3.FromArray(newProp) + }; + } + + for (let i = 0; i < oldProp.length; i++) { + if (oldProp[i] !== newProp[i]) { + console.log('found diff value Color3Array', oldProp, newProp); + return { + processed: true, + value: Color3.FromArray(newProp) + }; + } + } + + // console.log('Color3Array not processed', oldProp, newProp); + return {processed: false, value: null}; + } +} + +class CustomColor4StringHandler { + + get name() { + return `${Key}:Color4String` + } + + get propChangeType() { + return PropChangeType.Color4; + } + + accept(newProp) { + return typeof (newProp) === 'string'; + } + + process(oldProp, newProp) { + if (oldProp !== newProp) { + // console.log('found diff Color4String') + return { + processed: true, + value: Color4.FromArray(parseRgbaString(newProp)) + }; + } + + return {processed: false, value: null}; + } +} + +class CustomVector3ArrayHandler { + get name() { + return `${Key}:Vector3Array` + } + + get propChangeType() { + return PropChangeType.Vector3; + } + + accept(newProp) { + // console.log('Vector3: newProp:', newProp, Array.isArray(newProp)); + return Array.isArray(newProp); + } + + process(oldProp, newProp) { + if (oldProp === undefined || oldProp.length !== newProp.length) { + // console.log(`found diff length (${oldProp?.length}/${newProp?.length}) Color3Array new? ${oldProp === undefined}`) + return { + processed: true, + value: Vector3.FromArray(newProp) + }; + } + + for (let i = 0; i < oldProp.length; i++) { + if (oldProp[i] !== newProp[i]) { + // console.log('found difference...', oldProp, newProp); + return { + processed: true, + value: Vector3.FromArray(newProp) + }; + } + } + + // console.log('not processed...'); + return {processed: false, value: null}; + } +} +/** + * This is the end of code that needed to be copied, since it is not exported. + */ + +// we need to keep registering these as our fiber instance is being recreated when reloaded - the registrations imported as side-effects are +const registerPropsHandlers = () => { + CustomPropsHandler.RegisterPropsHandler(new CustomColor3StringHandler()); + CustomPropsHandler.RegisterPropsHandler(new CustomColor3ArrayHandler()); + CustomPropsHandler.RegisterPropsHandler(new CustomColor4StringHandler()); + CustomPropsHandler.RegisterPropsHandler(new CustomVector3ArrayHandler()); +} + +const getRandomColor = (function () { + // const Colors = ['#4F86EC', '#D9503F', '#F2BD42', '#58A55C']; + const Colors = [[0.31, 0.53, 0.93, 1], [0.85, 0.31, 0.25, 1], [0.95, 0.74, 0.26, 1], [0.35, 0.65, 0.36, 1]]; + + let i = 0; + return () => { + i++; + return Colors[i % Colors.length]; + } +})(); + +function getCyclePosition(i, blankRadius) { + i += blankRadius; + let angle = i % Math.PI * 2; + const x = i * Math.cos(angle); + const z = i * Math.sin(angle); + + return [x, z]; +} + +const WithSpring = () => { + // this only needs to be done once, so not on every render. + registerPropsHandlers(); + + const [props, set] = useSprings(100, i => { + const [x, z] = getCyclePosition(i, 30); + + return { + position: [x, 20, z], + color: getRandomColor(), + from: { + position: [x, Math.random() * 50 - 60, z], + }, + config: { + duration: 3000, + } + } + }); + + const [ref, isHovering] = useHover(_ => { + set((index, ctrl) => { + return { + color: getRandomColor(), + position: [0, 20, 0], + config: { + duration: 2000, + } + } + }); + }, _ => { + set(i => { + const [x, z] = getCyclePosition(i, 30); + return { + position: [x, 20, z], + config: { + duration: 2000, + } + } + }); + }); + + const groupProps = useSpring({ + rotation: isHovering ? [0, Math.PI * 2, 0] : [0, 0, 0], + config: { + duration: 2000 + } + }); + + return ( + <> + + + + + { + props.map(({position, color}, i) => + + + + ) + } + + + + + + + + + + ) +} + +export const ReactSpring = () => ( +
+ + + + + +
+); + +ReactSpring.story = { + name: 'react-spring' +} diff --git a/packages/storybook-static/stories/babylonjs/Integrations/tunnel.stories.js b/packages/storybook-static/stories/babylonjs/Integrations/tunnel.stories.js new file mode 100644 index 00000000..9f328b83 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Integrations/tunnel.stories.js @@ -0,0 +1,151 @@ +import React, { useEffect, useRef, useState, Fragment } from 'react'; +import create from "zustand"; +import { Engine, Scene, useBeforeRender } from 'react-babylonjs'; +import { Vector3 } from '@babylonjs/core/Maths/math.vector'; +import { Color3 } from '@babylonjs/core/Maths/math.color'; + +import '../../style.css'; + +export default { title: 'Integrations' }; + +/** + * This is a javascript port of ./Tunnel.tsx + */ +const createTunnel = () => { + + const useStore = create((set, get) => ({ + store: {}, + add: (key, el) => set((state) => { + return { ...state, store: { ...state.store, [key]: el } } + }), + remove: (key) => set((state) => { + if (key in state.store) { + delete state.store[key] + } + return { ...state, store: { ...state.store } } + }) + })) + + /** + * Tunnel Entrance + * @param uid a unique identifier - similar to key. if same uid exists in app, only one tunnel entrance will end in tunnel exit + * @returns nothing + */ + const TunnelEntrance = ({ uid, children }) => { + const add = useStore(state => state.add) + const remove = useStore(state => state.remove) + useEffect(() => { + add(uid, children); + return () => { + remove(uid) + } + }, [children]) + + return <> + } + + /** + * Tunnel Exit + * @param uids optionally add uids of tunnel entrances to only show components of these entrances + * @returns Components of Tunnel Entrance + */ + const TunnelExit = ({ uids }) => { + const state = useStore(state => state.store) + + return <>{Object.keys(state) + .filter(key => uids ? uids.includes(key) : true) + .map((key) => { + return + {state[key]} + + }) + } + + } + + return { TunnelEntrance, TunnelExit }; +} + +/** + * A tunnel allows to render components of one renderer inside another. + * I.e. babylonjs components normally need to live within Engine component. + * A tunnel entrance allows to position components in a different renderer, such as ReactDOM + * and move it to the tunnel exit, that must exist within Engine component. + * + * The nice thing is, even refs can be used outside of Engine context. + * + * The createTunnel function creates a tunnel entrance and exit component. + * The tunnel works one-directional. + * TunnelEntrance only accepts components that are allowed to live within the renderer of TunnelExit. + * Multiple entrances and exits are possible. + * + * If components need to be rendererd the other way around, a second Tunnel is needed. + * + */ +const { TunnelEntrance, TunnelExit } = createTunnel(); + +const rpm = 5; + +const WithTunnel = ({ uids }) => { + const [_, setReady] = useState(false); + const ref = useRef(null); + useBeforeRender((scene) => { + + if (ref.current !== null) { + const deltaTimeInMillis = scene.getEngine().getDeltaTime(); + ref.current.rotation.y += ((rpm / 60) * Math.PI * 2 * (deltaTimeInMillis / 1000)); + } + }) + + useEffect(() => { + setReady(true); + }, [ref.current]) + + return + + +} + +export const ZustandTunnel = () => { + + /** ref to tunnel is possible */ + const ref = useRef(null) + + const [position, setPosition] = useState(1) + + useEffect(() => { + if (ref.current) { + ref.current.position.x = Math.abs(position - 4); + } + }, [position]) + + return <> +
+ +
+
+ {/** Multiple Tunnel Entrances */} + + + + + + + + + + + + + + + + + + + + +
+ +} diff --git a/packages/storybook-static/stories/babylonjs/Materials/grid-material.stories.js b/packages/storybook-static/stories/babylonjs/Materials/grid-material.stories.js new file mode 100644 index 00000000..3a794cfd --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Materials/grid-material.stories.js @@ -0,0 +1,99 @@ +import React, { useState } from 'react'; +import { Engine, Scene, HostRegistrationStore, FiberPushMaterialPropsHandler, FiberMaterialPropsHandler, checkColor3Diff, checkTextureDiff, checkPrimitiveDiff, checkVector3Diff } from 'react-babylonjs'; +import { GridMaterial } from '@babylonjs/materials'; +import { Vector3, Color3 } from '@babylonjs/core'; +import '../../style.css'; + +export default { title: 'Extensions' }; + +class GridMaterialPropsHandler { + getPropertyUpdates(oldProps, newProps) { + const changedProps = [] + checkColor3Diff(oldProps.mainColor, newProps.mainColor, 'mainColor', changedProps); + checkColor3Diff(oldProps.lineColor, newProps.lineColor, 'lineColor', changedProps); + checkPrimitiveDiff(oldProps.gridRatio, newProps.gridRatio, 'gridRatio', changedProps); + checkVector3Diff(oldProps.gridOffset, newProps.gridOffset, 'gridOffset', changedProps); + checkPrimitiveDiff(oldProps.majorUnitFrequency, newProps.majorUnitFrequency, 'majorUnitFrequency', changedProps); + checkPrimitiveDiff(oldProps.minorUnitVisibility, newProps.minorUnitVisibility, 'minorUnitVisibility', changedProps); + checkPrimitiveDiff(oldProps.opacity, newProps.opacity, 'opacity', changedProps); + checkPrimitiveDiff(oldProps.preMultiplyAlpha, newProps.preMultiplyAlpha, 'preMultiplyAlpha', changedProps); + checkTextureDiff(oldProps.opacityTexture, newProps.opacityTexture, 'opacityTexture', changedProps) + return changedProps.length === 0 ? null : changedProps; + } +} + +class FiberGridMaterial { + constructor() { + this.propsHandlers = [ + new GridMaterialPropsHandler(), + new FiberPushMaterialPropsHandler(), + new FiberMaterialPropsHandler() + ]; + } + + getPropsHandlers() { + return this.propsHandlers; + } + + addPropsHandler(propHandler) { + this.propsHandlers.push(propHandler); + } +} + +HostRegistrationStore.Register({ + hostElementName: "gridMaterial", + hostFactory: (scene) => { return new GridMaterial('test', scene) }, + propHandlerInstance: new FiberGridMaterial(), + createInfo: { + "creationType": "...", + "libraryLocation": "...", + "namespace": "@babylonjs/materials", + "parameters": [ + { + "name": "name", + "type": "string", + "optional": false + }, + { + "name": "scene", + "type": "BabylonjsCoreScene", + "optional": false + } + ] + }, + metadata: { + "isMaterial": true, + "className": "GridMaterial" + } +}) + +const colors = ["Red", "Green", "Yellow"]; + +export const GridMaterialExample = () => { + const [selectedColor, setSelectedColor] = useState('Green'); + const onChange = (e) => { + setSelectedColor(e.target.value); + } + return ( + <> +
+ +
+
+ + + + + + + + + +
+ + ) +} \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/Models/model-loader.stories.js b/packages/storybook-static/stories/babylonjs/Models/model-loader.stories.js new file mode 100644 index 00000000..07a2ba53 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Models/model-loader.stories.js @@ -0,0 +1,94 @@ +import React, { Suspense, useRef, useContext, useMemo } from 'react'; +import '@babylonjs/inspector'; + +import { Vector3 } from '@babylonjs/core'; +import { Engine, Scene, useAssetManager, TaskType, useBeforeRender, AssetManagerContext, AssetManagerContextProvider } from 'react-babylonjs'; + +import '../../style.css'; + +export default { title: 'Models' }; + +const baseUrl = 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/' + +const modelAssetTasks = [ + { taskType: TaskType.Mesh, rootUrl: `${baseUrl}BoomBox/glTF/`, sceneFilename: 'BoomBox.gltf', name: 'boombox' }, + { taskType: TaskType.Mesh, rootUrl: `${baseUrl}Avocado/glTF/`, sceneFilename: 'Avocado.gltf', name: 'avocado' } +]; + +const MyFallback = () => { + const boxRef = useRef(); + const context = useContext(AssetManagerContext); + console.log('context in fallback:', context); + + useBeforeRender((scene) => { + if (boxRef.current) { + var deltaTimeInMillis = scene.getEngine().getDeltaTime(); + + const rpm = 10; + boxRef.current.rotation.x = Math.PI / 4; + boxRef.current.rotation.y += ((rpm / 60) * Math.PI * 2 * (deltaTimeInMillis / 1000)); + } + }) + + const eventData = context?.lastProgress?.eventData; + + return <> + + + + {eventData !== undefined && + + } + {eventData === undefined && + + } + + + + + +} + +const MyModels = () => { + const assetManagerResult = useAssetManager(modelAssetTasks); + + useMemo(() => { + console.log('Loaded Tasks', assetManagerResult); + const boomboxTask = assetManagerResult.taskNameMap['boombox']; + boomboxTask.loadedMeshes[0].position = new Vector3(2.5, 0, 0); + boomboxTask.loadedMeshes[1].scaling = new Vector3(20, 20, 20); + + const avocadoTask = assetManagerResult.taskNameMap['avocado']; + avocadoTask.loadedMeshes[0].position = new Vector3(-2.5, 0, 0); + avocadoTask.loadedMeshes[1].scaling = new Vector3(20, 20, 20); + }); + + return null; +} + +const MyScene = () => { + + return ( + + + + + + }> + + + + + + ) +} + +export const ModelLoaderStory = () => ( +
+ +
+) + +ModelLoaderStory.story = { + name: 'Asset Manager' +} \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/Models/model-lookat.stories.js b/packages/storybook-static/stories/babylonjs/Models/model-lookat.stories.js new file mode 100644 index 00000000..6117930f --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Models/model-lookat.stories.js @@ -0,0 +1,59 @@ +import React, { Suspense, useState, useRef, useEffect } from 'react'; +import '@babylonjs/inspector'; +import { Engine, Scene, Model } from 'react-babylonjs'; +import { Color3, Vector3 } from '@babylonjs/core'; +import '../../style.css'; + +export default { title: 'Models' }; +const LookAtModel = ({ lookAtPosition, position, id }) => { + let baseUrl = 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/'; + + const modelRef = useRef(null); + + const onModelLoaded = (model) => { + modelRef.current = model.rootMesh; + modelRef.current.lookAt(lookAtPosition.clone()) + } + + useEffect(() => { + if (modelRef.current) { + modelRef.current.lookAt(lookAtPosition); + } + }, [lookAtPosition]) + + return ( + }> + + + ) +} + +export const LookAtStory = () => { + const [lookAtPosition, setLookAtPosition] = useState(Vector3.Zero()); + + return ( + <> +
+ +
+
+ + + + + + + + + + + +
+ + ) +} + + +LookAtStory.story = { + name: '3D-lookAt' +} \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/Models/model.stories.js b/packages/storybook-static/stories/babylonjs/Models/model.stories.js new file mode 100644 index 00000000..519cd203 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Models/model.stories.js @@ -0,0 +1,105 @@ +import React, { Component, Suspense } from 'react'; +import '@babylonjs/inspector'; +import { Engine, Scene, Model } from 'react-babylonjs'; +import { Vector3, Color3 } from '@babylonjs/core'; +import { ActionManager, SetValueAction } from '@babylonjs/core/Actions'; +import ScaledModelWithProgress from '../ScaledModelWithProgress'; +import '../../style.css'; + +export default { title: 'Models' }; +class WithModel extends Component { + constructor () { + super() + + this.state = { + avocadoYPos: -1.5, + avocadoScaling: 3.0 + } + + this.moveAvocadoUp = this.moveAvocadoUp.bind(this) + this.moveAvocadoDown = this.moveAvocadoDown.bind(this) + this.increaseAvocadoSize = this.increaseAvocadoSize.bind(this) + this.decreaseAvocadoSize = this.decreaseAvocadoSize.bind(this) + this.onModelLoaded = this.onModelLoaded.bind(this) + } + + moveAvocadoDown () { + this.setState((state) => ({ + ...state, + avocadoYPos: state.avocadoYPos - 0.5 + })) + } + + moveAvocadoUp () { + this.setState((state) => ({ + ...state, + avocadoYPos: state.avocadoYPos + 0.5 + })) + } + + increaseAvocadoSize () { + this.setState((state) => ({ + ...state, + avocadoScaling: state.avocadoScaling + 0.1 + })) + } + + decreaseAvocadoSize () { + this.setState((state) => ({ + ...state, + avocadoScaling: state.avocadoScaling - 0.1 + })) + } + + onModelLoaded = (model, sceneContext) => { + let mesh = model.meshes[1] + mesh.actionManager = new ActionManager(mesh._scene) + mesh.actionManager.registerAction( + new SetValueAction( + ActionManager.OnPointerOverTrigger, + mesh.material, + 'wireframe', + true + ) + ) + mesh.actionManager.registerAction( + new SetValueAction( + ActionManager.OnPointerOutTrigger, + mesh.material, + 'wireframe', + false + ) + ) + } + + render () { + let baseUrl = 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/' + return ( + + + + + + + + }> + + + + + ) + } +} + +export const ModelStory = () => ( +
+ +
+) + +ModelStory.story = { + name: '3D-Model' +} \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/NonDeclarative/nonDeclarative.stories.js b/packages/storybook-static/stories/babylonjs/NonDeclarative/nonDeclarative.stories.js new file mode 100644 index 00000000..01d83f7e --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/NonDeclarative/nonDeclarative.stories.js @@ -0,0 +1,132 @@ +import React from 'react' +import { Engine, Scene } from 'react-babylonjs' +import { Color3, FreeCamera, Vector3, ArcRotateCamera, DefaultRenderingPipeline, HemisphericLight, DepthOfFieldEffectBlurLevel, PBRMetallicRoughnessMaterial, CubeTexture, Mesh } from '@babylonjs/core' +import { Control, TextBlock, Slider, StackPanel, AdvancedDynamicTexture } from '@babylonjs/gui' +import '../../style.css' + +export default { title: 'Non-Declarative'}; + +function meshPicked (mesh) { + console.log('mesh picked:', mesh) +} + +function onSceneMount (e) { + const { canvas, scene } = e + + scene.clearColor = new Color3(0.5, 0.5, 0.5) + var camera = new FreeCamera('camera1', new Vector3(0, 0.3, -0.7), scene) + camera.speed = 0.01 + camera.minZ = 0.001 + scene.activeCameras.push(camera) + camera.attachControl(canvas, true) + var light = new HemisphericLight('light1', new Vector3(0, 1, 0), scene) + light.intensity = 0.7 + var pbr = new PBRMetallicRoughnessMaterial('pbr', scene) + pbr.environmentTexture = CubeTexture.CreateFromPrefilteredData('assets/textures/environment.dds', scene) + var gridSize = 4 + for (var i = 0; i < gridSize; i++) { + for (var j = 0; j < 10; j++) { + var sphereMat = pbr.clone() + sphereMat.metallic = 0.1 + sphereMat.roughness = (i / gridSize) / 3 + sphereMat.baseColor = Color3.White().scale(1 - (j / 10)) + var sphere = Mesh.CreateSphere('sphere', 16, 0.2, scene) + sphere.material = sphereMat + sphere.position.y = i * 0.3 + sphere.position.x = 0.3 + sphere.position.z = j * 0.4 + + var cubeMat = pbr.clone() + cubeMat.metallic = 0.6 + cubeMat.roughness = (i / gridSize) / 3 + cubeMat.baseColor = Color3.White().scale(1 - (j / 10)) + var box = Mesh.CreateBox('box', 0.2, scene) + box.material = cubeMat + box.position.y = i * 0.3 + box.position.x = -0.3 + box.position.z = j * 0.4 + } + } + var knot = Mesh.CreateTorusKnot('knot', 0.2, 0.05, 128, 64, 2, 3, scene) + knot.material = pbr + knot.position.set(0, 0.3, 8) + + // Create default pipeline and enable dof with Medium blur level + var pipeline = new DefaultRenderingPipeline('default', true, scene, [scene.activeCamera]) + pipeline.depthOfFieldBlurLevel = DepthOfFieldEffectBlurLevel.Medium + pipeline.depthOfFieldEnabled = true + pipeline.depthOfField.focalLength = 180 + pipeline.depthOfField.fStop = 3 + pipeline.depthOfField.focusDistance = 2250 + var moveFocusDistance = true + + // add UI to adjust pipeline.depthOfField.fStop, kernelSize, focusDistance, focalLength + var bgCamera = new ArcRotateCamera('BGCamera', Math.PI / 2 + Math.PI / 7, Math.PI / 2, 100, + new Vector3(0, 20, 0), + scene) + bgCamera.layerMask = 0x10000000 + var advancedTexture = AdvancedDynamicTexture.CreateFullscreenUI('UI') + advancedTexture.layer.layerMask = 0x10000000 + var UiPanel = new StackPanel() + UiPanel.width = '220px' + UiPanel.fontSize = '14px' + UiPanel.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_RIGHT + UiPanel.verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER + advancedTexture.addControl(UiPanel) + var params = [ + { name: 'fStop', min: 1.4, max: 32 }, + { name: 'focusDistance', min: 0, max: 5000 }, + { name: 'focalLength', min: 0, max: 500 } + ] + params.forEach(function (param) { + var header = new TextBlock() + header.text = param.name + ':' + pipeline.depthOfField[param.name].toFixed(2) + header.height = '40px' + header.color = 'black' + header.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT + header.paddingTop = '10px' + UiPanel.addControl(header) + var slider = new Slider() + slider.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT + slider.minimum = param.min + slider.maximum = param.max + slider.color = '#636e72' + slider.value = pipeline.depthOfField[param.name] + slider.height = '20px' + slider.width = '205px' + UiPanel.addControl(slider) + slider.onValueChangedObservable.add(function (v) { + pipeline.depthOfField[param.name] = v + header.text = param.name + ':' + pipeline.depthOfField[param.name].toFixed(2) + moveFocusDistance = false + }) + }) + scene.activeCameras = [scene.activeCamera, bgCamera] + + // Move depth of field focus distance automatically at the start + scene.onBeforeRenderObservable.add(function () { + if (moveFocusDistance) { + pipeline.depthOfField.focusDistance = 600 + (4000 * (Math.sin((new Date()).getTime() / 1000) + 1) / 2) + } + }) + + scene.getEngine().runRenderLoop(() => { + if (scene) { + scene.render() + } + }) +} + +function NonDeclarative () { + return ( + + + + ) +} + +export const NonDeclarativeStory = () => ( +
+ +
+) diff --git a/packages/storybook-static/stories/babylonjs/Physics/physics.stories.js b/packages/storybook-static/stories/babylonjs/Physics/physics.stories.js new file mode 100644 index 00000000..e3577ab5 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Physics/physics.stories.js @@ -0,0 +1,89 @@ +import React, { useCallback } from 'react'; +import "@babylonjs/core/Physics/physicsEngineComponent" // side-effect adds scene.enablePhysics function +import { Vector3, Color4, PhysicsImpostor, Texture, Mesh } from '@babylonjs/core'; +import { CannonJSPlugin } from '@babylonjs/core/Physics/Plugins' +import { Engine, Scene } from 'react-babylonjs' +import '../../style.css' + +import * as CANNON from 'cannon'; +window.CANNON = CANNON; + +export default { title: 'Physics' }; + +// The TypeScript version of this story has it's own repo +const gravityVector = new Vector3(0, -9.81, 0); +var sphere = null; + +/** + * clicking button will apply impulse to sphere stright up. + */ +const onButtonClicked = () => { + if (sphere !== null) { + sphere.physicsImpostor.applyImpulse( + Vector3.Up().scale(10), sphere.getAbsolutePosition() + ) + } +} + +const BouncyPlayground = () => { + const sphereRef = useCallback(node => { + sphere = node; + }, []); + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) +} + +export const BouncyPlaygroundStory = () => ( +
+ +
+) diff --git a/packages/storybook-static/stories/babylonjs/PostProcess/imagePostProcess.stories.js b/packages/storybook-static/stories/babylonjs/PostProcess/imagePostProcess.stories.js new file mode 100644 index 00000000..17b8d735 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/PostProcess/imagePostProcess.stories.js @@ -0,0 +1,80 @@ +import React, { useCallback, useState, useEffect } from 'react' +import { Engine, Scene } from 'react-babylonjs' +import { Vector3, Color3, Texture, FresnelParameters } from '@babylonjs/core' +import '../../style.css' + +export default { title: 'Post Process' }; + +let sunnyDayRootUrl = 'assets/textures/TropicalSunnyDay' + +const SkyboxAndSphere = () => ( + <> + + + + + + + + + + + + +) + +// https://playground.babylonjs.com/#17VHYI#15 +export const ColorGrading = () => { + const [colorGradingTexture, setColorGradingTexture] = useState(null); + const colorGradingTextureRef = useCallback(cg => { + setColorGradingTexture(cg); + }, []); + + useEffect(() => { + if (colorGradingTexture !== null) { + let i = 0; + const handle = setInterval(() => { + if (colorGradingTexture !== null) { + colorGradingTexture.level = Math.sin(i++ / 120) * 0.5 + 0.5; + } + }, 10); + return (() => { + clearInterval(handle); + }) + } + }, [colorGradingTexture]); + + return ( +
+ + + + + + + + + +
+ ) +} diff --git a/packages/storybook-static/stories/babylonjs/PostProcess/pipeline.stories.js b/packages/storybook-static/stories/babylonjs/PostProcess/pipeline.stories.js new file mode 100644 index 00000000..4c18852e --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/PostProcess/pipeline.stories.js @@ -0,0 +1,22 @@ +import React from 'react' +import { Engine, Scene } from 'react-babylonjs' +import { Vector3 } from '@babylonjs/core' +import '../../style.css' + +export default { title: 'Post Process' }; + +export const Pipeline = () => ( +
+ + + + + + + + + + + +
+) diff --git a/packages/storybook-static/stories/babylonjs/ScaledModelWithProgress.js b/packages/storybook-static/stories/babylonjs/ScaledModelWithProgress.js new file mode 100644 index 00000000..e2310963 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/ScaledModelWithProgress.js @@ -0,0 +1,42 @@ +import React, { Suspense, useContext } from 'react' +import { Vector3, Matrix, Color3 } from '@babylonjs/core/Maths/math' + +import { Model, SceneLoaderContextProvider, SceneLoaderContext } from 'react-babylonjs'; + +const ProgressFallback = (props) => { + const sceneLoaderContext = useContext(SceneLoaderContext); + + let loadProgress = 0; + if (sceneLoaderContext.lastProgress) { + const progress = sceneLoaderContext.lastProgress; + loadProgress = progress.lengthComputable + ? progress.loaded / progress.total + : progress.loaded / 10000; // TODO: provide option to input file size for proper loading. + } + + return ( + + + + + + + ) +} + +const ScaledModelWithProgress = (props) => { + return ( + + }> + + + + ) +} + +export default ScaledModelWithProgress; \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/SpecialFX/glow-layer.stories.js b/packages/storybook-static/stories/babylonjs/SpecialFX/glow-layer.stories.js new file mode 100644 index 00000000..a36522f0 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/SpecialFX/glow-layer.stories.js @@ -0,0 +1,85 @@ +import React, { useRef } from 'react' +import '@babylonjs/inspector' +import {Engine, Scene} from 'react-babylonjs' +import {Color3, Color4, Vector3} from '@babylonjs/core/Maths/math' +import '../../style.css' +import ScaledModelWithProgress from '../ScaledModelWithProgress' +import { Control } from '@babylonjs/gui/2D/controls/control' + +export default { title: 'Special FX' }; + +/** + * official example + * https://www.babylonjs-playground.com/#6ZVKE3#0 + */ + +const onSceneCreated = (scene) => { + scene.imageProcessingConfiguration.contrast = 1.6; + scene.imageProcessingConfiguration.exposure = 0.6; + scene.imageProcessingConfiguration.toneMappingEnabled = true; +} + +/** + * TODO + * loading so slow + */ +function WithGlowLayer() { + const glowRef = useRef(null); + + const onCheckboxClicked = (value) => { + if (glowRef.current) { + glowRef.current.isEnabled = value; + } + }; + + return ( + + + + + + + + + + + + + + + + + + + ) +} + +export const GlowLayer = () => ( +
+ +
+) diff --git a/packages/storybook-static/stories/babylonjs/SpecialFX/highlight-layer.stories.js b/packages/storybook-static/stories/babylonjs/SpecialFX/highlight-layer.stories.js new file mode 100644 index 00000000..24435eda --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/SpecialFX/highlight-layer.stories.js @@ -0,0 +1,65 @@ +import React, {useEffect, useRef} from 'react' +import {Control} from '@babylonjs/gui/2D/controls/control' +import '@babylonjs/inspector' +import {Engine, Scene} from 'react-babylonjs' +import {Color3, Vector3} from '@babylonjs/core/Maths/math' +import '../../style.css' + +export default { title: 'Special FX' }; + +/** + * TODO + * alpha mesh highlight + */ + +function WithHighlightLayer() { + const boxRef = useRef(null); + const highlightLayerEL = useRef(null); + + useEffect(() => { + if (highlightLayerEL.current && boxRef.current) { + highlightLayerEL.current.addMesh(boxRef.current, Color3.Green()); + } + }, [boxRef.current, highlightLayerEL.current]) + + const onCheckboxClicked = (value) => { + if (highlightLayerEL.current) { + highlightLayerEL.current.isEnabled = value; + } + }; + + return ( + <> + + + + + + + + + + + + + ) +} + +export const Highlightlayer = () => ( +
+ + + + + +
+) \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/SpecialFX/multi-glow-layer.stories.js b/packages/storybook-static/stories/babylonjs/SpecialFX/multi-glow-layer.stories.js new file mode 100644 index 00000000..80327c54 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/SpecialFX/multi-glow-layer.stories.js @@ -0,0 +1,144 @@ +import React, { useRef } from 'react' +import '@babylonjs/inspector' +import { Engine, Scene, useScene } from 'react-babylonjs' +import { Color3, Color4, Vector3 } from '@babylonjs/core/Maths/math' +import '../../style.css' +import ScaledModelWithProgress from '../ScaledModelWithProgress' +import { Control } from '@babylonjs/gui/2D/controls/control' + +export default { title: 'Special FX' }; + +/** + * some inspiration derived from here - would be good to extend this sample with more cubes at least. + * https://playground.babylonjs.com/#129LNB#16 + */ + +const onSceneCreated = (scene) => { + scene.imageProcessingConfiguration.contrast = 1.6; + scene.imageProcessingConfiguration.exposure = 0.6; + scene.imageProcessingConfiguration.toneMappingEnabled = true; +} + +const Inspector = () => { + const scene = useScene(); + scene.debugLayer.show(); + return null; +} + +const RADIUS = 10; +const NUMBER_OF_BOXES = 20; + +/** + * TODO + * loading model so slow... + */ +function WithMultiGlowLayer() { + const glow1Ref = useRef(null); + const glow2Ref = useRef(null); + + const onCheckbox1Clicked = (value) => { + if (glow1Ref.current) { + glow1Ref.current.isEnabled = value; + } + }; + + const onCheckbox2Clicked = (value) => { + if (glow2Ref.current) { + glow2Ref.current.isEnabled = value; + } + }; + + return ( + + + + + + + + {Array.from(new Array(NUMBER_OF_BOXES), (_, index) => index).map(x => ( + + + + ))} + + + + + {Array.from(new Array(NUMBER_OF_BOXES), (_, index) => index).map(x => ( + + + + ))} + + + + + + + + + + + + + + + + + + + + + + + ) +} + +export const MultiGlowLayer = () => ( +
+ +
+) diff --git a/packages/storybook-static/stories/babylonjs/Textures/fire-procedural.stories.js b/packages/storybook-static/stories/babylonjs/Textures/fire-procedural.stories.js new file mode 100644 index 00000000..b731e37e --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Textures/fire-procedural.stories.js @@ -0,0 +1,53 @@ +import React, { useCallback } from 'react' +import { Engine, Scene, useScene } from 'react-babylonjs' + +import { Vector3, Space } from '@babylonjs/core/Maths/math' +import { FireProceduralTexture } from '@babylonjs/procedural-textures' +import '../../style.css' + +export default { title: 'Textures' }; + +const FireballPlane = () => { + const scene = useScene(); + const ref = useCallback(node => { + if (node !== null) { + const fireTexture = new FireProceduralTexture("fire", 256, scene); + const fireMaterial = node; + fireMaterial.diffuseTexture = fireTexture; + fireMaterial.opacityTexture = fireTexture; + } + }, []); + + return ( + + ) +} + +/** + * Insipration Playground: https://www.babylonjs-playground.com/#KM3TC + */ +function WithFireProcedural() { + return ( + + + + + + + + + + ) +} + +export const ProceduralFire = () => ( +
+ +
+) diff --git a/packages/storybook-static/stories/babylonjs/Textures/fresnelparameters.stories.js b/packages/storybook-static/stories/babylonjs/Textures/fresnelparameters.stories.js new file mode 100644 index 00000000..d1e223b2 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Textures/fresnelparameters.stories.js @@ -0,0 +1,150 @@ +import React, { useEffect, useRef, useState } from 'react' +import { Engine, Scene, Skybox } from 'react-babylonjs' +import { Vector3, Color3 } from '@babylonjs/core/Maths/math' +import '../../style.css' +import { FresnelParameters } from '@babylonjs/core' + +export default { title: 'Textures' }; + +/** + * Insipration Playground: https://www.babylonjs-playground.com/#AQZJ4C#0 + */ +const WithFresnelParameters= () => { + let sunnyDayRootUrl = 'assets/textures/TropicalSunnyDay'; + let pointLightRef = useRef(); + + const [pointLightDiffuse, setPointLightDiffuse] = useState(() => new Color3(1, 0.5, 0.5)); + + useEffect(() => { + console.log('changing R every second'); + setInterval(() => { + + setPointLightDiffuse(new Color3((pointLightDiffuse.r + 0.1) % 1, 0.5, 0.5)); + }, 1000); + }, []) + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) +} + +export const FresnelParametersStory = () => ( +
+ +
+) + +FresnelParametersStory.story = { + name: 'Fresnel Parameters' +} diff --git a/packages/storybook-static/stories/babylonjs/Textures/image-texture.stories.js b/packages/storybook-static/stories/babylonjs/Textures/image-texture.stories.js new file mode 100644 index 00000000..ce9ff14a --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Textures/image-texture.stories.js @@ -0,0 +1,91 @@ +import React, { Suspense, useState } from 'react' +import '@babylonjs/inspector' +import { Engine, Scene, TaskType, useAssetManager } from 'react-babylonjs' +import { Color4, Vector3, Color3 } from '@babylonjs/core/Maths/math' +import '../../style.css' + +const textureAssets = [ + { taskType: TaskType.Texture, url: 'https://upload.wikimedia.org/wikipedia/commons/8/87/Alaskan_Malamute%2BBlank.png', name: 'malamute' }, + { taskType: TaskType.Texture, url: 'assets/textures/grass.png', name: 'grass' }, + { taskType: TaskType.Texture, url: 'http://i.imgur.com/wGyk6os.png', name: 'bump' } +]; + +export default { title: 'Textures' }; + +const Shapes = (props) => { + const assetManagerResult = useAssetManager(textureAssets, { + useDefaultLoadingScreen: true + }); + + return ( + <> + + + + + + + + + + + {props.showBumpSphere && + + + + + + } + + ) +} + +/** + * official examples + * - https://www.babylonjs-playground.com/#YDO1F#75 + * - https://www.babylonjs-playground.com/#20OAV9#15 + */ +export const Textures = () => { + const [showBumpSphere, setShowBumpSphere] = useState(true); + + const toggleShowBumpSphere = () => { + setShowBumpSphere(cur => !cur); + } + + return ( + <> +
+ +
+
+ + + + + + + + + + +
+ + ) +} + +Textures.story = { + name: 'Image Textures' +} \ No newline at end of file diff --git a/packages/storybook-static/stories/babylonjs/Textures/pbr-configuration.stories.js b/packages/storybook-static/stories/babylonjs/Textures/pbr-configuration.stories.js new file mode 100644 index 00000000..e32aee3c --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Textures/pbr-configuration.stories.js @@ -0,0 +1,122 @@ +import React, { useCallback, useState } from 'react'; +import { Vector3, Color3, Texture } from '@babylonjs/core'; + +import { Engine, Scene } from 'react-babylonjs'; + +import '../../style.css'; + +export default { title: 'Textures' }; +var cubeTexture = null; +var cubeTextureClone = null; +const onSceneMounted = (createdArgs) => { + createdArgs.scene.imageProcessingConfiguration.exposure = .6; + createdArgs.scene.imageProcessingConfiguration.contrast = 1.6; +} + +/** + * Official Demo: https://www.babylonjs.com/demos/pbr/ + */ +const WithDynamicConfig = ({ roughness }) => { + let environmentUrl = 'assets/textures/environment.dds' + const [texturesLoaded, setTexturesLoaded] = useState(false); + + const cubeTextureRef = useCallback(node => { + if (node && texturesLoaded === false) { + setTexturesLoaded(true); // trigger render and props assignment + cubeTexture = node; + + cubeTextureClone = cubeTexture.clone(); + cubeTextureClone.name = 'cloned texture' + cubeTextureClone.coordinatesMode = Texture.SKYBOX_MODE; + } + }, []); + + return ( + <> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) +} + +export const DynamicConfig = () => { + const [roughness, setRoughness] = useState(0.0); + const toggleRoughness = () => { + setRoughness((roughness) => roughness === 0.0 ? 1.0 : 0.0); + }; + + return (<> +
+ +
+
+ + + + + +
+ ) +} + +DynamicConfig.story = { + name: 'PBR set roughness', + parameters: + { + notes: 'Experimental API.' + } +} diff --git a/packages/storybook-static/stories/babylonjs/Textures/pbr.stories.js b/packages/storybook-static/stories/babylonjs/Textures/pbr.stories.js new file mode 100644 index 00000000..5084ca71 --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/Textures/pbr.stories.js @@ -0,0 +1,95 @@ +import React, { useCallback, useState } from 'react' +import { Engine, Scene} from 'react-babylonjs' + +import { Vector3, Color3 } from '@babylonjs/core/Maths/math' +import '../../style.css' +import { Texture } from '@babylonjs/core' + +export default { title: 'Textures' }; + +var hdrTexture = null; +var hdrTextureClone = null; +const onSceneMounted = (createdArgs) => { + createdArgs.scene.imageProcessingConfiguration.exposure=.6; + createdArgs.scene.imageProcessingConfiguration.contrast=1.6; +} + +/** + * Official Demo: https://www.babylonjs.com/demos/pbr/ + */ +const WithPBR = () => { + let environmentUrl = 'assets/textures/environment.dds' + + const [_, setTexturesLoaded] = useState(false); + + const hdrTextureRef = useCallback(node => { + if (node) { + setTexturesLoaded(true); // trigger render and props assignment + console.log('hdrTexture', node) + hdrTexture = node; + + hdrTextureClone = hdrTexture.clone(); + hdrTextureClone.coordinatesMode = Texture.SKYBOX_MODE; + } + }, []); + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) +} + +export const PBR = () => ( +
+ +
+) diff --git a/packages/storybook-static/stories/babylonjs/VR/withVr.stories.js b/packages/storybook-static/stories/babylonjs/VR/withVr.stories.js new file mode 100644 index 00000000..4f0e730f --- /dev/null +++ b/packages/storybook-static/stories/babylonjs/VR/withVr.stories.js @@ -0,0 +1,103 @@ +import React, { useState, useRef } from 'react' +import { Engine, Scene, useClick, useHover, useBeforeRender } from 'react-babylonjs' + +import ScaledModelWithProgress from '../ScaledModelWithProgress' +import { Vector3, Color3 } from '@babylonjs/core/Maths/math' +import '../../style.css' + +export default { title: 'VR' }; + +const SpinningIcoSphere = (props) => { + // access Babylon scene objects with same React hook as regular DOM elements + const icoSphereRef = useRef(null); + + const { setRotationY, rotationDelta, rpm, position, color, hoveredColor, name } = props; + + useClick( + () => setRotationY(current => current + rotationDelta), + icoSphereRef + ); + + const [hovered, setHovered] = useState(false); + useHover( + () => setHovered(true), + () => setHovered(false), + icoSphereRef + ); + + useBeforeRender((scene) => { + if (icoSphereRef.current) { + // Delta time smoothes the animation. + var deltaTimeInMillis = scene.getEngine().getDeltaTime(); + icoSphereRef.current.rotation.y += ((rpm / 60) * Math.PI * 2 * (deltaTimeInMillis / 1000)); + } + }); + + return ( + + ); +} + +const WithVR = (props) => { + + const [rotationY, setRotationY] = useState(Math.PI); + const { showIcoSpheres } = props; + + let baseUrl = 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/' + return ( + + + + + + + {showIcoSpheres && + + } + + {showIcoSpheres && + + } + + + + + + + ) +} + +export const SimpleVR = () => { + const [showIcoSpheres, setShowIcoSpheres] = useState(true); + const toggleShowIcoSpheres = () => { + setShowIcoSpheres(current => !current); + }; + return ( + <> +
+ +
+
+ +
+ + ) +}; + +SimpleVR.story = { + name: 'VR', + parameters: { + notes: { + markdown: `Click on ICO spheres to rotate ghettoblaster model (clockwise/counter-clockwise). + + ##In VR mode + Use your hand-held controls to click ICO spheres and teleport by clicking on the ground.` + } + } +} diff --git a/packages/storybook-static/stories/style.css b/packages/storybook-static/stories/style.css new file mode 100644 index 00000000..033dc484 --- /dev/null +++ b/packages/storybook-static/stories/style.css @@ -0,0 +1,25 @@ +#babylonJS{ + display: flex; + flex: 1; + width:100%; + height: 100%; +} + +.second-canvas-babylon{ + display: flex; + flex: 1; + width:100%; + height: 100%; + touch-action: none; +} + +.container { + display: flex; + border: 1px solid #ccc; +} + +.box { + flex: 1; + background-color: lightgreen; + border: 1px dashed black; +} diff --git a/packages/storybook-static/storyboard-site/assets/images/building.jpeg b/packages/storybook-static/storyboard-site/assets/images/building.jpeg new file mode 100755 index 0000000000000000000000000000000000000000..ab51aee4c9cd83a4bdde5ea84668014612b75273 GIT binary patch literal 321865 zcmbrk1ymf*_W0Q|0}QT%yF0-pxVyV0xVwAskYR8MA-KB)hmb&U5+FFif?I+Hw=Cb^ zJNw?-J?H=5J-gL2bv|?JR^QvVs(VWM@50|T09QppSpfinK!DQI0sP&-G*Xt8eW|6R zsi3ST|5N|~m`ZAnZth@Q0C08l@zPP0p)oQxp@EJAU;qt30eAqw(%RcYT~|R5cuLCh zvNYaLO8@YG(&ZfRbS40p=2X(6q4|&e{}tg`dwBT(07&aeo6pA9+xm&4pV-CU$KxOQ z$rHn@od01k(m(9=z5!#1vNHcvYL`0QchYV!~GKXII&uk8~< z)Sfuj&(YTZiD#ae!Nu3r@rkdW80Kng=?wr#nE%LqY^@!hnEQz_z4UZspI8h4P%-WQ zi>>~PeQX1s`~(15caK0XM|%e!8Ww9-8Xgf5VHzb{e-~RHA5JYxYiCO@8yZ=6R}V|K zKmhpHHUCo!!2c(;|F-boTK{|ar)~eG@kjfA+6+YW?LV^r z)cudly$Aq=FP>tP{2!UsI{;{l0RWQ4|Hv2$001W%09q&h>w1X(=`RjGJ|54XJ@fbX z=W?{Q=K3d~|4#pp3jfypU&DXd*7Q6Pf)GhUEF=WXuLfvt!-&I z|L>jn|8vFva_hhR;Lx$Pv-PrddopG4)XN;*?4O$3&BoEk(cO*4(d~cL!v7zu{g)5_ z;J^Cy6A+X<04|qDg;%68bKYPUeE|=67&PK4%!Eufo{PNFeVrVrUWyApMizJ(qL7v9@rdg5B3BH zfuq5R;4E+vxCYz`?gf7Z&w|&$zrYs|0D=J_g3v-ZA;J(@h$h4YVh8bpghAktOh^%= z4$=u3f=ol!Aip6uNGM1INHj>CNTNteNcu?DNS;VxNC>2Cqza@~q<*Anq;;edq(@{d zWC~<<eUICLJCA#TM}WtJr-|o^hrp}C8^PPdhvGBg%j4VNN8=ac_u+36KnUmw zWC^SZq6kU|1_-ucC@^N2GRz4U537ZZ!%hhC3Hb>P2m=V;6Lu4>5kZKUh?I$3h?0mt z5X}+Y5>paO6WbEMA+95yBEBLaCy^qtC4rOFlgyIblG2dMlRA^8khYPokRg$=k!h3p zljV^Oko_iyk&BXBlf%hBkS|hzDcC4r>Q7EM3R2`vS!60I+7A?-Nr9UU{BK3ybTJ>3dD zI=wKx9eq0e7y1(hY6f+N5Qb`oMMgA6VMYhWw~RxKS4_-IhD@)S+L-p3Ntl(HgP5zC zmszk_Bw0LJidbe?QCNjpomq2Pzq5ha1lSzd-m^`xgV_by9oci)CpnNgL^#|yia6#u zF*&6<{Wz;R*SUze)VLzK+PIFMF+4MQmhx=q*(0|Aw+nX(_Yx02j|xvDPbbeAFB`8l z?|a@EJ}f>3zE^zhe5d^E{I>jg{0jmE0_p;<1-=M82nq>$3Dybj3o!^;2;~UP3&Vu9 zgb~8SBFG{#BCkX~irhRGeD3r7!}DWNPElvkD$zYLW-(i_60uEjI&n+!Lh&^T8VL)D z0*N(AT1iXEBFPOYdMO*JGO1l@R%s{c8tEe$ZW%9`7MUyA=dz))J#r8^MLD?KxIDhR zzI?X)ssf#Yy+XCZiK2jFuwsuAvXZJ&iqgC?rLwhhrSgf2kV>dZzbdAxu4=aGh8mli zms+PfSY1UuO?_E|QNvB6O%u>m)=bk}(PGx})auek(bm#_uf3zgqZ6Vtq)VXtQnyO? zQcp%NNpDG?Mc-Hdivf;-nL(w&m7$zrs^OZ^Gow(Wuf}A?j>hdKP!j`_GLs8adD9Hj zZ8HJ0ShG2EX7d2^kr!kyTwZj)#Cd7?vdIG3!qB41;@(ozvdHqnO4%yM>cm>s`mOaZ z8!4M~n|)hx+f>_KJ8`>IyFGhx`!xG~2T6xahu@B}j@gcvTsz$G-JIR}-KpFI+$TNQJz_o9JfC}Jc%FEvdX;&Dyv@DaePB<6sc*h4zA?V* zeiDA~{jU8D{F?&s0^9<=1+oRc3ET}*2r3Om3bqdZ5<(ji5wadC9aG<^%INUu%^1a)>R9Ypuh{w5qObGgkm4NU#^3P0 zdH3cKZUY~U=Z?>ezeiXjMiY1vvJ(C#+9i%B2`1$wqa?c}&!tGFRHWji2BmJMsi(E3 z)1<@G&of?TjAZg>=D$UM>-%;sOD(JY9mBiiclX&2*|YCu-q+_)Eh}t|494seK%ou(kJv!(VzZ)4*Go2f2 z%gZlIeMWsV{o4KG1F8eVg9?LvL()T^hsB3Kjyxaf7!@9E`zrXg^_#%AmN9{`mT|%H z)(N4B_U|I!J14~^KTSza^-jx856&phe4W*pot)F3TbMVSUt6$Q*!$t~<8;w)@op)6 z8F?ALg1eHrO0in>ll5o)n&4XZy4?D=4c(2UP3z5HTi#pu+tE8%JDI!GyOn#qdmr}| z_P-yP9&G>e_;vR?_7Lwd=ZNK~`B>`s+lkT1_NmwD-!sG?(m&_#3Fa!cYf*>IyBR&0fp`f6m zLZPUrSZL@^2NnS)Hs;fZ01t+T^Yo=6AtWTBqNk*wq-SGfWE0>Oke4?D{r^3|-yQ%D z6*&-61_99lU_1~65A?SmSa}+ppg{ha>-?YT$ww3@DhP}QpyL8y(39I>BnUDJ5*QgE ze{upq!b8TVMd6Vq(1y}kdct@kPzmW}QuuVNyb2qM7+8ihcc zj@QyN0t!nhY<#k*)5~Y&l{!hpz#sWRR@b}e3o0?AoORl|UegqlfS}Du)Zaw_69Rg= zRtO#-32YBZ`I;rGWi}=JN=n|{f&6e(tfBuIu!R?EJ(Q+Dj%LEDJ>O0IFWzt)Yq?G(pU&ZnTay^F9mmp4i4Dq zRDj%Uy`^~w*5j=6tv7JaBFk*?_xgla^5xGXVNZpz+Z6e`2&8=b^Xk&iQNENfx7NCx7edAm1KlL*e^!JFjiHfg^ifkX!HjE6^@9esAg3xAujl2ES8{@%InKL8>of z&8enV53pp`q8!>lI;+8e{W!)xVADUFRHOK=sD@P_H$wHAF-(DpzTuB5*d zDQNZB|Oj%v|7r;FimH4oa@nEQ&D3^+cv&mtz;jFxIOpd-|VW03& z_0#8gkXRO_nZb8%O=*3m(B?1jcDD9y!uYF9Un(cA>-chqxBgc_Xa|Iay4e z9m$&??sU5lDv|OcG-3LyI7vE_yKmJ$#$=*+Zz%<$ZUX(L?c&;9NeQw)heZw5{{ptE zeOw)wmJ!~6!-+!7^m z+3rH@uXW2VR%1BS4A>WVFXt&AL_8lWRUP7iP#VeRhMx&&7!orPl`z5>pxinb*S_uePLB{I;s7p%SzEDyg!Vc^6se zhs^ZUS2c0-%n-!Q?d+!p@9?efsDf87cHt~WLGfv8X-5t}493YJP?4*mqtXZx(g_&< zx@VpvxoNvmv$^sN=);`f&<_pP+>_^%wYSU~3`raGN@3p|Cd@>ViZ3p=2pir$$YY$m z*J^%|KDCxGV%w_aRl*e#?ikVg@ny8)AG%tdA(|7{bt$Fby}pnXw7^Jq%A9tF3IGDR0(bGFxN_OHG*wO&=(jR? zqt;uCBiTK9mlxFUkZY%Q)5!CCy$zgp&K#QWoC8J{6sa$fuK6ckYr#d&$|FT|usyIi z&0c3?m^b0YdFfq=R9yU^`?P2lIf)SRmiZ=Km66b_mRd=X+kd+&uKt`cl_*eZ`-cA4 znEt2k1|gHnBr0Nj6zE_e;q&+9%4U3ZYrD5(i5FYSon6v2r)^!q$7N07r)z%!-p7`L zfZ)*5$CDsgR_F%qjOFRe_2m`n`ncq-g%z6AIo->fluyR$Xaw!{?^``!oHTv)Uc^X@Gy@1058 z%z`I~yO8q{O?Up=wa1P5d+1}aw&1H%|G&WX$Y0>Fmh^=I951#Mj{vk5I?jTI^z!G# zV)1}_!$$Z{tCsSbUGxP#;F@${olPD3l}5A`v6;v+lk0fx58;ft%QkL8=d8QT?e8~? zI94jc)z4}5T+Jc#(6xWHc54qi0KF3z&wOC1Mfj8z7RuYkDun*hD@%7;Z5nWG6M!Ea z3g38ZPsZKBF%wGQxPFEF7<1_q2=p%n zG?V82lW`-!BFP zyeu;Kjaq7;r9`9cWb(tSD~7{$wEmXNdr@NmV2HZ>El&A;w68s{;DIPnnf@N`;?qa_0YlQ`=@X*#%{ant_9b6%1goh?BaX+3~NgXrg` zk5YCkFaYl~abi~aO;$-da0C?7Nv`XV*Yj^0fO+IeK|z3He?zSP0J9=7U91I&2Cj?F z3!<#({wC`|b84Qg)}xQjiWf`PpiUYvKIQPPSkD^F!pm;vX-c*%H=e>6 zesj%66MUS#y4tr?2b7o^UO0O_fIA(xfVuNQgWYB8JHyswjO>6fg_nbkZi*s&JC=p; zCBGYe&ZKhrX~n+D^MnowRw@lF5o4TUr4MD!5ruiYJj(B@d*+Ol1WL(@I%)?=41qG|iXSyi29Zt1;LfxI2WeBQ7H|v%ejr@yIp83V^8&+MMxJ1h{l`wM z_#PRVN?Wa`OvM;BeOzl)f1pqSj- zu% z#XnYz2n78z?1xRpqBCyE+@ z8%>$~bj4TT);B%E{5~G6?UgQCAc{JSoIpayTd=b^pHjYlb7Sx?{^-REuAJW#SrprD zR#d=WKvq9czoVQgq58l?p^$Prr<6g1SYZ2^tMUXfV9;I!ZNERwF<= z)(cHW$&e~KQL(p+f-Lj-X2E!Zr)#jqVPNskXVsQIAGb9n-fuS5XSaX;Fdkni{uj^_ zLvJ+uTGG&JzXn|vOw+DcydX-l$NoML(89Q%Z?(yOL@PWQMW1dpz6;U}<$03R= zqeR~Bb;HND7ki-#0aX}x=FYfILC>UDU8@?5Pfj$X@iCZv7=ijKA-F?SkVZryB;CxPilA_qQ}z*v@t8;nGP1>tm8U;Yb2W zYQRzOOzYFL8ZYn!4`;Oe(`3i&kVfqTGFLC{kEKSs1S*~+2}cPL3G!_a;S>2*MDe~Wr86G2eQzj2_NiU9T>3c6%vYT>+prz$<#o@S?ic2IF z>toC1Q~cELs+p<=#K`U54c_f9?M6#0Ynw7WV?$(cD3Ok@tV+x*%r;R*MM~4o|4MY+ z8kfXl9vL11rm6M3F5BYs{I;w=>Fwm_`^*rg__fQdR;Y77`|%l#R)O;Lvdo~^EmbgY z&6{%B8F7V=>0gPzA$~$K8~3#O6L?i7Sc<1A!c5Qjg2*BeVvViXP|-1j(!3&}#tV3; zu7&t}>LAV8x)y{D^%7DZ2n)H4G~a&&Ew#b(T?^r^{FyKMBQ6G{7gs70og-m|;~rw3 zO2Qk(&G7|S`1HPJN&Pc{UI!;idiW#Fxt|#iCcD!>)!!ELC+rmZ_F0AYpZN zx1VaymDYwG&hvl$gU50I5%`!_t8&T>wYr^4`TL zc;yb=xb;&uhUze#+R*cgxBg@ER&6m?;4#5#J(#10G_2LRpX)C2)-)HCi z1vc_8i(JrPE-BXxR~MRh+OLC-P4LCS(B1!VvhTyktSi>A>G(6KUV(&erZV~KTm`US zotWfHKNP)+_$(_=_db=y82y^&m6^5-s*}f8qH7$;A7;r?S}H>cMU<>gLb@c=xd48A zGU{xF&M3lGEO*uC>NSRjk;M3v!;jeoU&V4$!lJ}Sio=xwEqtH^TY3!pGi$Gy)?028 zF2c*Zh6?Qc&%#b}!^uzPD7WX3uanwNZw}$UB=iDqBk*&}NzE zFBr+X-i4V2l5CbTi`$~1e9((pY=DlL%k_@2p^TC}Lu8XsAqQ~r$d_L;pnqk88Q@EJ zs|4dRiwv@4`ECW&jg)3H>hQ^Jdk+vS%W93wBT4Z)C0eQKWHk2(;#jK|SrBT3OiS(* z5*ZG%@Mv0gISjH%5f`(8Hqxg~-_79Vcp)oR{6?jjj+|WRBzq>{-ZZmo4`Hx@r*K#h zxY2m=!0D?Bp^zqulta~4Ub?|@W{H`os<)0jYh>ciLfQ(QQb&i0`D9M5IID?EOK7-H zqbAc1hTVwX^0E{gv;k5>rs_qm6wZrVIbC3vDT>H_4-kbruga(7c*C=HT9k~r``jce zZ+Ei%=MDx&lhUVZshd(vUUaS7!iTfYR1kRDh#PcPas7tiQw`(VGq{E#T!BSDt}J6` zsoGvS5JsVzgU{mlW@Nyf%vD6Z!aq)e#88KwfMghw?fQH-M<<6TGE006+e$pHG_F=k zOCAfkCBFGJ;&xJ)lO&aAHF3l?Qg|oF&s5fhHCx~n1Ly;qFhuxPYol(Y#5A6FdkEzn zem|a0>cY_wztxeKCS@hh%U{xZ&hO~|sMM=GW2H!RWK3ZBn#llXv2x0l_vvma%h<6=|#Ryl| zp0utI87m1h4vTp{IIZ?njkGj~tl7hB{sNdf+V=F(Jyzr%R}yUFRgoPQ+`$nhF%|u2 zFECFL0~ghaLAdO>FUdL`99NW{ZIZm!M!vIlsqRCsDKRwsMCbFxd4=8AiTL^iBG5#A zTyX!nqD}`_nkEwU2**>8^TpC=CkM2NnSOV*Tm90zE{BW@{ zlL8Ju9*j`Rpj+j1cMNCkkMh0<#u5{v8iB5_R9Aki=F4zP`Mbu_^u1^Wg1FUvR1?FW zT7h!rT3~S^oOnVo#)H25-WC2^U1C4(B750;Uqeh8Z=;>VD0sH+8u^sia6hkBRk$GU zXh_SW4Ogag1?NpN4*O22Yxyt_RYK1-*_W^>F|PSVz4^?lq78t-S1b^o>k%wW0eLBv zIem*D_GC^)TifWMy|eiwAdw^$0kn0y7O%W>I$OH8zIJ~a2pH|f*D5kTd@B=B%E+P* z7WrLP!F-r`eK4M->B?*UU{lNs= zO`Ir@U|8({0SJQ2HXB*5MD{H6M9Nu*D-jk_VG9ug_K$gmI37N`O!&~qoH z{{RJNCi=KI1 zVO=*+Po>UVcDO_!blG+3uW#<#t1Xytgth`$cQ&gu-#H&u+ALO4xshE0gvt%D|FA zk+3BGp8W*a7-hq1&KMp3NZOy>pAS`HQ9FR>P8&ub-QD{U+NFlV&3ajbiOO5_)8{Xo ze?3;sTqv^QC5nH+&_1vL(`goNG@Vixbn41qy9e-(QB5ssbJp1|U`8M9a(M+7@^^>4 zyl3fb;d`C0kx7CkIYH`S?Y=*tEJ@r({n~JsJTBP#7NXHwsJ5Bod*BR?{R@~x8Bf*P zby^S@vSLRgp3J_(Pn+`UFOaU1Akc z6BWr?D+UWd|CVFQJf~2Ln-D3$3;Z121IsXeROl!vu-jewmzgX3r=m5~*Mo1c5-TZ0B8iKdcid0X3K{(?yimMm|`ce~(JtOA(ar9g6=Vt<65DEq{ z;aF=r)ABJ$e*8a^L}Ns(8S1CUU^BB>20ExkkxL>lbJw_J-7>;uZbc_z7YoF9y}jv_ z$ZXdUa2gL>D5l# zq>nEDR~G0HVzxhCE%B>{-eT1;mHum_{Q70>Rrv%%dWP(apRpf#2poTOC%tvI2&%8u z9(YrfUa0Z3mf+>c`dZYB3~|u<>u%5%qm8*O+v9v7#rZ_|egV0Qx>QnBh9Gg)=EKxx z2-KuOI1BOYjSlvUUo;#-Y>7K%tSE@Yc@H^<*;fWUVN$O)={+gE6at za7=7zkz0hWsy`RD(@>}r)sHN$0I?7@n$DPv;Xy~--tLK+JKaSiGOgg9I1|}>HN4%% zV?~EV=Wk?5uWf?Yz_^M1QOZ*bc1SK38RHHg1rfCx?<3>MfM}~`l7M@n3Fu<{_9S)R z+{PwkRiD~Kx}#YEUBO$y1e0!)ae>W66}iAJ0uJl!+EQ@c5*v>q|MWg znV-Qg$nREz3Qj5G{3XPHFhjWMu1SGCw3@uFU=gsTBWE$Is@LqWvZ1xw2UZZhf{nGu z=dq-jwo|94Xw>(;wcdrT#j+qUNgcAP$Q;JR67Iz)^ju+3F}Sg+yd}aek)PJ=^meNI zqtk)X+C~&i)s=&IL5e9G$4NU0_Hr_GB|$}rG1iv3ubIYw1mUw4q0Mwnxw5o{<3(wOEhtfy8m6cpe-ld$^coB${+bgXn225jm zC>HUel*o6Y;m)wSvNFbdu6U6LTdqnmN=iEm6~BI2x8!Pmhpm|T()~;z@DprR6Hm?x zJ-7cxn9v(9qX0YiO_ln|0cg){;_T`$!eB_V(`X~Xlmg6d+%%D#&vv4iP+&N_>qD`d z%-XMn^OJC*9+8XGX*+)$FMR6i^%wYqDyqmHNWJc~_w>GxL;w=p{ovNTuD;~Og60jE zHOo&;D~Z9#%SkQ^8}XpZa{+>N^{`L^1Ngepja+oD~6$k7IGX&`V2jZetM&f5* z(FRH$5kq&iYx#v`g@oy1Zm%&*$ZiRc`w0pHN(^7>iyZJtQ?ba>);hy-g=_AAJFXP| z%6^O&OLJ`d^Fw97vE)rF&x`9ZLD{uPWJ;y&cNut;OZ4b)qd%9WxD6J1$zibQlcld1 zCBsRiR8#H9O4m`k6JLT8liqJorgxi7k0DLF5!?=dmkBZg^AHL4yjyyKu6@ApwI&x=u>}VoQe2 ztN2#UNvE}i3{x6m2y{&6I8JasbgrA#ZiwFJjGMx)c81J{+i|agJ7BqB#z%y2ImrFx zt-N`NTuNB~ciaw4tBl4ZW7BNmI1ebrGgyRAR>oaq&sFIjAttjY&8f1#bNF&zAQhWN zMS~y{U6EfTdo5a_WhZk&O01-ir~Y(Fb6wG7%UZ($nqa;tcQ*a_Ngw2b(2_P81EYwM zyGC?D0<_Sx)hY(By@lN_KbX2Cqi!`S_b>Ibx7gf&O{%QG=>BAb6qU1vXF3jNzRPPQ zarjtNnrlM}P2|>8IIsRZB}C*ON?%qTHPDbS(bTWvM@Z(2-?h{)|9PyV4|0S>z7OJT z88383`(pajtQyl_N0#L-WR~&gzP7n3zpR_SF!O`A3fm6PSxw6pe8~9SnTlAM{57=d zEn^2}e>q2qP{`)O^jFnpQ&~rRSl?>@)@B~@&&9YgH@e{HWZb@R>Ep{%3~AwyQ{StD z6r|SLK5;`AQ{?*$(!BYULF5m)CHL4U@_d%}ZdtbsTC$zfdQ+3TL%spK3oZHQ*v1ihN>53A z?#myoex9yl<{U=dvCyurT$J+Kfbk(UEFQj9+#vWJ^GwJ_+j6Icbij=-&G?51UH4^m zGu|mv`kLgKq4jyPM1&9!C~RD*pT{;|K+X|E6#2)-|qMLq#dXA)pV-;+G6MlesEB{YPKTL{3hkP z`(+8sLKxw^*jp&9qxeyE;Llzgb*WhN z_sL#$WO;A~8ELc3)a8Qz!fpV{SGg+jK-&fh8L?+qp@^qxtP ze@qHGkVJW{0q}c?obbr6yn5a4B}!d*JLyBpuac6eAj6|k+WCT|FrULysdqStw|;^y zUT5P>0kBIv9tyjzmt`vyDOy);A<9675e^!@bimFi?Js--=onx-Sg$7D0tNg*uU*d? z`B5Ze*#n@b$=^Svu*3PBogP1U?nLo_)Eb@|1g8y`PxVG$0HNEvD zQi^(B^M=yr*k=fE`{b*bf980-_1iN?Ckn5ULxKI}$>$gW4D)zz^f>sj$ZzF+)d$8> zHMxp6$-+oC0!}EIHq%8|Jw`(kyeL@w{J$Jrw(J+fG4aK+GcCK@x+3T>MJR`;#AfZz z{QZ%zkzM?`h8sDYqct8g)LLrs+-lj!(*ZR`M3Hc?qsfK5HS_K(*HDk4V#>a^(;$(9_u)qHo+? zthU!%=%f4we;qCiU9C&3b+hW)%y6n(v35rv?_B@_ArhJ-r7lbo7T0i3mq)8jG2U5I zRfkEm;hP4u0SY&Q$6C(nuyg{zf z;ayupJS|<1kAj@JL>7f7BDAHt@#IjSHs|U0Oc3e}G8#jm1_x?J4N?6omAr9-h4=o4 zNDmH)g{3lU&l9hq3!ZAl7E|trOD*bGl~^^?bZK;gQ{}=WccH9_x+hndGQ0dNy>HJe z-{-PTxws>6gJ$$-&hr@p*&MCd^&PS*cOQ_2j}FC^a-&0&n2+T+{bdl|OXqYMi|zaR z4Bu-lvnu0YGrbdNtWga}27E>%MLjp(<#mZKu?4nQ1=2*%kSEAjn zmn|xu7RwAPv~^GQRyfr1G*)vH%%Ep#QFS?Fn4TIPb~Q_?r~dJ_o`T&M(ysl=<( zZRXw=?4Jq@b>zR4mJcP_l<~WpYmlR6faC*Hi%Vi#F}e{7sXwQzMApLI!Ri(#b(Oph zLK<*GSh;8_4m3T)E5Bl}#r_-tz&JEh;@_Ol0O?|)@9u~bFJuZ%jUT-nyy@szRBbr) zojY$N-XBPSwo)BmYP8sAwBe)&JS|1+Nx+BK*3uHC*0ML@d1NmBxGWjLc`XFF%zQ^f z`C?Y@P5SZbN6TsS%K1x<|746QlGR9UCo%2|Y9ZTxqMNGa{9SUUWs}obF*(gCrzBGP zj=q;+${T>fvg*auvY6gn*1Iyr=#60-f)msQvo!@izC;Tfm8HXAUj)t?Ui4FcbaZbp=Il z6$8H|TZ*t)_@JuN$IzkdAX9lN?CrzhUX;!(Z*b6>7)_#nC_Wvtpl}H8(KxfsNLFUypG#DyOT|_X#6$LUF)D zN3f+!1PVCJON84oP6LKLiNR*-CDxgs03MBc2M%?m~hnyG?j1egWu7XCmc4YN$vriUu@WlMT%NX z*iGqyjQPSENvhu03>@4WeJ>tVacug$#A&de_1<@=Mc=uU^E7)Ic_d!(@VNV6W~6y3 z82=M%Zu@1K)yU{`9s*w_=1obGz>&s!}ljt1UfGiwfjG~5ir(lE^(n#Uzntp&A3>8 zayEp{rD#kh5o$l;UMPJ&V6R-lxUObG*lblxtzZ5H6e^o^TIUHi_=!DCgIb%S&95c< z*tmP9PE~3m-XL%=98^6>-D%J6J@mQh&*yg=Hfdq3H4Wr(a&LBRO-DfYt|BV z3YC-;RT<8@8qlPaw^P$0O!8P;qwqe~PB=%yI3M=F`*9RDpzWP)obG$0lkHYCwOBB& zY^+#MWlH9tiZoH?vmAn(&Da$BRjpswzW!L!XRq_}ee*3DJigj{-A>9tp4xLv(v0_q z&!XR8ltt*!7(Fh_=Yip;L1c6tW!kP>2oYsG6E+r2pWrt|trmyrBjU@se2VxEhR!f3 z)pw84S9oUai*ib#e@t)$)^7}A;H)+-3@$?pm~)LIpNfmukBO)=j$Gzb(`HvsY%U=u@yPT?jSjCGL*^;6%LQ|J z>QsKUj&+!YE1_h%-oCgv!W829N?o3FsP$u_v6`SVmsq{YGB`wByWinuP9U;jin`o& z{B-MSGUxWY_H7u;=JCecyIh2vd$RraY?nOxQ{-i}xmNj^6H=|D3cHPN$H{KG%)s+H zH#gG{NG*n-#P!x|-$`&;Np2K@6HSwulaAOENJH06mS4Fu-z0z$vJizjDPsIr z*>Ekp=#!yc4Tg72o3u8E=kDFkdl@=Cc!>ugI{5Y;1CksnW-JP>b;2^>0F#9*f?@4vPrPv~qhmYJ9hC+CeB4rhE`7@@T+HQE5;x})!R)Si!D3~V_2y_vMZj{5V_V!GrTv!A0?rhwfN0>xYkG)Fa(L(mEil$ zl0(L?`vQtu7@RV^V*2tIuGvz|i~d+<@%{Dbv|i4#m3|d&;zQM@=Y=kYAEjc#$@LpR zgwGs0eNcW_8MP78@Cw51#_yS2}k4>0teY4Uz4lgDsI3S#!8WAQc6j!nW>bn zl23nTlD;!FP#Fk_h3Pn2dlj09;pB=5rBpb0@F5_If`Z!yYn0`5C0Rs*(U$EL{+AWC zjM)kUqH6821YnwSv1FS)vLVK+N%55{Vx z(@GfrBT**9+9A!fw|P^d5TA@RPFlEdrFBKK&H1WyFSTF@ZeT^^nG6Sm+5OkVhf~9a zEC~|oh-%wqr|-j>>K%kwPKM-Kn`6Ai8HoH^kro&)A4tg#Kamy6&{2;b05^Si;rLSG zODpRD(o!)foPVqF^I1R z<2_{8C)^W6>*{*R>CCu5G*suK?Hyr{WLUN1FrEi?-xi*Pd&pwKsLiV^o<(eLS$VX8H+H`jSfnaR zey;~A8I1^!W^-CQOsVGBQ)Is~F(!XsVJ)3HhA{A{<``TUVeTO8x z9?@Dt_-G8fiL3HPA~db3KO)!hL_{FW+0oCqQ^lMU4pWCl%J-S>PxY&-S?EI7yc{La zDD7RtsVk7KYA-}=NLJ1ocVSFfDoUk_-+nx8#E|Q^3hB6SwxS3>rdx$pMZXPf3C&6S zu7g~xP+^p3y6jh0SB@>s{1cq(HiBfuGcG#gS@p9CMN532>FMq8*aOrWK_!K?=Qt*I z>U4;t%964^3it?83mS!5KuPr&*9(Px>58Wf0l2P`o|l8B8a^^I2j_cOCf$*`OPs?U zD=A5_$3RA1Y3dROGBdwiz)oUTD_zu1;w@67=LFF?UoNJWn0>qFCz{gO`e zGr}Wlb0{PUvomUImg*udX!s%h-aX}-wPe5x@ztR=*!NZs4ev|B{bN+fXOzyGWOEKJ z-%`_&s7#tX6xIaZDB3NM$}?fVt-vB)u1y&>{4;lvCTUdTp&Y}?uvK0(!h-{(W&0AoDdN^Nil&a7w_veX-Q!LTGOj5 zXCksM0#DlB9A3n04->GEXXcnQ`d^1y5pl@e)D;7iOjrk{E{nwTzIlK9r}^nves&+^+PG}yW$zDeI%ul3J*dc>guEUBC!%=hy( zxrsX4t_EDO-#>}1t*24n;NFmM{9uo`Cqc*Y)?cg1`)qL;M|1B3B1P}G^0~nuMIvvv zi`r+j#;$d+kUG>6Y8keru!+XcN8K))QQky2Kb*QtN*bM{NpSsIoel3~^Tv;RbtlL< z;0$raL4ptEzh=nVCUYQBGAOvC!&toYzw%i{yc`Tu&ZIC6(YK3|{LEcatlfH^H z58**xlz^S&BbTg-^KsM%Ru?cp{$|L-IWQJ=C}laIu6T%^9zh1tOr~>n^Yhw-s=%OrxD2@s|wNk+es1oKi9sWjr?t;K+&SO4PHB=Aw4@OOHD*e<2A) z!3Zgv@F35)yfmdi&Cm1CdeWlo)r;dg0UtB&>so%e<<2)BYHGj_R@J|M#Xk4kc24<> z=W0dvk?)OlN_nfHKLVFDicqpvDIewb@mOiLU~2dMqlUk`67|;q0dqi%zm>n})m5^a z?$5;9~%p&a!4BnU=4?jS7sS?vwb+VjGH)ef~SN$p`)NbRBDP#OvDV|qI=3F?4?HFuT zra|m=#d)tlu#yY?%skDE*isJG45dzS&MfJKNKjLfgOZ<*zl|gk=;Z$)+ znuo>ym$i|^Q_FOvNW>|C58bg*E-jUC^8xFYt+Li%5E=7rr8DCuKQ29rr#(ps3HcLD z%MXN>*01C~KqJleeIEca@c7L0Dc{N|PPmS8cF3Ss8 z;RA(|U!Cd})cWVD^(M{EsWW{Pgahl}^Ru=qaaOsL3wwWcQ_PdJZb zlckt@ZS$=`!KH{Lj%hWP(a6# zOmF3NfZ&0e^@Qmh5iySnK*dc_SePv1K%kG8j@;7+RYUla3BqpWYEiV6me3`}0~~EM z%GaG9>K8${?iR+1*Nx}C?>BKmWuLur>9aXY3Z#}S?&zQ z#siED_%$G3U8ky8Fd#PKe2S*p7Os}CGqF9qQjNz|+z`Z&3v->>sTp+kX^9;wLTeXj9~!;070l~^510t08G+N&rm7IWbHu};F zPGZ~S`K_VUq*ffzH<6sL){}AbD+(@1sMox_f`4L0U8G|MrY$D@!tTPFb6M&(?IBrk zRQ)NFqAvSp$G2lfL;>X-5ziu|*OebC_0ElddHX9*kPzk26Q1=pXu7)wDwr#{4t!wv zs}ZBwS*6n4DNtk_pCdI>G)o(cX}1o_LFczMZ1nf^w8(*D5zhy2djX9V%f7DJ8PD$%!oDvauO1~+`=ax+n5f@NWvpZc!l9fzlnW55{2K@S;8 z3uA(Ls}#p2c&{>jqFY5Cr4k|>0hd2I04RxpG+`lohTJeH35$>b85yS~v=1Br9_(oV z39P=x$*w18!m*7;PaWtvM3CEKGzGg!!t>2PtTb6J_M;pR9As3EIwnZiKJZjy8+qoA zKvFWmR>yDP-A-4EP2x1#00i@n^xo0Rt-BTgW4G3)E|k+^_0sXqM?WJRb4*(eETWSk z1x%dyZ+f0I>quJCKpk?ck17DB_j3Um0QIfnG%#AEWb^=LnHTz#zOx`JluWS8ayIq? zn0mgvdnP=#e1Lo!U(}_6uB9=9yJ=4N!TK7B`ikT!M9Sqx08vMVH1>U-g1Yi#g3;vZ zwP*=-nTs+Z!jnx#xQ(V}2f@kj%{Lz9qsh)WJklcF6D|qB^GcVmIci=ic9B8ryQif* z4e^E356Beix6}xPF*(AJ58k1-f0=M|&S_{~pOr&k0nH{`HD9*zJj(K9@y5}bQN6#$ zep8-*tw)m+B!tqet{C^^ngKSmdkP^nooZK7-c6QnGr*!rY)bAufT81oLC@-QN(`W( z!J_fRP%)sWp>C?nh0h&m7EnO#%_>1>ge=+4I2FCUsrL1!$7r`XGa4Rj0Pq{Qh_L=Gvn)V%WE?}OW4~PU!3e|&d@Xc;sr?}$sHw)z-4r0V0i=|6(8w(X|TN1r87L! zUflZ5$Bn9^YM{r36)DMwiY$A!PaY`b%Z3Ee1!3x7J_dVHg+5MK=|z-sJK%UfT2PER3*;+f6q)@00In$7 zxx)}m8k|T86no1IQ8|ty91w8ddL** zY5kcw>hJ#mQLQh;H!!93v=0&xmQW4Y=OQJ=dNy#N?c{hgkF4a{kiCHfXMvvp(&UK7 zFaZZ73QE=hipkw~5R1qi_^A_AJ90kr5$;-|o}m)~0AsfZdr%bq#v9tXBM2S5_-vE5KIO)zyKDaOu*@WLQI$EWif# z%^+6D?vAXah6f;u5J)+r1A|VzR?b^_$Eo?7Iiws4l!SJ-T{0&sJy@k7y})XXT|%*? zXHBdycwh*p1P-(-MVRB`x}WqkUuOkP9b^0$fAfF67a;LXXv7Lik$m~=Xe9jW_Y|oj z`S5$vVH;kI4L4=Mr42xT%{SR;JW{r$wA?8l{jDh~i$-sKzIC-{HI=Q%uA|lz;*Cbb zbrY??B!C5VC=Vi+?e0|=#`$Q^^%XH_dQ>+EfMDmd<2?Hsj5O^YY0BgtdsV#Y9-X_> zmI?F-!x5Jq=cE2TPatluK}orLY$x19y;W`SiY+%WV)K4g%9+=cnzG z>KR%*Alf%$v8n3P2t~977YEKhl>w+;`Kq|6-D6RV+r}f$wcpUueM-e7wQK+itybH~ zuA$Az$d2KzEM$wfn4-pm>HoYgeyn`@Zv2I2jubK@ed zuAO$0#H>p)k+rc&x4jt^>dfCZ5bj^s%{R21K_ds?8f9-XKqZb-v@z?7qh!exEHVK0 zJ}H%ZddL7$c&YPO(3K#Whaq=zDz<7YM1^s{?V7f$DH#T!d`%!zVZW*>n{CV$3uVHaGQlt=YXoT@P79MGX6S&uu^?QrgzMb5XW0kqZE)9(lB=ScF zo8F|Mn>4d(!L6Nf$P}L}S#H!rQTHX}iWgIkDLUnwq&9XPw9y9+bbQNFdvSKt1tKOI0Ri`3cV;W4>xWwn=?ZJK)rfr@JKZlE7>k zsU-JBdb`4ITGA9KRbyZPsYg!OASlt0$BZ7_cRzZTF7>Nuqibcz*%};ypRPqmT0&br zz-M8BoRRhSr2DC@qSXjEVYCJS@y#-HStP;F12wnpLR22rBv|X_TZ0d#yH$x+CjfEp z?@oF+;#z{~!gFs3i=?X<48^*$U13oF4jw2{4F}8?f zh{~i4Z8ceSc%*rA&vH4Y#Hgu&MNM5#rW;8k+%R_JfPdDZD~D%sk9<_lRhJ^M-xFHH z6tYN0=6qv}b5P!~ zbkfcMaY=ba-!0G{mA&d0OKWah0G@zTmiJq^n)E-Y%1t>eHH}NskZ)kP9{AwXD^Isu zhm0Tfr(B>z8z=x0Fa{~ZDsa0+M?lvPmuAYIK%&3A8DpO=OR+wE`86M0nVpP`#N_+a z=kSvH22H+C`gx>l>wT+%&PRWI(Z=3sj-v#VTaa^rI29M(9D=x}%RW1reqKd{W4D|N zWf)7pZb`*PI3bOA>%)v7QIowp7C4cTjmX)oY5uhSI}=I25;Q96yJXBl3ZhNwNXGw)^+@r7Kl=6B*dP zez@^kT*OvDKpYMT98guI(>CZr@F|~ga7YIfnI=Cd&jX5fwXnlG0DE&t6K>5YysFG;CRvV1p%tE8$QwM-Ly=jHj_NF2l1&?dOSj&S zP^xm^3U*ma%ENAQYCy7>xkT<4&S|q}U`p@__o=Hy(yf*#+~Bv6cobfOwm%Q)_fk5H z;B_>kYo&fGaV@t1@I@aQOQNn1EO193tt>=?)>v2M10<2=o%ZOg4pV4F;GZk+Niz{! zGFZcoocA=_5Jv=PJvAP{jPc(!>h_>6W}oE^$Fc2RpaYJyEW1eo4h32pE8AHjNfFiK zl|vz3K?ku0vm~WhjAOtc@luJ_iJZ*L1(Deqs1nXWOlTNr+SM#l=8=#$i*I($~qK!`y+&|2` z@%rQ5y=!jCA*>^*Wl`UgN0jA{%YsjT`_sHtZJE_J_Qh#+411KRIX=`{(j{%`M?4BJ z*$tC{^48XfL6Ggh-P_zyVu`tgByObX<1hj;3g;%VW$C#*jOLauzn=ljrkthiHc;bb3VC(`MZ9S{8O&Of= z@TKc(nBTa=6Yol=ft-v}R^19?wK(lwHbx#)&=F8q5rtw`IIOt^2^NUVLa^&P8W%6&iAG&J)ggGLfXXz+Z{Gbu>P$gP5hPuKd^_bv>4 zalo#mM-Bk)d8*m)^XKZ0uNzK(d0_Lv0YzGC#Rdf<+#0K&4Ys#Xbz=ZXI<%aQ+zPXI zR}f1KW;4NTeyhQzcAwa<_?z{sZ;Hcy+!zM}C;|Tf?TYr;*$|O|?r9qQhl|oqeL&uO zidu~`2n79U0m)O5?0BgPsX_gwbCRcug0=5j{{Ts~iBux`$@4!LAP@@GW;eHxbtrq_ z6A_{nVUW@({$CvX)s^Zi300V^;UI0ToZzF5Kp%Q!Y8H^*-N6*rvCFkVR&$)5;4t?- z^$BqsGXf3>Bjjt)+7;Xo+p?4m9E$nJ44LHhrmm?7lI%A+QNXzl(H4McsrK_8H za3Yz5#z#9#@lu84-lg0kLmIq$#{`AI?l$=pg{^5iT5I-Z0z^|n(8GR8*mE{ z%Z?m=b)adotV`udyW54fkT@GT>sxgfO10WU5` z;qDYpy}>|vBi^jOmbW)DEv)cJ?*l3Mi2SG96vgWvotpmu)t&_Z0GYQ^1V}O-CFJe< zQ%lP-*q$Inib2P&DgKeH0MDo1In)ev4uB~grvQ1=yYpbbl(&J*fw<_y{^gazPURlhx z(aOpSlYmE#I~rx7!KnjJzqcAi&AY0Z8dPLsKmhJ(^hH<@PB`M5sy-ZyJC%8 zpopsHki_ya+)(k(y9gqaG_tDa1kyV$G7Tn5pXrQJIqJPA~vNs8^;gW8-&9!5=iE5ZH%TdQcVE|s>k;Zq$&52jm3 z3`j}<%5(KKZ8W`S{{U9orT~rdGmI75F;z*YLf{TD->%xWu@(`{XLJcCaVI1n6-~d0dCmiJ0I0220VI+D`(I!pr3>2(>Ped1 zEMS7%@tjjpb@=AJp4gC2%o$1Nf!%4_(^1Gb<<*zEkUV{AEXHF)xN}f#Y}VH7Tyg*- zKN@gq*EaU{stN!{eEWOT4^Hbfi{)>WZ)|;qI(nw%B2$nKRDdds-)i!u`DRjmIT?T* zj(i$@V`eTRY>JrCbhxi9+j{(RO-nsd@ew4{rGyNoaLt@zn;L&qM#W2aUIGagb`% z^fs?7+SJjwKAenMD&D&)MnG;%e4jN#Ix=-j=w!&mX_h3^w8zIM{Yjm zqluuC)#Q2Nto`MRPo!>ze!0hheA7BD2_}npBXXY|kNv3?m=Ho#uXSrxNhQbfV+8(#ijVE}L`!BQ zf=YB4))W~=7D2ZIl^oJE_k$#srp?XcPq~S~t*4WA?l3u~yU10jYbw-ls^yL-&!e1y;*C`&9%o8K2u(Qbq2ywTmD+LG(#^EqlPz(jtztnaEmEGE2E|uu zn6#+Bf=Zz(Ti=}2OQgfD_JE5?pxb6@E# zdg|8B{n;%pT?}o^QUyL!>s>YOQwO^b>0F=cTZXvmEnZWMz2xVQ^BU5%!{vx%L$*!C zZXI!78$Qf~T@6Oka3!@7t9ed0C}udw2D&5Be-LzjqX8p6h2pMcw{yw*q5ff0J-mQ3 zo@T23{VngW>8b+OsisKU`7RPUi25P2Ro7Jc1A2joUCT;2$+@ zuRS{Z2abY;nO7=!BXwwKMv)_AMmgP_aqZ@{%7*;h9OK@)k{Q6DBix<&&jkG`WJ`r@ zr;0;Y0f5QJG_a_Txkd*ZkEIP3U^paE_~TN9gV^>Q(5bx{TNuZ+X%5r`XXT;Tuo)bW z_ss=GF(i@H8c|nSW8LP1W3^BF(I_0FfJX+6N(%*H+cXr=rq{=613xzch%;_?Rz3cd zW^n4u@}5To3QIfvKtcP^)7X?Aayn7fgzXs|P)?gj$7(Ya!K23`6^R!<1q}#h3_+x+ za*hbeUur9LlaK~R1_#!+xC;0LdBql*QX>V9ae-Y@ajD84^;o_UM?9LYza*Q98kE_= z!tTvXS3Ns*r1d4W)urXsmY0%BF0G_}=@U219z61+J;g&m2=C&G>!<{d6h5Uf_UCb{ zXMJ*vBjuy(RPWI^eI^cr|KfvWiFXKA_a1Np^Ovo%{uQPyB0|#cLpgGh?`;!?gwmrsIj;8 z5K9%tW!OvOBLsIG_%!#q{42bQU09w$UjxN9bxUWp{6y#o4<6P4ay;-VP_KHc+uRr0 zp6e1w%8ql`)l=&|3L7cm)bz;YiULrwjOG~!oS$<@JzLa&@g>#1qcY;{p;Wv+9oK;4 z?kZi>^$Q(GO4L%`VEf@4l>Y!Dj@hcSB1;6Uj0j=D2DAN9Jf?3i8zlgcIsy-B^xuY9 z+(jSW19|qlkr|J+QGnsSXct^ibaW_XqO1rtSO&C$D_YHFy+)$eYc-1Xbq!{=twn4r ztE(oxTUWEqb#;3cy<-*X>gvr26Jdd^Yrs%Z!RDk(n_2JRd#EBNJ^uhRXBf>hv$T*@ z=QO{h>Ys;#<_!FkAsqYB3D6jo!s8eYbKIH(jz2n(eXIim&w4Io`FNq>DnQTomWmF- zj6_KOtN!#_BIh(;P(}-GebD~^p`?0q-!ACkUq3(T%{BWRS5YNgKhRRmoMq-g;F^}< z(0y5A3Ww$$%`h~0@iOiecDh4JhTz2`HvoK~cyZ1tMc5VDyH}?^%zQ7WYLH#M(r)tE z4n7qeX}Tn~H*m4Y&x7>yQg7}s@~ovY3hwzxr5$nq02Ox>Xb5CGPabMk(=FEDry_Zx z$2gRE9QUHlIY{F;I1I|UD!;Tn=r`)k&2RZD|Yqbi(w}} zGWW=*E&Y|0x0hazI2)9c*osin;1T@9Q-+iGWPo$Fx(gWXo@o;~a$6pm ztB=w;eU-hjR8SKmk>ZZ(HzM0rXvrHHcQ5-IXLPQ)Y~pA`47S{31Chly`p)J+Nh}rA z62DPYZzKgsj%w+*rdSQo-DV+?aNy?z))uD9sXf{ds)wS#`-q~T4lhX&iU2S(;xW2s% zqX2xQ5$2=qW2YgUz_Bu~tmh}SHf(iY$6Uw0WmzC219laG9gcgNA6C|HE_BPnn2Jkz zeetyYKJ>~sWr@*K*~ee4B?K~C`Dq>$D8Z(eR_S_74+vxnBB@3L>E^1H{mfSP#UjB( zU}@c}U28W|Gr4kdMt+pVT^8-64B6!KRv6XNH3a1MHJ*5m?*4U#D_ci0D}vJ%!NqNP zs$5ASWjr4gQqulqf0>Eqp97|3D!T(5C^Ul%lQxuE?eB_0}XL_dZ$VEM)RcIxSl1 zl0@B|-RsMyG&8pGk2FHVQQL41)jR`IKB0RI=?Mo1XamdWunH2`Eo<#XO>jg^Vt8aZN-4 z*b;fEm!>WM02h4(dpBi=6m%dQn!R{J80OS=mfN_Eq)=;Uck(h^40!EMn;kA$H5j5m zKxGZytUjaCwl-GIA8!1QPa{5j({2qdqPSa#*C9}j-i}%EIC4CMn)vzocURND> zG~CqVyS7M+D*kP`8OJpk>Ne5EHWPruaPyH<-PW0?ye%rDAD1kiGxVrMEblHZhydj*9*i+JVFEJr=Nk9tM0&|Ttr8a@-hJDrsu9XA}hY*8wJ22_wfWBSxlt!T1X zl>zq*9OJ%yja;i;IRtKl^5A*x_NGR;)5~)#M?WTa5%m=fZ+=!x6UQc++iEH26=vX* z%~QMmGC^#t%Gn^XG?!_mytesOJBa{Qlhw4So-~06xK15FR|JgPeY1~+c0 zR=-7yaqHMqnWVN<^H^nwATM)K=AWX=4TMQ3`K882J7dA6%YK}AOS>V$fycc{QOR#E zpzxA5r)+UcH>T1pI^h>5g2d;!s0X@~w@-SZB)WaTZTGN$8m(7y!YzoA20$PmZ297$ zJFQI*$~F;_d-F=YPjx@yWB`z$@H0@g+ZBA1`qiQs!lp^S3^;m?*j;-mYWGEz?N zed!|OO(reCXB9YVdTfbfB&7+=xKZpWwFHqHNn>RIu*#BqQ**VKH5aOQb5EGaUn=gW zpN&HiS^(VBj@lBjv7^#yqtg6#YhAEkM0f2C5qNt1p z_u~{@mF7+RNgSNh!p}vxx{X=TfLC!pN^sigyOq(S0aE~S2k2|6*&c^=DvxBU5x}Sd z^4$nx4sdBY3mMF*#xvTc`Ls>iv&5^AxNK)0C>bpxO-IJm9w;`|N?!)dW-jCaBnyH1 z(_t+=IMoP0Q%IL>!6zfwQ_oeIVBi%S&RV0J$)bFaaYe;2)+2_|S|uZLj+BooWmsmL z7YY=6((KnGZU-M~Z%*y)Tq_&DbUi2tv&qFC7Z_3nBYK=-gAQoes1=x~;+5iNW+t3^ zb&F4MySQBUG?ic!Z3I-6rbf(D2ttF~8O;ZJx9IjOJh5*%8Od6etl+hZH5liN5lQa^ z(@42Erudoo>Tgw6?pm zm`x0eoc193Rvs8q`$_^2mmflFKm-s7IR~MyBFhZXNMn%-x}B`2f(YzEtpbAKix2x! zsRbq{!CnWNMP16|o_*-*%6?vQ2;<(3O{7*NcNnEs$s4)tMpVc)`)9Q#hboMGiZF!W zHVq9&vhhl@N00S{c-2L9;7ld4rwyv zjITa>lk*z1Q^L{Q!c-l-m=466fIbNA{{V->4CB|7gYFA=t2cU!ybyfxpA{Wo z0JMkVpw;`u_b>j`Un%IWR1cRGx)K8q0+TKjC?FrVK50-htY2}-`%+Zy4nsE;DO4D< z=2L27rrP*2Mz-YG~4x!N`!4r)!+<`6?WG@DA4#_^Ec)K8|~td~lTWE+k13BPV5Ti^&7PKT2X~9ZW8@Wv~!W=|W`0jDB4CQB4{^ zA7k`mfm875hFBuHgWrKm%g#XKsLna1u9Uy^ZEc~KZs354GlR&%ni(c=(yOHN4Vf#mYh-8X?^AxKdh%(KBx5q+H!p8&{+OcMNK71#)iJAC zB5JB*Y~{vyz+9TFdV#pMos!v58C32&c`ASFNt&p!)NMn=j3Y`3eZ;Atcvz?L7FvcDa{5X zw3O$S#~$?C0CPtml%r%H9M>9NG6AD1J5iYPla5Y5>q1Joa8-Cb{{UJpq@#c3G(u_G zt_=&QNH)c{ux6qn+2$M6ed${9Po*AzzHv($La(UF;fIl24;3YEXZMTLjGP9=3#Y-f zAtwZ5pK84y4^6w-LfIhj3uA!QO`wkwxjH79wSa~$S?S)&9lNh$!Xy>*Q;YnbBm42+mv!10k!nQv!`?SiR72?m9^ z)f(c~*BD7xD%ko_NnHBd%Mw@&H@T+G-05$1A0zV& zGTL3l?##^_a5Ih%1XI7M`jSh*2uH{qpSkf>!shULh(k8gb56hB2;?cr1aK)c3}!`q zaw)C0r38{NC3hwOZ(PuKcLq4!a(%^ZWpGrig^zG^N@=A{dm21wTO=v*$)}aiL+S{M zQWDBL;*@7VMpz8fuO{rzycOGluoH~a98WmB+@S4hwml)!7h0a3B$o~SpdOTmlZbmKU@!X?G#Zg;7rAPfutB1XiqIV|-toK#)^j5b1 ztV%)M$@&_t(`XW1Tx5bk?rL@^5>?(lRNGctx$FYklevf+k7|rA14@YB%ta&FLdst? zAZi+X>QxbV$BH8jn~>^P1oov$0>IWAd*Rt+)gzJB_oq{i7~+yG!C3(w4k}U8>?ON! z2|GamnqBFhk$Z`d6+btcu~t1OEf6sPg(TzaO(waHA&m1{UXP?bt+*2~1-aQ(FHwb} zlVMCa;EDiSNX5WhoB}aZ=T+zkac~nEU!Oc}H5gi4M2hUgl|R*S=9Ec;MhK_3Ht4U( z;fECzUb`gdK;t5jwL`os_#o4pSTHO6r#$AHEf{z)??^~_HRjI|yPKQn1MUoR2cZPr^cR3^rt^fvaaPw?wvOjaJNPS(PkLju&8!;{FxbGwIdyBe z;k36UvA|6C1pR6=*P&?idyANIu8t2Q9lVcffq`-WB;dCd=$n6VWSnj|6(Za9K9=Ta zWZHK|K?jPhGT*E>(gX8E&-TdrVx!GNQ+X7X1zeIz91=}6zj-znajPx8l0~@W`&~sj zj_TIc+mr2MKAcsS8vVE6_Ch&eKp6i3Vc^s6r*)}41X)w&$oq_Oo@$@znu~rp2JA1? z)rPj!AeP?RR5;q+ndXz8)iz)*a(dLow2)mwc8;uS)Yg@&YE+IDjM9fQ({*_TB ze_nFxxZKrm3*fiF_-u zCZevl=s16JL}H9)Bf9`qQIp}N{H&6IK*0<#it9Dbp7#;@Wq2Z*cYP?kRRZl&IRc>V z^(iAwr1z$<>h|(Rt3K8_Cz|C2-$sZm95ayHzG2?6(|rjg)}XLD6%GLej?3>|6V$ps zDDxHpRyl92I<)Sev$27kB9mxu2bn(Gi^}B7k$r;#F}2o*yY*!)t1&X zBt(|LH3!FQd3N$JOa@{PxunygUNzZRqhg_e1dM%Z_h@}DW|j=nKnsv^N#~kL)$AaK zE!;1B@lQVfrb3}=IjwEva=Vz2deslqx_aXhNhf-XFEpI(R5>J$51Q&Oozj-q@d+f0 z8@W~Q`kH7@@VY5A%XdURnv9+XF-Ke22_cRMs$Q$%Z7TJMFR{Of*FPia3E%=*k+I{B z38cHtGTUk12yE~LbepO4ojTsiK_o~$BtAJU;0mProvaM`QUKg|9jU}JtgDbQRQ*rF z8fCSp@>Cr5YOWVLcE&hbPKM4_kN~~=RNT;8G>0j`&lIBeHkd*XAos;N#bgcP5b`rD zssKGHlWn8A`b&;j@@iBTX%q;F&fey+>8k`0k(_(2w$Cwo=0ky ztZiXN2oq}O9{dh+DhlH85_Z;w5{M()oRLs{=S#9$nGfa!?E`|Qq1*ieP>jWLJ1_$V zuI<`IEDpPd&@evLTY9aeNWw(ij#!T86iaE`oKl3V#QTRzsoK}2Y9j+2p1|V0MDwdK9$pcpVaNTqQ-clcCx;XQkQm;kK)@0?H~t+N{%|Sql}$7X=imLCE~ogU{D1z zV1z7{qiPn*KG|Y8U^s7Ifv=Qa5%C0?JddZ|WT}(`5j@5SCvf;0rR`-M^|_iB0sCN{ zN%n7J?0nNfk&%k9A(Y^QPhCSw)w+KCHr>cc3i!%6@~vB3O>3$kYzX90jmO8ZZ*lBu zw9tw3(Iy>Npl^t;MO$6%23ibE9)6IMtG4A=862H4|?Q~Ta!vqgl-RfarCIOrh21E*YwZC*+@xVCWW|onD}p@@M=)EJLD_JYSPis z&@!+f^dh`ve`!6evPCRy8^&@5yXC%aIPNG%Qc;5Vz!aT2at7|{kw#&ZE;V9k8ajfK-Ff)ZL8i zlcTBSO0e(9s@L#3J-smyC%n>TthTINygO9nHzKR2!0aBIUO(|%pRqM!H7S)YAmor; zhp_ETY)AW~AK+TM_^gxS{YQ+EEQXFFgAR9N1047!o7W0+oxC3B#%XO?S|%S}J+n#9 z7aMSK_4<2Ml~dvNT=CwSn#Gm1)|)gEXZWbfqZ@Eoc&Gx$M!Ev#%%qCZg6Gp8$VL}! zPMX_a4?x7HY>pRrW#H!}h8T~&Dg3dEn0JN=Dhw#cb^6mX`$>yU>d7u+ka~B~J7doDAewR| zn?RXH%w+B)`xjn;$GCYJ zrIZTOG}}m?`P?8Wv0ET=xHNY1)-h<4=MoMG_x}JDHy`m5Z6wfgYHY}3VV$IN=A2eB z{vz((6SFV^oq`zFr5u(zrQers?z^@IQNb;oWYck=a^Z$@c&8Li?>J?gU0Aax$(WvJ-ofhBRxF!3bb zOe=2E65t18(>&l&xUk?7dm4FI*iUgPEMS)KDYv898RZHMU0;R0GX>P9-BF z$f%c9wY)b2(_!--)guuO0M0n8U6g|5Rd?(gG4&K*SLu6e+crhzWMDqSG}N2n%of&i zF<+TU!ww0lFG*{tq!F+?QF%1~0M)b6oe; zdJa|C+dBry_oQ79qU~;gE=X*jmxIMwjdxRt>~Jx?vbfJbaZSx7E$w7X;ZERwyw#O& z?o00?r#-a1a6t$;lHrB3+BTzzd;+(ee#WZfLqjM5BQdQ;CODXj7N|E%Y z)R%I^xj)IfaP!Zahr`LqJk$osrWt0#98({!G#iApyp31{kOHU4+H;Dh+J&pdY>XS1 zCq63Tb#AdW+FI{jkd)d^InR?-LtlnyXCR-Da-V9m*%<^NH8a$Vt72MDcqR!Qswce5 zjAo45Bu{S2#P3$(u{;dVxG5`~(Tg-O$j7>xc5_~N^5kpgW=w|2B>uG8)GcacWvYx+Ar!66#H5AT0quHtb_L%GH`%s0FlfjBH?cdvGcO z>YjqTyhol7oab<+_L4{Ee(>ODil2?-_P7B500=c(F5M?C>Onq6DQimUi8VRpR9pm$ zdlGR-5owo+c3@RLrgot7yEv;6rP)4(V)I-!URZWx_2#VeIYh#rX#1j+g4E7WnGO%3 zs>yX`)_2Z>J_xC&p{!uMVI0g=RkFk1K55^tbZ_G=wA+h#wwXW#A8z}NPQ4+}_K0oE z51-S+5AS_VM_gaTw&d=?IUIEaQn5sqEi9r;C$+Q=qctR2bhW$P+Lg};InRo++7C}g zSY!>V38vMJn#FE_rZK=ZHfaoyTLMSS*sRXx;zsXS=D(}mJUCY;u%eBpBu+MtXvEfG z(~lIa#iWq1?L{tJs2%~uMr53GS<=ljGG)1_*HW?dVSXyEbzYinpm^=$`Q^yK6>@IQ zBMbDV9p;&9BMC|dU}{#{VuTY~CXK1I3^!!1cooSmrRW*pww`z4-E*`4*{Ih^(ISrK z2*?iQ`*^OJbzXz`uT|C~fJX1As?jcpv1_nMk$Py1HxtJnTE5#~i6c9@;MSK7t%cKx z%qiwz^ZC@f(7ib}onp?J{wU7ea-`MP>5CoKu^C(E0-=jVh(&DZKu`f?9!*TvI;0Ur z3n^cm_^M6ZuOk!cYKyKs(!;hj$2?=UDp_b@jj6e)N`T~Y1tH#QW!!CQ*5F8BB=#br zl}N^GH-gR4k)68JZ&4njhR+!7MI_?W#&bblB+C&1XMs)Ul0fkX_Z()QD&z{hK@RB9 z1{emIx1BKBh3d&EVHgdT$s6fRE%y;INk5MLV z!=*5+Y~i!C>+8kZ%|METDaRf z2v>?d-J0AL&k6@hU}@S#q9Yj;?j(VN3C$3_(a~;;Ny^3n$BL3J5(v+A`Ft;Lu|D+M zp5hyjsEmGI{zhrQB%IVd);6I6Y+gDFK($o2UCci?J69dSsnb9pDx-kB2KE^|0BMb; zX;HHWDV?}D`qZ7LTS}9u0A!F9Zt?9+=3qe-rMy00pcQ2FcWCyKbH{30dGcgsY&PuD zHH*eDPTa03bO_}G1TpS#PZd;edXao@CWDcK#z5K!Yy(xds&>F;AQQcb2f(Wlaw8G# z2PA!e-m6bj!14#-i+D8l)84M<%6xiNUDUBGx!d|@-n~UNXlFAO2N*v1uT`9Mtb*;x zxPRRf&sn#w3hgj2Q7J9y#p{=e#3%hSVoVnqU)RzZS^!Hv^L2s(*P-z;evJ=Z} zq%P?c?Kc+Re=A5`T@Y@bzZf}W3){X}3{*w&TjA$YzNypiryzoB4I()saQ>Ud12YQM zuF+O)>X~eEqxijR;?9!sU+M5#++KMbWRSyhdc(0n13$`3bflk%8U^N=rb86)31OIp z7g3z6W1pE%k}95cM@e1illt&)lG`H=MoJUms`K6=3Vb@}wMe~9(U3%!D9A)=f;>9%0RBlTDqCc^Ld%sS8+}yO_fGLe&xfwk&f^ji z@_CG-_j4}n22;;GS1l3Xzl19QvM*oXL*F5A0rG6$K8L$?mW~is3tyKm|4a!-JZP@Z>gZP zOQ-`$YT4esUOI;BIj2?cPwH0JZ3v0w7-mkD zz<_u(<iz>dw$EF|hfFMu+* zrD_G^+DRP`S`kZ-!?q6;M7!@FH3+Op2ku81pd>4~PU3PreJE&AaK@ElbDsF-mD1pr zQInHRpy2nTWr!IKKt(i`AWb<~rt{C9DTCBE&|BL~vJ#-g`(MB~JTdW3SndEq3Hhm^ zugV3D*>a>9C0(pDkWlbNBH0RQT|OLL#uySZDhl`}Zx^PmaT;wU$T{#0Puk(d#jri{ z)e3wNDtb!HY;57aW9J5@PNkP**4}v_gH5cz;UWJ30@d%tM8Ax$#?TL)Eh$3k0|wv^ z6q_j~P{5LLial&WOy`0zpS>iKc1U<{n;8R|kgBX}`^KalUg|4rT+F+bT}r6@#DktG zj=IEC{twb++Vd_v9(R#{n5+{oOi9tKB| zOeHQDUj8r45X%8`)M9Qhk$c2auzDUQKZzv#w260omIEqLe zB|8LxMtwG#2V9mN)@*+)7jftOvjT+BO{o46JvS;;7U%u2X}LTNHjON4CRre35G|6% zFPL(B;-4Kgq}uf!qorGJ2rmk*dxhRV=xLVXT;q&@YUt?%HoK)Hq(%3902{OV)LVOT z6!>V_TPizyQR#{Z5<|^ub7&nwf2CX^yF()l$~b+zZ(ngmP2IbJ7;G0} z4&KBHYOD@&Mrz0u6osP&qaZT3s*y}RY1UhmagC)02=)}gyn`cf&N1^3`qS?A+Bjqp zp%^1Lq$v{_rw?uH5`!%T+u~dMJXc&7^19%5%-}6xz~)<+v^CR{{ZS@_;DbOca2{3Z`*=1 zx~T15p0oG@Spzx9;mH5o2vf+gjE~EdHc2QfBk*e{bq!$16tP9-mX=> zZVh8KjB`Yz(VPK}YkW{c9A<_jD`kE7G!&?z0-R8*xcS8bcZTiAtmW>T$!Dna}O)9LfDP*nOXdFMH!k=V}G zTQEr4aA;%H3f3;JHsTOIzbVZd)AiLK*%FwiFd0E?}jXg)}eTRsS--(*oc zdMT}wNAUf=n|&0JIdH5Cx67Kd{ZrD@Ug=itl9B~D1M5@{^8WiuzM30_BM)7C*6v^t z;vfl+f(JPjLcS{Kmb0R`jaBiGaokmVO1gIT7cp5B$24J{G1&LoYBRAq zW&CdP$;%ZypA{TxnnV$5lc3@@f0LforkQ0r&#i-l$>fg<+9T zUV+fhHhRsQnK^!j=M57rQs&)RPBoacafzve}_coTcvshckz;l*kQk}f9 z$r7eH85H1#7uXvgLMlABm7{i$WP{B}x?ZHBAS4_&y-?&*I#xe@6o{mt$j?f0h*hCh zz#jCN@NHl~`_LEn{-5RSXq1-{vTp-}ifk3C0w`zN2{;YwO|3{TZzPk7O}DUFr;W;E z9Mh6mQdyTd?ONHgw9bHVr1MV0ki1ouXJmkd&O-8jbR%fdAt!HoU`Qm0%wLpOIH}4g znU@Xh0I1trv2a)c#(A!WLR$pVT6O7piaX~x=Bd9^Dz*2i4oVJA(aAL0ZBujFjhvwm z^%$vZsM32(tT5%HJIDjN=M>6o0e3C5@kN55?u!^8`--~4>SJ7v03aOJ@ohYRcZiXd z!NX_ur_WEovr6P40MK1S9i57+FoaUt`NaRhYl{^}PI)6#Im`XqgU^!AVPDykd zOLg8@t7C!RB>1PDtP4|QW$to~Dp9{CZ?TRm{ zXj;vlp!X=G0Kjh|q}017ON)9L2pG;e!KjI3;Yyr?iYv<4LWDA$4h?ha{{X1=cP|mreYPVYLjk3n*(SzTy z$F)uQ*3*?x6;)K^)u!3)XC*@d7bN^CqBMuR*5!qsh66E@dA$kMfS()6zI@FK?Mv5)%Lu zRXIy#l($Z%vm5zjCP-RLDi3L@PK~0KW8h%(PX&>q$tvws1f1|blkoD8L6v9^GF-1A5gH4Xyqh%1XLfd zXhqQv3Oo=oQYF^8_-mOxNdNM+T*!yZmM8kURAOgC!M>_zRkR_dH{^QO(H zp3=`_V}ak;Q=>?{fhJJ$eAwV0<jEM+6t0uX#b<|y4@TUTg+{7LbOLy;0IW5eRsoBE!6ms6_r8r^5E5^H|z@rSU zIa2Us8aV_coyV{=r6MARZo|bX+rX^9O5W<&75mZ~xvJ}229yG6rq>1B4Y=Zx?y|h( z0tG5h2GR19?M?Z27gZqA>IF_f5RgYoW@;ID9Gq^Z+w?~1CL%rTp{KgzizexB82vzU=q7@WK{1W1n|jw0VDb|?O{YD;9bj5rEL zd-0Mzg#)SGtOZsz!9VN;5f^c?k5RG!iJx&-!dM{-F}aG(R*6`8dd<&qf3%yFFL3{xgj&S}Cpz^VI8xgcP$@DzJy zq=+w;-Z>rH!NzI=(_ok?zU~yA*=kt6zm|A{Gn2*u#yI}~y+ug~XU1tqj5R#9EkT$* z9|R5n<248Cch8p2Np22l+ViXyLvs*G8TY8STh!oq(=M#byB_rJ2=IDSdG@47oKy|e z(i1pT&j*_IChC{g>o#yXKVx30dh^DnV|(dX%m+Ox_Ul3JZ4xcu2fDUj>maLD*N|Gr z)Y_SnFy4-p0)OyATB{YbUbX&}7BlK<7ULgdny~)>5$=oicU7t!V%FhD-Z%nQsdj(( zgntMmKbqIXDPku@krd-MF%P2#&;2!BFFH3vy7+w*x3f5lPU-vGlZD)3k-!1h+>GQ^ zUC_QPbvBiIrrY%dseNfWB3tSwnC_zCL6N__qxBwY{`IU;Y5xEQI+e-*M@+zhz09(O zu1566uWc2q`gQHE<8-@%OxA?pteC)>2L4G$^ge1C?oZwuX~7&1^fj?~S51ol0K@k! zcL=ycaP70BC}K%uJ)53~gI5!-x=!lW-sKw7DPpymrH*J@cG%<_)Zlkg4N<ocNg;>kQlq?(f7NNk&_{BI`Ij4j>OLZ+^qo@kM3NFE4Fu(k67#Y76 zX_7=PZ)S8LxLDt67X2HFgLJK4SQ)If5Xh{dNsw{}fd2qbV^NZZWe{8*hxc;-0Ih49 zMD{Yw`i7jFU62c#UX6t$WPFG?sM@hl4P!@ZNg3kHMZx=KnnVIKRk@*(Co1CxwOf0L zr-@!R$TYL0YWjwie+}K7#wnvY2f_CYJcHy{Njev;$RbX&wIn?OPDJBN_4q1V|;p;EvU*N)IG* zJRT{dhukJ zK)%}8CMhz+?I<>!oYaQ1ayX_ZT}bhC&aC+V0PHz(2Y%Grf9#+9CZ)81%c@!MGv=rt zQ%z5TgZ}`n9Xl)8Sk$f5F_|Z|`HF(aI2owl;K*g@-8p^XC%3t&UsEI3LG)osS^ogS z!~Xz=zokg)u1AZtCLO1j^)=`eh`1!E`ukAn5Gcotk_e{lmF#OX#^-1l=RMEToZ;<# z0?6U8e)vAwr}?Vn=^{P|Jdwy0$JFhn`~=I9m$(FH`BV&=Xvrg(NPtz{NS!eds971Pb8A0?fi8a9hE|P0+qUs8#|a)B!I~9!Mg>rH+UKMBBLIj z>R9f~kVzShqZ?N%%P;pwu@xI6fJ&;wbMDrYVPwr<^2Cfve`(WzPXtngy)Pu!#jT*0 zSp%}9QD^(P;Cp!@pWg=qKEKnO6&S@kM8ZRbEH`mh6X3R&E%(GY7*FZFt-R9@W?-8@ zKTc|;bq=$6(ccm7uC%m@Ye=pZa}XPq9#BK5C$<<=Y^@w~wmk-Z8@v8gEPk2T7TJ5!Y|{Rx+2DPRUT z-PnriJ)gt|)~w>VwN!I`F6*ezCOyX)u5a}=n{Otes4_@IkxwqiAJ6li{?tpfa3YaN z&woas`#zR2>Ew0jkAzcANQ(#`fnyxjWKDH8700)|%00g@@%bfkEsX`}TJVEn_es6kg56c9!! zu8uoWuzka|BRUXIA93txNSuchrYbZs92&g+acr^v%-;?q+(~^>>x1Kmswyh{b@1E! zFZ?YzCpwky{{T%?CvTc_AtbNJ3aDrZt8H`u{{ZK1Pvapqu&maVu;kJ;Ypul!2M3xA z2F@`;q;AImQE1>+Nv{f3j>m}FY_Y(t#_aZ`k3m2r`K<(C14ZVP z3O#75DF&Qy$|6Q{$xt{RL8OqME@*AUTS_oH3MOgvMWgnV_RVd1e=N>UF~%`RtZrmT zjt^>T88T^3Ifw@w40Byi?Jp%;gCTRf)KkvWRVH8<;CMA<{uy!zu@zPk z$S&kDsoIPy)u{~QQJJEQ>_%LQsh4^s&75e)J*ph9zD0CfrtD*GoU~pXh*TE$1XTsr z^_Q0E@aJdc$J@xOIq>JIXAlS`B!C7zw)m-yQaPU48@im4PxXsOdq3RZG-NX%srJSe zi4bxC>?z0UERVNuDk+t1)V7j5u`yh)YE#kmOF8n&+nXdGrYe-_CnTw?+Tz~l+joh9 zAJ(LJOhyje(8(;5$f^bc(Ky~WP{=?egF{6!#Xfk;8jT~ZR9R2A?40v}dsB`wOu{Fp z8=y;d0OOiz$uVi7e*wGGv8O>EB*r^~Oxv|q?iI5U$IMd};_uLva`?fey&VgqzBw*x z9O{epMRFe;@mgqoX&t;#q>r4cklytoZKP-eD650$_fqM?NRupjinw;Lui(M*1tHv8 zq`_FOM{`B=ZAbAjrW=M%D4O2>9{9w~kl7-kHn3yrD=A1W5_yO5uQ;gVR?)3xcOZ?} zIS1OH-FDaTS1?MMObiqM0Dq-Ty;XQ4xMGY)I3#!mqOE?)S+pqKiDIRO;Z_?`!)9B9 z#cUcZlLWVEB=#TK+I}K{hWARlwg41cqP)kPZ^xR6`iL}FGWw`jKbc7EdsS)HH9P3< zL#(9?O~DLu2=*eZhfVcfpVS(3Hu|0t>t+(;vdOo@`&E&xS`e}iX-`qyRj8@8eapGi zxbD9%g+^0qwvlP`TgaqIgM*Iw<06qX$fQTNidF#=a0fi|PEA`y2KIQ^5Mw-U9FM=y z)L*RI-P}MThEhm!*aoEI*uwzhcO=xOnykDYwI^R9!Dud*F1grGzC}dOtHmi;2NI#~ zf0<1?v`eY(EX|C~y-Mdf!TD+G-31-Vvz8b6(E;7$iYR#EBuIPkX`?>gq;;p~MRc?8 ziP?{&$+&xSR-(mi?WBnu4jQ2DoYf_>g)H3(BM47!)N1m3)t?@#e8&mzRe8jc%5r{H zTDgiz~d zX(gFf%G~WU#7(Jau{Wt4+1o5A>~$%T|e`!1Sg5j^7o8 zAf9oC$86Na)0&AFGDO^!Y?D#Om1!Nc5oDB7cRBZ|GeXn%I=(q}$@^3-$y2ok+>)K}D9E za~gI@c8MBc{*=>=fC}fG**|Ik#AS_{Pm@Q+O*obnk-=ktw5vVKvXG6EO*L<$Boe*x zLB%rLE0=82O!}-plOuL1bwi#iX4=+8e_?V5e08eJ*LHLMF42{o=PFckIr3@2qv`Eu z8%fwXIs1x{14D6nzDU6U8V=Oj-AghT8%}YGn=`kRsg4I)(@pe((IO~ti|vu|G|$!* zKXxb?0kCo^IMO4G%I@KdNg&#M4ZhVU>k&w$AznfdLH5NIvC+`GNN@t5m2v*GtZo(~ zlh&U>I!9{RKJg}>*4FXDfs?xo)7BZ9Rb^h}Q5!8Wnk80laZgJ-0;DMMQ0~IBi`%Gq z%VmW%t!!nBxFd0=1+B4FBpyXL#iWc^9`tD}+j$<;fs-{}n*RWPaz$%zxDTZTbtxlU_|lMeWE=D72t7L}rmDjZ>Z9YE_ZK#?9<`sM`Bg8=L42IYlO{ zmT<`Ah3Q9R$Oq>Y9qSjS3zZ=Kl>64}sk?vy$cShE-n_Y9mAC|W|pZvpR_&y2aiqk~V zNCr)fw+A4KEqkQR8YG(t`MKt!zjeIT$xDS4Usk^x04#fXAMJ{RwJk-1GiQ$n6zbJ( zm2Ol!ay$;z80#Z=4l#~S+IETnsxG^H!WRg6T8VWF#%akT9GdkYUeB3p)O=Tz?r$BZ zkeBaWmFbv-y;;-I9(U?dZTjM*Zl`9t>dvr`k%bqCr1{+-T4(eh&G8GQ)Zh_%Pu~MH zzV8LV>N}Yf?=m}v{{S@As!z@Pd?Hc)X8!>3Unnk1CYK2VCFcJCqd)6Gd|Q`q!7iiT zz`H@FKtEXvR~|HofAz(jYDf~?#D^XJW&*my@v3>#;MB=8hmvh_&OORIh~h0=$?01d zX6oGr7Ao8CV9M_9cV??hxwwDvkI)L;d=TpggUgegtj>NQb5_^mp1pCTd{4f#iYTtE zj+bEt-HhDDaDp&!!^3+xYdd>GrX?oq>i*(nTBip3Y*-n_6(ngRk4cIX7M+_-z z_KVf6hsFM;e^fK1utl*)AS6mC_e<;JP52Mg`lJ!6+&-^sZoZ%ntc3i^LGGrH1gn5a z_LVXZQYw5}7<5fNKJFcEUfLH%_EtjuGuH>vhcvvl+8wRmdweMd}jwf5D5zl1Hm?u_0 zkg4sD2gONUSJE1fQcJFD8c333Wheahn$Ny_RrgRoG-KRS^4z7(tC0}g2;2eS{6$Sz z=(jpfxen{nw*FZVGjdQ9?my$y@laNmtDAH9dyE*fjl^y%^!lv@s_F5<%Oq|J$;bo! z)cF*Z4v(u$>ap2QSmOg>9r^Q8J&#Lk>uh7ZwkvJC{{T2I8-NZ}R6I>Auo#{qzzla{S6JoWgFIVZCh@&&xqc8(5xa1FdjOr>_UM9l|oV2~S zx{G{Gp2T+)x20;g`d*<0<)o%Lp=_&vxFg6uMRb>ZF^*`PAoyYBSb0-Yx^ANOl3?V<$J$@&Dv#pd3ES&-nO(8nMn82g z{+9SxT@(`S&-bWU*I+(JnvS|JtF+#x(|;2J2&YUf%pJ-x@;%h}H7AXy`LHrSPHR<; zRFXAxY^fOryghwub7^xd6U5QU8QSQ38c;@vfTKTpB{(2(bA!*C%&`rvw}Fx|M*TeG z6{FN3Dx@6JLL(E~^zBT(xq-fo96u~ zwD|I5{{RWA4wda{wnQF$^uhS%f%r(d=^Za0{;n~TPhO(95ZuIkY$xt%rSPOF={++Z zEt3FyihS#lM{#h0vBv<>Ex+O7{{RBholTehs=q7_Jn3`znr$<}=@h^c`*Zy%GRExN zU9e^OTLjUw6p=hpwhE~@B-WSF?YA<2I`=v5Y00N4<&m)RufXTy#T(W?13j{d5m_DA z1D;WAU~M5xHQguZR?MSII9+llBC{Pi+EmkxZVo-;*>1!8t&358Fn_%9x{Xyz;~wI z#e`E|e2Ahz!GR+rj}%VY2y8CeX?01nF)b8tCSxIwI3#!W6(s0zO>?SRM4)bvfQ{cf z`)>CX*d59PbroTli&G?#H?g#l)DM?EaZVqHTE?^g01|3e_L_SvvfE0nD`RA8-cPtV zs{8RpKl=33qcZ;h5AZRo@IO9F5KodbR@+wT>!>x0i>(|?wrV{Ki2>LoWFIpEI|`-$ z01^`B(oGsQx--s&(n&}KSh2t(^x~OZaKQd_9vGGjpAe+66kjsjrp`%IwDQ@` zF^Y|>bqoCuRfcFTPQfCu*w_Rq=QX9yp>K6}buz|K$nPOgat7m`51KWsse(&pXoBPt z>PMPuFfmFDi?L5*NlIc^OGS>Rfi-^-F z`{TGZ&-=KUC1~9?vK%sd5lD`htN#G;m*GY17xK>tR^&2FgN=k_XC6MaLY-t*WRY;` zkiwy^?MyB(cOwj=dWxCT?~?Y}WdJGY>70~q>S+$*5Wu)zKAC!6+f_+c3ZV~0}I6X?eo1XV4;tH0NckJ+E$ zNcPk<8l*tvQ@M{TfsO@Hv;m7-kWNqEE`R;QKqwS!DDWt->}cwOQzDzys8*;*KWbBl z1>2fUG{`#XIdz#c9h7cc330^eAi` zW{bHSh^DXBgwO=w0645U{tUlr$=yQiKZlpk$xY8uOU4OS`5JGjA*k?fJJ2w|@*E0U zx3HIREQF{$;*U$&THMaSM;kUzP%2{RYb!tAc82OL(KmXxa`Z)>r!YEu0GZ;LeG$^} zUPlTddvbeoSBFB-qOd4|F}M9sy)(SI5MV2NKy>Y2Ni;n+4Ff@f+bGg(-opTbSPbT( zNc211DkY7{U=)wP)}dWu#(O!WD5OU>b*_Wz7O>7R*ablU09vknL!-z8kt_c>c|MQSC-4CX_ny>_sZWYDLqw!=DGi6`Pn{E&>7akTFo(^7*Xct`)BQ!Hvag zG`+Br?&SJ_kVwb=TJ+I`h2z<|a(_^2N_b-1k%G%jJG72cPzGP|Q>2ib4#K7&y=gWn z7*zbLoBse2I!^0J7q@(ROysY)-BIq6k{bwRkHBRnt#8DQGf>nbYZk|*Il@G& z--NmYbJ??UN7f_dd{QprH)cRj^9qfcSs*3ROE2-L>OL#}l>%rQJ4trsl&0dtZ?#!n zBTbi15v!7R^11Ixn%_k0+FX$rSpIRoDWPrA%Dwj?6(L(K-PW3jRF^@3#B)*iHy&UF zFd)(rUZk-jB#Ox0!KO|8@C%h8LNl=BQ|itkEKMU2Sqa#F)XCH|r$338X61Ga8Y{YaV20^WjVn-;q6Xk_aZ+2#(S=}gt;17x!o^+|C2&;mDdRP} z{uD044~m49l)Y#7^FY@F3J0}F2zc%d1*h5*B!%); zj2i--M>?cL?#?IyYqApHc02=3O+!xy0n}x&k@u-aTmZ+60Yz=?mhMv9at;8Ztb}t& zL45I(A?PW&r)b7m!pKLYqk&Q#y@YTw?4_7=Nfd_802Dh!$j*7~P2NJstyb=}GdqwZ z$j3@Vn1s*ElY%J#&htP~h7X!Ea%56m`5mbT@diN0>xw$B6!zX6rg%J#XlGI*Bf^RX zDbTLa*w1P$BTm@~ibh*0zYw9Ra0WWm%0z_@=L5Yd$pT1@q=U^xdaaa^`jaf1amH#^ z{2M}frY^cRLm*IC6P#l-;wJXEH8rNnMBppr98^s-vNBF%Cvyxr>?q98T*Gf{(5dH^ z!NoJRD~rhHK^lC_!yt|^T?p4 z;IYO#ig)SO7i8~wI0R&UDR1y_+q04f@eL7OMo1miv9#k9)VX1W6$JMWEPG;6fCpNW zG^v46k%LkUK?0Je^`;(~5=e-^{$MIgvVaA_6%ipBtgBOW5;xDK9=3=w0@R=&0=(@M zQ3_8tWUtf;YsspQ?;MgkW|OXyX70n@nDWcBJol%S#lkv~nvbs-JeV9}okv!kJqh83 z1$8L&_V>+1I;JDs!16mOr(UCa@hY9bnvE}SB9?aCK5>pJQWQ0#Y1YiRJ*d{3VgE1LYy|%C zK0&B|tabZO!v&3o{I3}BDl!<{zDT96WLO}QMj!w)P|%JrWybgjh*=BFBv3Bmn@agZ6pR z1l>KQPV4ha)bW0zD9tc<3Qk?$8xDSWuD0<6F?cplyV?RTUUXcYyF|si0sJDlzwv)g zztlb`^?d%S5OqnFa@pZXQC5$vx)L6o_ypD;h>?W4^{LA!2PQKs3T$c}1+HsdPt{kS zft^6r8_)$XCG{uyh$q6YB-Nk&q2{-P;g*3JV6n@t&e(1;A%HChloB>#yvRVw^f@M! zn_4$Io`GQv!ZKQcBcfoP(FE9kI_ICl-j&jIUb@h%giOyh!hjh06#eSxZzAjce^Tjr zWU%or(g!~<29=1%uqi5_9OQM+OpH{{r+ulWwJCzu;_bz%sf_K|GD#u) z!lP-ar{V6Aq5Mneyu!lUU$u?iOE%8wQ5$cm2t1Vc9xA`B%06XihhSHrA&7f{kI#6$-O(lBJf+^x^+Rqf!o zF=3(@$zFS$dxPSVxwqb%Thk!b$HSWBN=3!Hf(x*9-GD}Wil`OpeDwy4Ev(NvCPeaury|R~NiNObz zbv@OGkZY*jFVq%&L8IGW+I*_)L&n|F*SebL_KVQ3g_}^|e=G{zlm0S03cg(tZ44R; zq%fi&neeE%6@1X*yNhss5r#sZxvw*Qrrc=PP{SlEy5ctoW?yuv{uAp`K2B8glkeJ% zt1|QAfsM#G$;AmIj8}v5@!GCc<`&5~#Ro1)$-p4upr47?OAkhB;Ril}Rvz1qDtX9# z+#W{*?NzJe9h{HSH?1481Y~Ce`IH`1(<{P7q~vwj-=$nUDv`dwrlXt>yhZ;2P^X8( zNs4stn;AP#pq?sC)TBkZOynw$6Y9+#?T6voL9-Y>!?CIA3+29<-(g*(t0^6^ zLu$amANWN+*X$&RT)cL{8`zQv?rBZZA{1=M!Om$W@k`mt6nw=ED6UoHDyNn6&oq~C zz(z(1V0ggpY3ZmqK@PtH4McrKu0zw7HnZH@w3%|aPQbYCGwnqq)-=smPr8vxY?2S* z_Z~A(E~K%w)FVhIht-MHtmrsDLcYf}2ia&Eu7^CledFhp4A7dr_Vc*@)*>fbB0_t;aASzt*{J#!7)!|CE%JpjwO!+`=XkciD!2|hsaWg-!%BrdTURg zqqS@6+cPT1a}){??PVoN+$s?*bq1KN6k(0KG;TcYLPbv97pqxnx()5SPLLwc6wIH_ z>^@w5X{=7KCI|tF=LB`Fe^pDHdjRpfnB$r-%%tuBF!c4LrucQ#noml@t;-Unvi>~_@~_^t56 zR_I-Ep^&uJQ?oUt(Cs1)>fX{VRW5*z@<{XX9}!#M+5Z5Fqtvwc;FKy%gP`CrBX=JV z4NE@_`tB`K%08CXu2*SNnsv(zl>Y$cEKiSWtA7}J7U!q6Sl?m!*XPAG(TlKfdlAnh zkEk_t^lg7l>zx6#O=;s@Rum%6>&(1xt@RYXeArqe(DDzV^{X}Znznb1dk7*Y;&fm7 zfcRH1c4Xk1B{JnmK56Z*X%gwT^TOPPa;yhCSR8*!XipoEN%2*OMn@_}2sI%7@2?+- ztCR6A1dH}+_(lL+NppDr0I0|{Kmj1)uMb^atp5PBzrzTI58>}`k-5nQveih~5Y)VY zf&ui+QS^lZ-h6cX)c*kWn#CQrY!VF;#~BnNk_{kg!YM(Q28Ff+Ir{NfR@^C43wBu! zXzA9KRXc?ah;fgt4te15LWC+-hROim^yjrZ3rWctX>b?sPgy!~{{Rjg5;6h%QZAcy z6c=HbXAM)VYkPcE;fH#J`Iok8I#S#CHGj}Fs~fv{non)RU?}bJs_NQ&%O)GJ^GXm{ zPa;gHy^#K*t*)8y>iX_4S-wSlaBykn-w)!qj!#81nAn1UH6Ua_d1|pk;Q848?G6o9 z&YbBP^#%&Dkm=s8mq~mnvv{Oipbp`Jw71Y&5P;kh2oJ&Jb5SaAIFFV!V*6S$m1 za*ZkOG7oM=I&H7um<`wjimc5nj@#I0G_~c;#Dq%78!L=~MlPd-ge$=#6v4T*mTgKB z$Tp$JH2t)SMw64kZYjZcrXvim-kGd{8yTob?-tqimdPND`evH9kVeX$m;>MLD;5^p zOGtZwX>{5@B>3}3W41uJAI+0Vm-cZ@P1YgW8#I+~6n7E{8GO{1mNBd`xL*S_-L$p9 zP%25&pxiKd6vAmLsj1!L1TosZsWC0l5c7gX7Pe3yBeNc9Qt%X?U>(gAiFUf@k(zCu zDiK_?WRvd<(JSj{TICetm0++|g@U%;{8B!+>l>q%+E=&MkQ-Q-PZ&YVWAvkic2SCW zkX+4g8Ak2j;ZK`QIY}V$*#eE-*hv-2gf$xY-di;FZV!~;92%1Q(imTy5V_4vy$=K1ST>!g=HpJ2m5U!V4gL6! zf$p^Zo2HV?I6xjeW;Y&1EojFDzv=m-Ztr93pt8*^$T4UNh2)AOkG18*A2pgeEcha#9dP0ERd zvk(MbjXB@GJ`YN{rSIOf@XQU|1n7zBsLAt0W9;IY-4-_c zFmgyHoU+{yPilDYNHa=WGJH|R0V5~9BR|fLhF)29YvUJi3M( z3xycL`IwQ=%h~Rra!4SY40a#< zngMPZ^V*PWHEDPC6)3^f@JVv82^aH>pBXfjtzKKraTz;yq1teJ=gm~xTf38~goijz zNff=P-Q7ry^AG}#Gv=he;ub-M?Ope1)$%DzT7o-Ei6w!R!-JppsKWMWnOiPhiT?ok zibT~l$)uYE;AAd-w2m*-Z!SsC1;6c6al*=@CnlpNnKu!hm8)AVyx1$0I5g|I*8z!D z8HUvusQT{xqzV&^^MgX~Mz&B+4K7zW%|m(NON1i>npeHnWib>|dFLK8Q5Egf(n`VG zB#!jqzgf`%KmcLq$J(2T3^6H{<@ti-QE)3T*RL)oltyx@ypnhrqzU7>MPd}wHtyZt z;FcJvzB}7Hn@4@56ZC0evdvn;4=oDMy;yDnnKL0=3|FX~$!}DX&TG}x zm`K1m7^ynSJ#yPshFw0{mRXqQ0&tTzou69hKf|u0>8(#nyNdShwEOE>qMmzM0p5bu zdu=sAG_4y`n@Rj_mG0$>G6)rkk~WXZ`(mXHCJWA@fVESJ~bnclYsfOcCu+;Z4V0U`>Q0qvzl35%8Ha1lDBaZ(7 z8qPHj4p~@fc5010^QO|9=3^gD8Z`tiDy8b*6h0(st1?TjPLVXM3frKJ;hTlXs|WF+ zHheAkTWfQfFf|#l?Y|_lrB}a&8e|&BUv$-kgM2ezL+U5GhRzLGAKD*Mu`SX%d;o^E zvAiyWvKj7KfE5trvZiv_a87x^!4;?_wUw^1Z3VrwHsD7iVl)x%Cmx?8Mt^1qp@Xb0 z?v^YChE>Xp0qMl@RV-K<;$j=0Qg;5X^>_aOXL~~huUP7?aFA%1=&RojAS_K(zL>Rp zjb}-KAj{obuRiR;j0R-`AHbvYG%(7s-0Jg($ypOW4UvlIXYDg$VCc_>c5+7s??O;q z0vL$Y4Yf&hUYhEg%ci~4r)c#HI2uTA1LJZ;yNovj`PG2os_OpL*TMRarR)Y*@S1nb zJdaR{M(A`%EZvp>%Rn^0JTKs<9kGyNY-XJ4$Yi(N-SYe&Qb?*+rK!G|rCX#y7@ysp z>ygG4vO9y0MNishfvNQ#ho>8uk~@owB)RSa?kWlN^X*l)TIdrL#D&QYeNR=H zrY@Malof>7=@$S<eM+=c*C z?+bo8pM+Y>c z9PI0k+eq`?q%m2;MTW>Z0*uDeC?#qR__8z6I;#wilw^I_RM9KQjHaP4iS7?XYX@*D zV_YAu;gL-4{{Z1<{{X{p(yZPbQZ?;0xc>l(i~gZbFNZd9j-Ih_p*KXiAXD~eQrhK! za(9qPJ6<0k;CcOQB# zo|Nk*9zfD5`9b#ZC@!p0VJe)q^4t;aj>ee!R;?U5d@C%$8DuN|xa8Dpuo4h@VzgUp zSC+*kPkVL%9YCpX;n!H{`X0SEPikPr2B~lg-7|oSF_2p{pYa~RTI=@nq~hWWm|eX< zGZ@2QVxu0R(=GKSVIgHZk zvfV0f(??0~BfhudQyE*R&Q5YTbpE2B7P_M8+JU+B+~yf#DdR4<$sS0}Mne6I%Daet zz;NE(vMFVxY3DS0IMvPXujzstd`dcJkMyv@jmmpkb6CJjt2r0k3I8M+xX=3cQH96Fg2SblGr1FLj*Qrv0xidhHG49YN*#CtgU`-*7V$0Tw`EE4Tx!=nR+R#To0b?f5| zuR--MO-pNe)EaG-?V&PSPb}yRPBQdB{Iqg@~6l&{@EmT z1fc|V;=Nnp&l6eS*na+4#Haw1BmmxwK6O3oHV3NotE;$-NvXpg`QRLWAw0VMO;g=V zOS!cQ>~8kJMDRYu9!*w|4S|oCI&p8i3ziW|1}Cx6!X-xQ-n!V0m5DoP)>erJ?DfzxEP(pjz3D5D%277e zFpwS%O832CE$>a~`Xuav*3M}rgd*X$%lV5MV>Fs_ul6p->T0oaqs#TByPE%^QnSmjEgtIq;&R>QzE#-mRdDSM3`U_NPoD zLBmFWE;*zrHCx96=fDFP98pD{>pV3X8wQ>3MLcBFsyj(p3vOHk7li0gj z354K~KxM`aBDrmrIvG%S-utg3)x zzIP85K>8l;+AT|D;1zX0H}_3+v*FG4z4`P>E$QF}X35*ypzg^E$FQxt!M4`o!^~C% z-ND z8#xg&&9tpSbzQ@~Zng`DN-?6^-|s>|VUBzne10BCZ+3y0-^f0F>Nl~vzO=NR@K~VX zK%|bF)isOFOeqXe80XFpwF^Td2^%Yg6|Mc&c_NZc$Q2U@H8E=zHh?BPo)nxTx@^L)NOv3th>Det9C6b!+$_w`16WQN5n7WWB&Yl#G2rr+%X~ zywL6-V2txfnm(BUzK-B`18Mrx=)x>bkaJdhMYf8{QzAC(AI7D-C?_#)zy_QNaOkQR z&vQaJbhjHgJ}Ej044aNQUiA!4a%(wu^LH@=8KuJ^lMY7ga787^P&gwj2Q+Hbw2kud zk(^Q$(V7Vu;O!=g2RNi*k1`eLaloUxtY3v66^Y;6uI2=1sT4J|U`QVw>BHzo%i6Yv1x2Hjbd2MgqRla9$TY{FMv6&S34#tm zraq&jrM!gf;Q19d(Kok^&&)GJv6PGwYEs)&o+cS$R1TG2g_X_55dhe8oYZHmXg3zK z62h&8&YFM{gB1>S9i8i`@&N2<>=L+>9R+9_KC;hpp;=WAP{AYi9}xF(ljmL)@kq>IV$ z;HcnJ!b@GSjia!p9mZt1^!$)>OaTPd4%EjajKiSoMK3kcWJq*bpnuO9>~rnxY9ZF3 z(~xH0eApNPXY7OpF3lRAj=mCixn;8dS1rI?(2BU63hBhDGIpUnKNU3ai~+Qe{v6=jCOibxJlz$xn_k~4)IEiPK=3ag#i=QW6}8s(xzQb9Z#f7@wup~E5V zNi$$n4c+R*fkTBo#WrQO;11veNG)x$MmWGVEXQI?VTMH{U)o0#9(klg)I=JH-?KT$ zsG926)g@Ja^bMwpfx;2sWYni^Z4;*=kH>0_yJ*EL=8!Q`t*g2rL69mudvO{vqKpb- zPbJ8l#uw%DQ!LhaE%fh9Jwnw&mZf8Qkg&T#$0K%VgcGVLQ-w9Dxdul0siQc>+A)4H z*cy+uzNNQ;hovS<5~7`?CC&v}q0@}g4Y?(TPaP^yHyOAD0k)x@vvi(05jkvt27Rfg zeb*}*Myd%sb~vPML#Uw;8;2u4*}>+Y|`;k`rXn+m8U>drj zl~a}L+NHe%Sh>GxmE06xpK&|_Y3HV*8_Bk|;=kGtV^wQxj#`we}0MbyT_!h&Q3Y^sM_Ui#>UT{KU!+fc@j)^w;t6tV~lcYnSHAzuQC+_ zIO|VsQ&O`@eo#0$9gRj8+L|^AJ&7mS(OF~@O(89X?@cS^-@wlTlP&33SBQK=bs%<& z3Yj1eTvPhrSB732IZsXd(g2>rpPWZ2<2+^(xZuCy+qlVm( z%NlQsfe|EfT8T+;)9%UbT~QM1B*Z~t&4L%vEy@K%-M9>0KRT$gny-6PuE$l60{{Ylbvs+#N0B;dptpg50O0IoJqg-0uM|SeZ zC!&iCsh^ze7!E-9tG%bZcik(dO!n-Ns(LZIa2T<{4r^7ngsL<|mD|8Rpx2PK$3(w_ zQ;+wee0h=o01osRu6ycw7NwYCyqe_Q`dgriKuc}>*$3O&j#z8jw0dN)J=@(vK?+oo z@PWz5?iAI@>isWByRwRVyO`}RtZmutCIbrl4h($$V0%>^(yt`2)%44#pVBi(cjd4E zCj=b$sHv^|iPsE3ZVAqKI2Cu&wIQnM&RzgoK0*}$Zy9f7 zI~uzG01Yn&jqpRPZymOqyF1uZK3-Nxz^d)=%GxW=x#{Q(e7*D-Zx~aWm+mAMp8+)3 z{Yd`+j@e)jCwr4j4}&%nU;IVTqlRBegpNdtGEjs#AR0-KBO%XJQfoc2o=LRt5We63 za_v(bXKwp>4M0vB*bTIkUI0~+pz53>)6%z>vTFtOlgoXMHhNn zGNR;=tmnVf`4v&D?ExT1kDg7Vza!~Klq+q)&tKN8J`!myZEs(0)slV7pFk?-d@lIs z4ds=tfz?+Q-n{9y!&qaBd!Tsq=lKe=NceTr<4Dym zC$){Ia|RUhgqc(Z+IS2->u-q@$NvBo>dJ@$tgNc1{3nW9)+UAAXNKn$UoWIwYX(~= zSv{6VUIOH8IZ!@z6i+mfk1U`OfIL*Y)1eNJ5d>hf{m(TEz0#Xm6DyjT`gS<~0CZXn z+<_tU$vw&!r8A04*_3cV9MoA%Z z1`R*OQKURKGl_L+&s5MOO74%d6i10Exd^AUI=_fPMScw+aRr z4DovP2MMum>zAJ`DQU{rUn$r9Vn&k*caYhw+c2AE8Mf_v5LNVss(#&XEr zfyYzUnb$W;>j4g|3{H!%sPYR>h~!F?mAG&@OF{_b0;+TjpL zp-{8{F{;xyPTWgulUdtJ>OeTbVsbOaDh74C5<6@_NEr*yO1*ey=flsWT1RhnJdj0{ zjpp`F2LN{Cu%a<*w@}KmLd7Ij46Z*gU~&ldHD)aSGyHtk?jp0X)-@TXlmL<2LZRCp zcobu%J|5a$XmG5gX}52-bh@}~#8CXN1gqUye=?f49T9i%&!M%SSNH5UZq}h5=ZuLn z$VDB16!=-(7|D50yOmJC)YENC#CitJk=m`q=^;R@o5K2>jPX?pFM>ZDHJN6*xY5jV zO68=I?s(DNnDWis)Q1o3oAD}0R!gm4ON1P7BzX;9YwwM^6!$uR;B9a20$lEqW43nn zR1eAs9MaCI@kgnybbF6JTEfzG5khTHLXVJnlT^N`wCZYH!tM+Zw_V zeVwpv2ai|HQrj=tIek#KomR&n;6rQNkE@!Jtp5OIZh}}Y9!*bEx@e=2;7XC@kaply zxhGP5Qhp-o1&A2Y14(llk?rKub5E1wB+GWzgGjbnCY;D-m7Ripa4Ibh9uw{=(Dg0<08vKW zL-@!ou=h~Gc|1&5aCaf+!8Khk?Hb-+QCH+{f--fTQ?kzul z;n)Skf)0I=o|M~O=8gpUC=!8NgTd`bl?jM(RZ6@lqGD17C`7=z4C9_@J%Ix>DlrCz zxH0cig{<2lkpS*7NjFfGZ*Xf}IzuD}pO|>^Y0c?JG)$!P*m2sO?@}sY4d_2AZP>!z zx?tmx$T+L3@N)kCJxW+(aKm>dscocEM=??l2a+o4d@&6K`{4Osa6P;IYASJ%{{Sk} zJRS&;5s`;EtG_+Ip?fL`xeJ16?V$AKgljWAU^mi@XqSd{<{iMVdU&)=4Xc&!jEbbo zBM)b#dL3TJ_z00~rzc~kiiquat$F;+52P#Jy6#UYx zSd=u)-H{GjrRJV!Eu1u`+Uw6+clmVwB3Km3DI)F?_4R~&OptM(B{OJIs#CLrKczMV59 zg%`C)msZTsj`$Si&|*jwt8%BFX$MiABE|_Sa78LXbUz3rL6eTu`S%#{*qXM^C3`@) z_Fbx7xtcb&jH&#*3{pLsB-6ed1cQ~P{*`iP8(TO(=xKOc7%q1VgNlnQw<4)60E5ho zwi}#L39jU}l}J&L!+lnG4GJnza79u2R<-KQ2o{gFgESr~F6zxC$I2;Z z6{%X{fYFiJSP*J9xao^?D0LY36btEb+DE(&!lc|$Nnl9^4FTQ5X>ru(QOiZ%dXR3oj!>LXwP22BwkFN{^&Ou0$s9>&$pM_Q(< z3zZ$o@lpP#_2dbUz2F@iWNQN^|WwcV|%Ugez?Ld@eWj{(o~0q@*WgtqtJ zy&!=tz=)=IgTX#9M;z32imkz1V>J_V3^K0Aj3WTVl6W9`RI?_g?)XL-Bh3~vT}-)O z(2Dh~h06pXaZdQ)0w9161w}Dc=qimYmhg}eDKw94^0KgH$x*?hR`5#kIC1tKXzVau zD!JRhG@`8dRoH8p-eLM!Kiv0>7>@D8`!GJkSpCyd;_dexF8Tn`kFjo{AXxA&$;^5zi1Mt9jamb^T^F2Y4;PfWkDr(k@^a7SY8OO zCvZVkQb6Mw9w>@hM0ABJO0da3?MJ#_OP#I^jTw?89E0O`nlyzrIW(Eh27Ng+oR>4} z_o}X#Zo?c5)6{gqirhN`xHk!mnt$oq7M*E!Tt*OnZu!Zn3i<7zwr6mqf$rbpsEKay z%CUkM(xcgkDhD-It~Cp_xBMbSft`nr#*+0L2Z9&dfDdC+Ou9h4GPGzxJc0)Rdx~ve z=&uAN3vTBCkC=O&DcW2nKpc9C2@eb^rQbEkn2vZ9)wwb;#ZCH+qzQIamjJ2by)S|zJ>O{Gg0zQl z+*_9wyI~hii9U*{;}XnhW8y!bF6;u)i0%3wDw73!TB7I%Iq7u)kx^R zwY=%QQ7+?xDX^@#ah@C6r?b|!x~2WC)u-?-;zQ^ZOcVg`E9^ySHWv`ii-|vY2eb+0 zv-;K%;ypI`B$_m}U%N67Ew=f#;j3l(2002xM$3WkjgzmpHJ=(J{1$o)Ecg#(^lFfsIg6BBA0=N z9fFOjSKL(P`#HEziuyQp;v|{R&?4rLI*X$(=U5)~Q)RQV{_=>8(BR++JQ45WjC4m( zP14;)Z*@qb6Gx}r$8B*51ui6&eIy@n#+lw)mRBI;?Ai~n9sLa<6~(l+j~%*3rblNe z4@M^>uc-KS6^XT9-+gq41Tn=w-KH(&14=hgf63H4oOgmGoHMGOwWw6 z#P?bpD#aGtM6~r2&g0HMTCVyc2h?no05ah~@I2Iu@djBRT$FFi#bs>|Cpatbj}*@7 zi*`D+0hb((dx}LX+Hi%Qg;u*Mm|ig753aXI>pH zCT2M!5BZg->Ft0BzU}ijeky9wjx@Vq0URE~#(dO9(XzUdc-@+pH2G0&AO%Amyqb`J zdq%C=!xp!Qb@ua1gL5K`bDrx*0>1SlBfkTVX&g)y7oG{{KJ>W>X(8SS1RM@IH2$cv zhEbl`HS2^DMx`^5Is4UF_{Apfm6P1d5}bVvS*Mi~c3Yg)T=>Y0I%Sx4{6tx(y+{5A z=6qY#|$BG<~ z?ihTh$f6-)SuzjIc{u+7tuIXwdiqpr)%y9-?yRM7N=T)5;BeXV?M(ecUD2MBXqENt(trMI3jEK^%B!SH_dTy6R%PO+N{bs~uX`9UFHo;M1IoZJWY zLXrMIX%bGO;5H@LmK{2Pmu8`2~YWf-d83dC3RGF`qd&J*wNKG-VXJ zU>OEIM>JL)TH+}phkvT4Adbvv#;4R8yz+~21*^qnZ6n&V<(Zd_!;Dh~=JD;N7UIbf z;~R@-aUxm?i{x==mu~Ep&QZdWFZgY}Yb){z0qqA8S0Emhb zK%o?H%-t{rUrvGOUX_;LNSgaiOQ|HWmPt(H%eaTYCvmG8qG`G{wznaJOR|AOz^W46 zR4E|#!1GMLgH)09n8N}WO_zc=$TcWvfj@jm?%$GS2P1*<)Xa*CvhmVB)#eE=@2Auw z-7}SIh8Sif3^&KH%}G++6RqeVKER)ea0kB3QQog?^!3nr4%4s(@A;e#X$A>U^(Cx% zKP9~ExySPmDSxU|4J+m+=eoD!ALA8NY%R^N)Bd7sY_*8Xrs@nmS$_lqnR?C4Hj=g@ zETjNik&OAK4vTj?SWL*y-lwX;i0pSB!1<{cs$oejrBNmc1dYqvnuYXHa}YN2F!>-P za4=D_a6ej^wg~ow_sGs_LF^_=@xj__yagk6!YX(^*FqCt)T+yxkhQdbAXWoEVLi0FQlZbU}s9mh1Dk&whu z=<-e|Z$}S<`WoztIgFlhS%Om(nHe7SBWZ6Fx!k}5@7kj$jgn3dMrusat)gA5&9r$G zM&M?rbg0@}fgT6eq@TiAB(S&uzR|nuR@b1kc%`)s6l_?w0`A6FzC}}M0;Zsm=jGZk z!;zZ1{{Rl{rQZpNG;WKzm&QDiQL;JOPJ36NG&^rD8>RBqcCh?v`t;tKVABvfWwH6G z(y6(2vX3H?^o!y6e0TXMoHI}Oi2yypAXOpv7i`tJ1HSHh07V#!OpTj{2kB0WeYV7B zfl=CC-NrY26GX0ciCpr#SRTjCAkn)Xyi}vvT}*IX6{(Kq>In*ra4ACF)TZ3$*wiHk zsVlP%dsFJeRES1FIXL2)yey)jZnVi_i~tG6Ja1=66NAa`nvAaH^-Wh}#?$U9P$6jCbRw^-Zu44PA@&(EKs9AWui>3#L6At@ zOP5!$NfQ+#atdeJUvGk4&6UMO_Z>%NYpF4Nq+IaGTlA>3f#hS{ilo7%&vh$;33$h0 z)||K9RUMH*aK%;I0R2TUwa9Gst3vkDo%lE);M7Uh9}x5=4*~%*5ZK2cGWazHXBN*2d?XkPG2YI3zV#zLU1oq`36shy$FA3WvR#813X! z5igvVs10)R(%(}Z53BCsvwQjnnnir;9dBu%3gPj|_! zK%px*uK`NZCb3?v@mk`#g0(ae6g6sSD8ie1nJW=&XNrLJp+4iC+Z)=fvjD(?DGK9H zwsjeaNTk(p`KwlysHLk7(dMeeu$x;F*yJfS3|(AY$^<@^OS$L94PLvwCdO4N&I4Udgq#-w(%@)7?ocPatQBL>c^&|c11A(w4W6z!K6lz z7@7dPR&g=@2g5BA` z>`h(tod-~PR7oHR#-|DO4LO}4hE|!o_v4Qw(*A|2=@9D{sIx>QV&n6Ie=Twosdav* zvxaE~p>Pq7FdTvU0Z|5n*1DaaQfaU2zC`M|2a~%i=g&1~IyNKEoH}uVQ(EnwpQl6R zTwKYSP=z6K32r&BqNeK0INSqto&ER}iFMbyY?7Fuon4fT#2zb?x_4LVcNR^8LaEwv zeY>2~^G(;GiU?)(R|>`0XTCk^A@unZlg~Y>k7cK5Gd@EfDsOHjJj(L|W# zq&)CIq#Zx15^YhfmD?dkGgb4a{wL|z9eJfh_YlEu7U~J6oM8cF^4>W#Lqyb4>#c5D z(H+oj5=oq@vW`Ok0EgP0ea!7`%YY-uHF?vP8-XN26o{h(a`eq~TGB<5)GqI*+|+|- z07yoBij4Yx&B`Mj@G3{Rm(xw7#Z%<>h^((t1J5xdXWGf8)~w2r$VF3*t%h5fSrxIn zJespQ-S!c=Bzsj->dUQ6K*lJ646Rc3D%*!j)BGiGA~=Ti6sH?}{pt)Co|tx3`N+rGwaAndQb!3z6i}Cb>wL zBz&r?r%fiN^U7V)6?FjP1@p-RJ*p7C(dUZLIu<(=0)5YFo%$a@xH?O-BY^#eIVPqJ zBc^P`7Vyg$BuT!ku8E;p!vG5(ZYrmFst+ij9s1P9rK`bh5dac%Rbp+}cz(5|C4lDRp!R0s*ier9llv*9W~+4~kYWq>pQw zq;`61MvRLdA191sici%vYoQ0r4kRR;k=Rwtxap`CV*Zd)e2PW8(idP|nZP47Wxe)+ zrK9l#F5s_zwa$y4i(8R1H_H5h#Rs7DUA2tQB;Ygl86Acy=3nU$C?v1n0;648$r%r) zfwYg*RMKC_>$f-ttZ>~$FGT}A>bG?+hW7=K0zbLipRGf7wi8;-A#83313j_kty!=) zGdswK3OH6iDXnqS4?nEIHhJKFT9u061=>v>cq4WV-D<3AYO&4;W89XaaM=3t0>_6^ zc{MibeJd5T&eJJwGK=3Q>rvc#W!zTk=W>8g2aIFINh_-;!K$6coaRzlcPZx;5$gIq z%v*{?O6}m(8Fy)M>ai(`x4MS8XS35F6OJjOB+_pY$w8H*>j?25hP3Oeov>aiHzc9y zRb``f?kEb8dWm3;<&_f);-jX&$mD@yO`v%19vO5kVwrA~HILRu~}E&2Q9EYBx-`2(Q8z(152a-FFWJRPWI} zajEE+wpxAN<*lSqF57E~BOyH(V#Gg_f_v2@3_}7A2=XdJk6ugoB7*uAmP92|;JFN- z_&BS5rm4RoQUsadkGjD2HJ)mo8-dYLA}tSfTy8?6hD`DEtA%&ekwdQmr

Nw+(r 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