├── .editorconfig ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .vscode ├── extensions.json └── settings.json ├── .ws-context ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── apps ├── .gitkeep ├── astro-docs │ ├── .gitignore │ ├── .vscode │ │ ├── extensions.json │ │ └── launch.json │ ├── README.md │ ├── astro.config.mjs │ ├── ec.config.mjs │ ├── package.json │ ├── public │ │ ├── bump.jpg │ │ ├── cube │ │ │ ├── nx.png │ │ │ ├── ny.png │ │ │ ├── nz.png │ │ │ ├── px.png │ │ │ ├── py.png │ │ │ └── pz.png │ │ └── favicon.svg │ ├── src │ │ ├── assets │ │ │ ├── angular-three-dark.svg │ │ │ ├── angular-three.svg │ │ │ └── houston.webp │ │ ├── components │ │ │ ├── cannon │ │ │ │ ├── sample-debug.ts │ │ │ │ └── sample.ts │ │ │ ├── cursor │ │ │ │ └── cursor.ts │ │ │ ├── first-scene │ │ │ │ ├── first-scene.ts │ │ │ │ ├── scene-graph-step-five.ts │ │ │ │ ├── scene-graph-step-four.ts │ │ │ │ ├── scene-graph-step-one.ts │ │ │ │ ├── scene-graph-step-six.ts │ │ │ │ ├── scene-graph-step-three.ts │ │ │ │ ├── scene-graph-step-two.ts │ │ │ │ └── scenes.ts │ │ │ ├── hud │ │ │ │ └── hud.ts │ │ │ ├── lightformer │ │ │ │ └── lightformer.ts │ │ │ ├── postprocessing │ │ │ │ └── sample.ts │ │ │ ├── soba │ │ │ │ ├── abstractions │ │ │ │ │ ├── gradient-texture.ts │ │ │ │ │ └── grid.ts │ │ │ │ ├── canvas-options.ts │ │ │ │ ├── scene-graph.ts │ │ │ │ ├── scenes.ts │ │ │ │ ├── soba-content.ts │ │ │ │ ├── wrapper.astro │ │ │ │ └── wrapper.ts │ │ │ ├── template-outlet │ │ │ │ └── template-outlet.ts │ │ │ └── testing │ │ │ │ └── test-bed.ts │ │ ├── content │ │ │ ├── config.ts │ │ │ └── docs │ │ │ │ ├── blog │ │ │ │ ├── v2.mdx │ │ │ │ └── v3.mdx │ │ │ │ ├── cannon │ │ │ │ ├── bodies.mdx │ │ │ │ ├── constraints.mdx │ │ │ │ ├── debug.mdx │ │ │ │ ├── how-it-works.mdx │ │ │ │ ├── introduction.mdx │ │ │ │ └── physics.mdx │ │ │ │ ├── core │ │ │ │ ├── advanced │ │ │ │ │ ├── directives.mdx │ │ │ │ │ ├── performance.mdx │ │ │ │ │ ├── portals.mdx │ │ │ │ │ └── routed-scene.mdx │ │ │ │ ├── api │ │ │ │ │ ├── args.mdx │ │ │ │ │ ├── canvas.mdx │ │ │ │ │ ├── custom-renderer.mdx │ │ │ │ │ ├── primitive.mdx │ │ │ │ │ ├── raw-value.mdx │ │ │ │ │ └── store.mdx │ │ │ │ ├── getting-started │ │ │ │ │ ├── editor-setup.mdx │ │ │ │ │ ├── first-scene.mdx │ │ │ │ │ └── installation.mdx │ │ │ │ ├── migrate-v2.mdx │ │ │ │ ├── testing │ │ │ │ │ ├── advance.mdx │ │ │ │ │ ├── fire-event.mdx │ │ │ │ │ ├── introduction.mdx │ │ │ │ │ ├── test-bed.mdx │ │ │ │ │ └── to-graph.mdx │ │ │ │ └── utilities │ │ │ │ │ ├── before-render.mdx │ │ │ │ │ └── loader.mdx │ │ │ │ ├── index.mdx │ │ │ │ ├── postprocessing │ │ │ │ ├── effect-composer.mdx │ │ │ │ ├── how-it-works.mdx │ │ │ │ └── introduction.mdx │ │ │ │ └── soba │ │ │ │ └── introduction.mdx │ │ ├── env.d.ts │ │ └── tailwind.css │ ├── tailwind.config.mjs │ ├── tsconfig.app.json │ └── tsconfig.json ├── ionic-app │ ├── .gitignore │ ├── capacitor.config.ts │ ├── eslint.config.js │ ├── ionic.config.json │ ├── ios │ │ ├── .gitignore │ │ └── App │ │ │ ├── App.xcodeproj │ │ │ ├── project.pbxproj │ │ │ └── project.xcworkspace │ │ │ │ └── contents.xcworkspacedata │ │ │ ├── App.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ │ ├── App │ │ │ ├── AppDelegate.swift │ │ │ ├── Assets.xcassets │ │ │ │ ├── AppIcon.appiconset │ │ │ │ │ ├── AppIcon-512@2x.png │ │ │ │ │ └── Contents.json │ │ │ │ ├── Contents.json │ │ │ │ └── Splash.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ ├── splash-2732x2732-1.png │ │ │ │ │ ├── splash-2732x2732-2.png │ │ │ │ │ └── splash-2732x2732.png │ │ │ ├── Base.lproj │ │ │ │ ├── LaunchScreen.storyboard │ │ │ │ └── Main.storyboard │ │ │ └── Info.plist │ │ │ ├── Podfile │ │ │ └── Podfile.lock │ ├── package.json │ ├── pnpm-lock.yaml │ ├── project.json │ ├── public │ │ └── favicon.ico │ ├── src │ │ ├── app │ │ │ ├── app.component.ts │ │ │ ├── app.config.ts │ │ │ ├── app.routes.ts │ │ │ └── home │ │ │ │ ├── experience.ts │ │ │ │ ├── home.page.ts │ │ │ │ └── home.routes.ts │ │ ├── assets │ │ │ ├── icon │ │ │ │ └── favicon.png │ │ │ └── shapes.svg │ │ ├── index.html │ │ ├── main.ts │ │ ├── styles.scss │ │ └── theme │ │ │ └── variables.scss │ ├── tsconfig.app.json │ ├── tsconfig.editor.json │ └── tsconfig.json └── kitchen-sink │ ├── eslint.config.js │ ├── project.json │ ├── public │ ├── 1200px-Starbucks_Logo_ab_2011.svg.png │ ├── 911-transformed.glb │ ├── Astronaut-transformed.glb │ ├── Beetle.glb │ ├── _redirects │ ├── angular.glb │ ├── bendy.glb │ ├── blender-threejs-journey-20k-hat-transformed.glb │ ├── blender-threejs-journey-20k-transformed.glb │ ├── bomb-gp.glb │ ├── bowl.glb │ ├── bunny-transformed.glb │ ├── bust-1-d.glb │ ├── bust-2-d.glb │ ├── bust-3-d.glb │ ├── bust-4-d.glb │ ├── bust-5-d.glb │ ├── coffee-transformed.glb │ ├── cup.glb │ ├── diamond.glb │ ├── dragon_chestplate.glb │ ├── drums-final.mp3 │ ├── earth.gltf │ ├── env │ │ └── skydiving │ │ │ ├── nx.png │ │ │ ├── ny.png │ │ │ ├── nz.png │ │ │ ├── px.png │ │ │ ├── py.png │ │ │ └── pz.png │ ├── favicon.ico │ ├── helvetiker_regular.typeface.json │ ├── magnet.glb │ ├── nx-cloud.glb │ ├── nx.glb │ ├── pingpong.glb │ ├── pink-d.glb │ ├── rock2 │ │ ├── scene.bin │ │ ├── scene.gltf │ │ └── textures │ │ │ ├── 08___Default_baseColor.jpeg │ │ │ ├── 08___Default_metallicRoughness.jpg │ │ │ └── 08___Default_normal.jpg │ ├── sky-texture.jpg │ ├── skydiver.glb │ ├── snare-final.mp3 │ ├── spaceship-transformed.glb │ ├── spaceship.gltf │ ├── suzanne.glb │ ├── synth-final.mp3 │ ├── texture │ │ ├── skydiver_BaseColor.webp │ │ ├── skydiver_Clothes.webp │ │ ├── skydiver_Metallic.webp │ │ ├── skydiver_Normal.webp │ │ └── skydiver_Roughness.webp │ ├── three.png │ ├── view.svg │ ├── wheel.glb │ └── ybot.glb │ ├── src │ ├── app │ │ ├── app.component.ts │ │ ├── app.config.ts │ │ ├── app.routes.ts │ │ ├── cannon │ │ │ ├── basic │ │ │ │ ├── basic.ts │ │ │ │ ├── experience.ts │ │ │ │ └── state.ts │ │ │ ├── cannon.routes.ts │ │ │ ├── cannon.ts │ │ │ ├── chain │ │ │ │ ├── chain.ts │ │ │ │ └── experience.ts │ │ │ ├── compound │ │ │ │ ├── compound.ts │ │ │ │ └── experience.ts │ │ │ ├── convexpolyhedron │ │ │ │ ├── convexpolyhedron.ts │ │ │ │ └── experience.ts │ │ │ ├── cube-heap │ │ │ │ ├── cube-heap.ts │ │ │ │ ├── experience.ts │ │ │ │ └── state.ts │ │ │ ├── kinematic-cube │ │ │ │ ├── experience.ts │ │ │ │ └── kinematic-cube.ts │ │ │ ├── monday-morning │ │ │ │ ├── config.ts │ │ │ │ ├── experience.ts │ │ │ │ └── monday-morning.ts │ │ │ └── ui │ │ │ │ ├── plane.ts │ │ │ │ └── position-rotation-input.ts │ │ ├── colors.ts │ │ ├── misc │ │ │ ├── aviator │ │ │ │ ├── airplane │ │ │ │ │ ├── airplane.ts │ │ │ │ │ ├── pilot.ts │ │ │ │ │ ├── propeller.ts │ │ │ │ │ ├── tire.ts │ │ │ │ │ └── wheel.ts │ │ │ │ ├── aviator.ts │ │ │ │ ├── collectible │ │ │ │ │ ├── collectible-coin.component.ts │ │ │ │ │ ├── collectible-power-up.component.ts │ │ │ │ │ └── collectibles.store.ts │ │ │ │ ├── constants.ts │ │ │ │ ├── experience.ts │ │ │ │ ├── game.store.ts │ │ │ │ ├── lights │ │ │ │ │ └── lights.ts │ │ │ │ ├── obstacle │ │ │ │ │ ├── asteroid.ts │ │ │ │ │ └── obstacles.store.ts │ │ │ │ ├── overlays │ │ │ │ │ ├── coin-overlay.ts │ │ │ │ │ ├── health-overlay.ts │ │ │ │ │ └── power-ups-overlay.ts │ │ │ │ ├── sea │ │ │ │ │ └── sea.ts │ │ │ │ ├── sky │ │ │ │ │ ├── cloud.ts │ │ │ │ │ └── sky.ts │ │ │ │ └── spawnable │ │ │ │ │ └── spawnables.store.ts │ │ │ ├── misc.routes.ts │ │ │ ├── misc.ts │ │ │ └── svg-renderer │ │ │ │ ├── experience.ts │ │ │ │ └── svg-renderer.ts │ │ ├── postprocessing │ │ │ ├── basic │ │ │ │ ├── basic.ts │ │ │ │ └── experience.ts │ │ │ ├── outline │ │ │ │ ├── experience.ts │ │ │ │ └── outline.ts │ │ │ ├── postprocessing.routes.ts │ │ │ └── postprocessing.ts │ │ ├── rapier │ │ │ ├── basic │ │ │ │ └── basic.ts │ │ │ ├── cluster │ │ │ │ └── cluster.ts │ │ │ ├── constants.ts │ │ │ ├── instanced-mesh │ │ │ │ └── instanced-mesh.ts │ │ │ ├── joints │ │ │ │ └── joints.ts │ │ │ ├── performance │ │ │ │ └── performance.ts │ │ │ ├── rapier.routes.ts │ │ │ ├── rapier.ts │ │ │ ├── rope-joint │ │ │ │ └── rope-joint.ts │ │ │ ├── spring │ │ │ │ └── spring.ts │ │ │ ├── suzanne.ts │ │ │ ├── wrapper-default.ts │ │ │ └── wrapper.ts │ │ ├── routed-rocks │ │ │ ├── colored-rock.ts │ │ │ ├── constants.ts │ │ │ ├── cursor.ts │ │ │ ├── rocks.routes.ts │ │ │ ├── rocks.ts │ │ │ ├── routed-rocks.routes.ts │ │ │ ├── routed-rocks.ts │ │ │ └── store.ts │ │ ├── routed │ │ │ ├── bomb-gp.glb │ │ │ ├── bomb.ts │ │ │ ├── current-route.ts │ │ │ ├── custom-routed-scene.ts │ │ │ ├── knot.ts │ │ │ ├── routed.routes.ts │ │ │ ├── routed.ts │ │ │ └── torus.ts │ │ ├── soba │ │ │ ├── aquarium │ │ │ │ ├── aquarium.ts │ │ │ │ ├── experience.ts │ │ │ │ ├── model_52a_-_kemps_ridley_sea_turtle_no_id-transformed.glb │ │ │ │ ├── shapes-transformed.glb │ │ │ │ ├── spheres.ts │ │ │ │ ├── tank.ts │ │ │ │ └── turtle.ts │ │ │ ├── backdrop-cable │ │ │ │ ├── astronaut.ts │ │ │ │ ├── backdrop-cable.ts │ │ │ │ ├── cable.ts │ │ │ │ ├── experience.ts │ │ │ │ └── spaceship.ts │ │ │ ├── basic │ │ │ │ ├── basic.ts │ │ │ │ └── experience.ts │ │ │ ├── bruno-simons-20k │ │ │ │ ├── bruno-simons-20k.ts │ │ │ │ └── experience.ts │ │ │ ├── camera-scroll │ │ │ │ ├── camera-scroll.ts │ │ │ │ ├── experience.ts │ │ │ │ ├── model-transformed.glb │ │ │ │ ├── model.ts │ │ │ │ ├── overlay.css │ │ │ │ ├── overlay.html │ │ │ │ └── overlay.ts │ │ │ ├── decal │ │ │ │ ├── decal.ts │ │ │ │ └── experience.ts │ │ │ ├── html-chart │ │ │ │ ├── experience.ts │ │ │ │ └── html-chart.ts │ │ │ ├── hud │ │ │ │ ├── experience.ts │ │ │ │ └── hud.ts │ │ │ ├── instanced-vertex-colors │ │ │ │ ├── experience.ts │ │ │ │ └── instanced-vertex-colors.ts │ │ │ ├── instances │ │ │ │ ├── exprience.ts │ │ │ │ └── instances.ts │ │ │ ├── inverted-stencil-buffer │ │ │ │ ├── angular.ts │ │ │ │ ├── experience.ts │ │ │ │ ├── inverted-stencil-buffer.ts │ │ │ │ ├── nx-cloud.ts │ │ │ │ └── nx.ts │ │ │ ├── lod │ │ │ │ ├── experience.ts │ │ │ │ └── lod.ts │ │ │ ├── lowpoly-earth │ │ │ │ ├── experience.ts │ │ │ │ └── lowpoly-earth.ts │ │ │ ├── porsche │ │ │ │ ├── color.ts │ │ │ │ ├── lightformers.ts │ │ │ │ ├── model.ts │ │ │ │ └── porsche.ts │ │ │ ├── portal-shapes │ │ │ │ ├── bold.blob │ │ │ │ ├── constants.ts │ │ │ │ ├── experience.ts │ │ │ │ ├── letter.ts │ │ │ │ └── portal-shapes.ts │ │ │ ├── render-texture │ │ │ │ ├── experience.ts │ │ │ │ └── render-texture.ts │ │ │ ├── shaky │ │ │ │ ├── experience.ts │ │ │ │ ├── model.ts │ │ │ │ └── shaky.ts │ │ │ ├── simple-sound-analyser │ │ │ │ ├── audio.store.ts │ │ │ │ ├── experience.ts │ │ │ │ ├── overlay.ts │ │ │ │ ├── simple-sound-analyser.ts │ │ │ │ ├── track.ts │ │ │ │ ├── tracks.ts │ │ │ │ └── zoom.ts │ │ │ ├── skydiving │ │ │ │ ├── scene-graph.ts │ │ │ │ ├── skydiver.ts │ │ │ │ ├── skydiving.ts │ │ │ │ ├── winds.ts │ │ │ │ └── world.ts │ │ │ ├── soba.routes.ts │ │ │ ├── soba.ts │ │ │ ├── starbucks │ │ │ │ ├── experience.ts │ │ │ │ └── starbucks.ts │ │ │ └── stars │ │ │ │ ├── experience.ts │ │ │ │ └── stars.ts │ │ └── toggle-button.ts │ ├── index.html │ ├── main.ts │ ├── styles.css │ └── types.d.ts │ ├── tailwind.config.js │ ├── tsconfig.app.json │ ├── tsconfig.editor.json │ └── tsconfig.json ├── cz.config.js ├── doctor-storybook.log ├── eslint.config.js ├── jest.config.ts ├── jest.preset.js ├── libs ├── .gitkeep ├── cannon │ ├── README.md │ ├── body │ │ ├── README.md │ │ ├── ng-package.json │ │ └── src │ │ │ ├── index.ts │ │ │ └── lib │ │ │ ├── body.ts │ │ │ ├── types.ts │ │ │ └── utils.ts │ ├── constraint │ │ ├── README.md │ │ ├── ng-package.json │ │ └── src │ │ │ ├── index.ts │ │ │ └── lib │ │ │ └── constraint.ts │ ├── debug │ │ ├── README.md │ │ ├── ng-package.json │ │ └── src │ │ │ ├── index.ts │ │ │ └── lib │ │ │ └── debug.ts │ ├── eslint.config.js │ ├── ng-package.json │ ├── package.json │ ├── project.json │ ├── src │ │ ├── index.ts │ │ ├── lib │ │ │ └── physics.ts │ │ └── test-setup.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.spec.json │ └── vite.config.mts ├── core │ ├── README.md │ ├── eslint.config.js │ ├── nativescript │ │ ├── README.md │ │ ├── ng-package.json │ │ └── src │ │ │ ├── index.ts │ │ │ └── lib │ │ │ └── canvas.ts │ ├── ng-package.json │ ├── package.json │ ├── project.json │ ├── src │ │ ├── index.ts │ │ ├── lib │ │ │ ├── canvas.ts │ │ │ ├── directives │ │ │ │ ├── args.spec.ts │ │ │ │ ├── args.ts │ │ │ │ ├── parent.spec.ts │ │ │ │ ├── parent.ts │ │ │ │ └── selection.ts │ │ │ ├── dom │ │ │ │ └── events.ts │ │ │ ├── events.ts │ │ │ ├── html.ts │ │ │ ├── instance.ts │ │ │ ├── loader.ts │ │ │ ├── loop.ts │ │ │ ├── pipes │ │ │ │ └── hexify.ts │ │ │ ├── portal.ts │ │ │ ├── renderer │ │ │ │ ├── catalogue.spec.ts │ │ │ │ ├── catalogue.ts │ │ │ │ ├── constants.ts │ │ │ │ ├── index.ts │ │ │ │ ├── state.ts │ │ │ │ ├── utils.spec.ts │ │ │ │ └── utils.ts │ │ │ ├── roots.ts │ │ │ ├── routed-scene.ts │ │ │ ├── store.ts │ │ │ ├── three-types.ts │ │ │ ├── types.ts │ │ │ └── utils │ │ │ │ ├── apply-props.ts │ │ │ │ ├── attach.ts │ │ │ │ ├── before-render.ts │ │ │ │ ├── is.ts │ │ │ │ ├── make.ts │ │ │ │ ├── object-events.ts │ │ │ │ ├── output-ref.ts │ │ │ │ ├── parameters.ts │ │ │ │ ├── resolve-ref.ts │ │ │ │ ├── signal-store.ts │ │ │ │ └── update.ts │ │ └── test-setup.ts │ ├── testing │ │ ├── README.md │ │ ├── ng-package.json │ │ └── src │ │ │ ├── index.ts │ │ │ └── lib │ │ │ ├── test-bed.ts │ │ │ ├── test-canvas.ts │ │ │ ├── test.spec.ts │ │ │ └── utils │ │ │ ├── mock-canvas.ts │ │ │ └── web-gl-rendering-context.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.spec.json │ └── vite.config.mts ├── plugin │ ├── README.md │ ├── eslint.config.js │ ├── generators.json │ ├── jest.config.ts │ ├── package.json │ ├── project.json │ ├── src │ │ ├── generators │ │ │ ├── add-soba │ │ │ │ ├── compat.ts │ │ │ │ ├── generator.spec.ts │ │ │ │ ├── generator.ts │ │ │ │ └── schema.json │ │ │ ├── init │ │ │ │ ├── compat.ts │ │ │ │ ├── files │ │ │ │ │ └── experience │ │ │ │ │ │ └── experience.component.ts__tmpl__ │ │ │ │ ├── generator.spec.ts │ │ │ │ ├── generator.ts │ │ │ │ └── schema.json │ │ │ ├── utils.ts │ │ │ └── version.ts │ │ └── index.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── tsconfig.spec.json ├── postprocessing │ ├── README.md │ ├── eslint.config.js │ ├── n8ao │ │ ├── README.md │ │ ├── ng-package.json │ │ └── src │ │ │ ├── index.ts │ │ │ └── lib │ │ │ └── n8ao.ts │ ├── ng-package.json │ ├── package.json │ ├── project.json │ ├── src │ │ ├── index.ts │ │ ├── lib │ │ │ ├── effect-composer.ts │ │ │ ├── effect.ts │ │ │ └── effects │ │ │ │ ├── ascii.ts │ │ │ │ ├── bloom.ts │ │ │ │ ├── brightness-contrast.ts │ │ │ │ ├── chromatic-abberation.ts │ │ │ │ ├── color-average.ts │ │ │ │ ├── color-depth.ts │ │ │ │ ├── depth-of-field.ts │ │ │ │ ├── depth.ts │ │ │ │ ├── dot-screen.ts │ │ │ │ ├── fxaa.ts │ │ │ │ ├── glitch.ts │ │ │ │ ├── god-rays.ts │ │ │ │ ├── grid.ts │ │ │ │ ├── hue-saturation.ts │ │ │ │ ├── index.ts │ │ │ │ ├── lens-flare.ts │ │ │ │ ├── lut.ts │ │ │ │ ├── noise.ts │ │ │ │ ├── outline.ts │ │ │ │ ├── pixelation.ts │ │ │ │ ├── scanline.ts │ │ │ │ ├── sepia.ts │ │ │ │ ├── shock-wave.ts │ │ │ │ ├── smaa.ts │ │ │ │ ├── tilt-shift-2.ts │ │ │ │ ├── tilt-shift.ts │ │ │ │ ├── tone-mapping.ts │ │ │ │ ├── vignette.ts │ │ │ │ └── water.ts │ │ └── test-setup.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.spec.json │ └── vite.config.mts ├── rapier │ ├── README.md │ ├── eslint.config.js │ ├── ng-package.json │ ├── package.json │ ├── project.json │ ├── src │ │ ├── index.ts │ │ ├── lib │ │ │ ├── colliders.ts │ │ │ ├── debug.ts │ │ │ ├── frame-stepper.ts │ │ │ ├── instanced-rigid-bodies.ts │ │ │ ├── joints.ts │ │ │ ├── mesh-collider.ts │ │ │ ├── physics.ts │ │ │ ├── rigid-body.ts │ │ │ ├── shared.ts │ │ │ ├── types.ts │ │ │ └── utils.ts │ │ └── test-setup.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.spec.json │ └── vite.config.mts └── soba │ ├── .storybook │ ├── documentation-template.mdx │ ├── main.ts │ ├── manager-head.html │ ├── manager.ts │ ├── preview-body.html │ ├── preview.ts │ ├── public │ │ ├── LittlestTokyo-transformed.glb │ │ ├── NORM.jpg │ │ ├── angular-three.svg │ │ ├── aobox-transformed.glb │ │ ├── archer.glb │ │ ├── compressed.glb │ │ ├── cube │ │ │ ├── nx.png │ │ │ ├── ny.png │ │ │ ├── nz.png │ │ │ ├── px.png │ │ │ ├── py.png │ │ │ └── pz.png │ │ ├── decals │ │ │ ├── react.png │ │ │ └── three.png │ │ ├── dflat.glb │ │ ├── dist_map.jpeg │ │ ├── gainmap │ │ │ └── potsdamer_platz_1k.jpg │ │ ├── gelatinous_cube.glb │ │ ├── glass-transformed.glb │ │ ├── helvetiker_regular.typeface.json │ │ ├── roughness_floor.jpeg │ │ ├── shoe.glb │ │ ├── suzanne-high-poly.gltf │ │ ├── suzanne.glb │ │ ├── textures │ │ │ ├── grassy_cobble │ │ │ │ ├── grassy_cobblestone_ao_2k.jpg │ │ │ │ ├── grassy_cobblestone_diff_2k.jpg │ │ │ │ ├── grassy_cobblestone_nor_gl_2k.jpg │ │ │ │ └── grassy_cobblestone_rough_2k.jpg │ │ │ └── other │ │ │ │ └── leaves.jpg │ │ └── ybot.glb │ ├── theme.ts │ └── tsconfig.json │ ├── README.md │ ├── abstractions │ ├── README.md │ ├── ng-package.json │ └── src │ │ ├── index.ts │ │ └── lib │ │ ├── __snapshots__ │ │ ├── helper.spec.ts.snap │ │ ├── line.spec.ts.snap │ │ ├── prism-geometry.spec.ts.snap │ │ ├── rounded-box.spec.ts.snap │ │ └── text.spec.ts.snap │ │ ├── billboard.ts │ │ ├── catmull-rom-line.ts │ │ ├── cubic-bezier-line.ts │ │ ├── edges.ts │ │ ├── gradient-texture.ts │ │ ├── grid.spec.ts │ │ ├── grid.ts │ │ ├── helper.spec.ts │ │ ├── helper.ts │ │ ├── line.spec.ts │ │ ├── line.ts │ │ ├── prism-geometry.spec.ts │ │ ├── prism-geometry.ts │ │ ├── quadratic-bezier-line.ts │ │ ├── rounded-box.spec.ts │ │ ├── rounded-box.ts │ │ ├── text-3d.ts │ │ ├── text.spec.ts │ │ └── text.ts │ ├── cameras │ ├── README.md │ ├── ng-package.json │ └── src │ │ ├── index.ts │ │ └── lib │ │ ├── camera-content.ts │ │ ├── cube-camera.ts │ │ ├── orthographic-camera.ts │ │ └── perspective-camera.ts │ ├── controls │ ├── README.md │ ├── ng-package.json │ └── src │ │ ├── index.ts │ │ └── lib │ │ ├── camera-controls.ts │ │ ├── orbit-controls.ts │ │ └── scroll-controls.ts │ ├── eslint.config.js │ ├── gizmos │ ├── README.md │ ├── ng-package.json │ └── src │ │ ├── index.ts │ │ └── lib │ │ ├── gizmo-helper │ │ ├── gizmo-helper.ts │ │ ├── gizmo-viewcube.ts │ │ └── gizmo-viewport.ts │ │ ├── pivot-controls │ │ ├── axis-arrow.ts │ │ ├── axis-rotator.ts │ │ ├── pivot-controls.ts │ │ ├── plane-slider.ts │ │ └── scaling-sphere.ts │ │ └── transform-controls.ts │ ├── loaders │ ├── README.md │ ├── ng-package.json │ └── src │ │ ├── index.ts │ │ └── lib │ │ ├── fbx-loader.ts │ │ ├── font-loader.ts │ │ ├── gltf-loader.ts │ │ ├── loader.css │ │ ├── loader.ts │ │ ├── progress.ts │ │ └── texture-loader.ts │ ├── materials │ ├── README.md │ ├── ng-package.json │ └── src │ │ ├── index.ts │ │ └── lib │ │ ├── custom-shader-material.ts │ │ ├── mesh-distort-material.ts │ │ ├── mesh-portal-material.ts │ │ ├── mesh-reflector-material.ts │ │ ├── mesh-refraction-material.ts │ │ ├── mesh-transmission-material.ts │ │ ├── mesh-wobble-material.ts │ │ └── point-material.ts │ ├── misc │ ├── README.md │ ├── ng-package.json │ └── src │ │ ├── index.ts │ │ └── lib │ │ ├── animations.ts │ │ ├── bake-shadows.ts │ │ ├── computed-attribute.ts │ │ ├── constants.ts │ │ ├── decal.ts │ │ ├── deprecated.ts │ │ ├── depth-buffer.ts │ │ ├── fbo.ts │ │ ├── html │ │ ├── html-content.ts │ │ ├── html.ts │ │ └── utils.ts │ │ ├── intersect.ts │ │ ├── preload.ts │ │ ├── sampler.ts │ │ └── scale-factor.ts │ ├── ng-package.json │ ├── package.json │ ├── performances │ ├── README.md │ ├── ng-package.json │ └── src │ │ ├── index.ts │ │ └── lib │ │ ├── adaptive-dpr.ts │ │ ├── adaptive-events.ts │ │ ├── detailed.ts │ │ ├── instances │ │ ├── instances.ts │ │ └── position-mesh.ts │ │ ├── points │ │ ├── points.ts │ │ └── position-point.ts │ │ └── segments │ │ ├── segment-object.ts │ │ └── segments.ts │ ├── project.json │ ├── shaders │ ├── README.md │ ├── ng-package.json │ └── src │ │ ├── index.ts │ │ └── lib │ │ ├── grid-material.ts │ │ ├── mesh-refraction-material.ts │ │ └── point-material.ts │ ├── src │ ├── abstractions │ │ ├── billboard.stories.ts │ │ ├── gradient-texture.stories.ts │ │ ├── grid.stories.ts │ │ ├── helper.stories.ts │ │ ├── line.stories.ts │ │ ├── prism-geometry.stories.ts │ │ ├── rounded-box.stories.ts │ │ ├── text-3d.stories.ts │ │ └── text.stories.ts │ ├── cameras │ │ ├── cube-camera.stories.ts │ │ ├── orthographic-camera.stories.ts │ │ ├── perspective-camera.stories.ts │ │ └── positions.ts │ ├── controls │ │ ├── camera-controls.stories.ts │ │ └── scroll-controls.stories.ts │ ├── gizmos │ │ ├── gizmo-helper.stories.ts │ │ ├── pivot-controls.stories.ts │ │ └── transform-controls.stories.ts │ ├── index.ts │ ├── materials │ │ ├── custom-shader-material.stories.ts │ │ ├── mesh-distort-material.stories.ts │ │ ├── mesh-portal-material.stories.ts │ │ ├── mesh-reflector-material.stories.ts │ │ ├── mesh-refraction-materials.stories.ts │ │ ├── mesh-transmission-material.stories.ts │ │ └── mesh-wobble-material.stories.ts │ ├── misc │ │ ├── animations.stories.ts │ │ ├── decal.stories.ts │ │ ├── fbo.stories.ts │ │ ├── html.stories.ts │ │ └── sampler.stories.ts │ ├── performances │ │ ├── adaptive.stories.ts │ │ ├── detailed.stories.ts │ │ ├── instances.stories.ts │ │ ├── points.stories.ts │ │ └── segments.stories.ts │ ├── setup-canvas.ts │ ├── staging │ │ ├── accumulative-shadows.stories.ts │ │ ├── bb-anchor.stories.ts │ │ ├── bounds.stories.ts │ │ ├── camera-shake.stories.ts │ │ ├── caustics.stories.ts │ │ ├── contact-shadows.stories.ts │ │ ├── environment.stories.ts │ │ ├── float.stories.ts │ │ ├── lightformer.stories.ts │ │ ├── matcap-texture.stories.ts │ │ ├── normal-texture.stories.ts │ │ ├── render-texture.stories.ts │ │ ├── sky.stories.ts │ │ ├── spot-light.stories.ts │ │ └── stage.stories.ts │ ├── test-setup.ts │ └── types.d.ts │ ├── staging │ ├── README.md │ ├── ng-package.json │ └── src │ │ ├── index.ts │ │ └── lib │ │ ├── accumulative-shadows.ts │ │ ├── backdrop.ts │ │ ├── bb-anchor.ts │ │ ├── bounds.ts │ │ ├── camera-shake.ts │ │ ├── caustics.ts │ │ ├── center.ts │ │ ├── contact-shadows.ts │ │ ├── environment │ │ ├── environment.ts │ │ └── inject-environment.ts │ │ ├── float.ts │ │ ├── lightformer.ts │ │ ├── mask.ts │ │ ├── matcap-texture.ts │ │ ├── normal-texture.ts │ │ ├── randomized-lights.ts │ │ ├── render-texture.ts │ │ ├── sky.ts │ │ ├── spot-light.ts │ │ └── stage.ts │ ├── stats │ ├── README.md │ ├── ng-package.json │ └── src │ │ ├── index.ts │ │ └── lib │ │ └── stats.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.spec.json │ ├── vanilla-exports │ ├── README.md │ ├── ng-package.json │ └── src │ │ └── index.ts │ └── vitest.config.ts ├── migrations.json ├── nx.json ├── package.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── storybook-migration-summary.md ├── tools ├── scripts │ ├── generate-json.mjs │ ├── generate-soba-json.mjs │ ├── test-bed.mjs │ └── utils.mjs └── tsconfig.tools.json └── tsconfig.base.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | dist 5 | tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | node_modules 10 | 11 | # IDEs and editors 12 | /.idea 13 | .project 14 | .classpath 15 | .c9/ 16 | *.launch 17 | .settings/ 18 | *.sublime-workspace 19 | 20 | # IDE - VSCode 21 | .vscode/* 22 | !.vscode/settings.json 23 | !.vscode/tasks.json 24 | !.vscode/launch.json 25 | !.vscode/extensions.json 26 | 27 | # misc 28 | /.sass-cache 29 | /connect.lock 30 | /coverage 31 | /libpeerconnection.log 32 | npm-debug.log 33 | yarn-error.log 34 | testem.log 35 | /typings 36 | 37 | # System Files 38 | .DS_Store 39 | Thumbs.db 40 | 41 | .angular 42 | .env 43 | 44 | .nx/cache 45 | .nx/workspace-data 46 | 47 | vite.config.*.timestamp* 48 | vitest.config.*.timestamp* -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Add files here to ignore them from prettier formatting 2 | /dist 3 | /coverage 4 | .angular 5 | pnpm-lock.yaml 6 | CHANGELOG.md 7 | libs/soba/.storybook/public/**/*.js 8 | apps/sandbox/src/assets/**/*.js 9 | apps/examples/src/assets/**/*.js 10 | 11 | /.nx/cache 12 | /.nx/workspace-data -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "useTabs": true, 4 | "tabWidth": 2, 5 | "printWidth": 120, 6 | "plugins": ["prettier-plugin-organize-imports"], 7 | "htmlWhitespaceSensitivity": "ignore", 8 | "overrides": [ 9 | { 10 | "files": "*.analog", 11 | "options": { 12 | "parser": "angular" 13 | } 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "nrwl.angular-console", 4 | "esbenp.prettier-vscode", 5 | "firsttris.vscode-jest-runner", 6 | "dbaeumer.vscode-eslint" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.validate": ["json"], 3 | "html.customData": ["./node_modules/angular-three/metadata.json", "./node_modules/angular-three-soba/metadata.json"] 4 | } 5 | -------------------------------------------------------------------------------- /.ws-context: -------------------------------------------------------------------------------- 1 | { 2 | "framework": "angular", 3 | "angular-template-syntax": "V_18_1", 4 | "apps/**/*.analog": { 5 | "framework": "angular", 6 | "angular-template-syntax": "V_18_1" 7 | } 8 | } 9 | 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Angular Three 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular Three workspace 2 | 3 | ## Netlify Status 4 | 5 | - Angular Three: [![Angular Three Netlify Status](https://api.netlify.com/api/v1/badges/63a4face-28af-41d4-8b42-003c80c8cff0/deploy-status)](https://app.netlify.com/sites/angularthree/deploys) 6 | - Angular Three Demo: [![Angular Three Demo Netlify Status](https://api.netlify.com/api/v1/badges/c3dec680-1621-4a7c-a136-5be24c288019/deploy-status)](https://app.netlify.com/sites/angularthreedemo/deploys) 7 | - Angular Three Soba: [![Angular Three Soba Netlify Status](https://api.netlify.com/api/v1/badges/9e72d542-fccd-45cb-98c7-5336ccb82ec3/deploy-status)](https://app.netlify.com/sites/angularthreesoba/deploys) 8 | 9 | Here, you'll find the source code for the entire `angular-three` ecosystem, the documentation, and the examples. 10 | 11 | ## Documentation 12 | 13 | The documentation is available at [angularthree.netlify.app](https://angularthree.netlify.app). 14 | 15 | ## Examples 16 | 17 | The examples are available at [angularthreedemo.netlify.app](https://angularthreedemo.netlify.app). 18 | -------------------------------------------------------------------------------- /apps/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/.gitkeep -------------------------------------------------------------------------------- /apps/astro-docs/.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist/ 3 | # generated types 4 | .astro/ 5 | 6 | # dependencies 7 | node_modules/ 8 | 9 | # logs 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | pnpm-debug.log* 14 | 15 | 16 | # environment variables 17 | .env 18 | .env.production 19 | 20 | # macOS-specific files 21 | .DS_Store 22 | -------------------------------------------------------------------------------- /apps/astro-docs/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["astro-build.astro-vscode"], 3 | "unwantedRecommendations": [] 4 | } 5 | -------------------------------------------------------------------------------- /apps/astro-docs/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "command": "./node_modules/.bin/astro dev", 6 | "name": "Development server", 7 | "request": "launch", 8 | "type": "node-terminal" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /apps/astro-docs/ec.config.mjs: -------------------------------------------------------------------------------- 1 | import { pluginLineNumbers } from '@expressive-code/plugin-line-numbers'; 2 | 3 | export default { 4 | themes: ['dark-plus', 'light-plus'], 5 | plugins: [pluginLineNumbers()], 6 | }; 7 | -------------------------------------------------------------------------------- /apps/astro-docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "type": "module", 4 | "version": "0.0.1", 5 | "scripts": { 6 | "dev": "astro dev", 7 | "start": "astro dev", 8 | "build": "astro build", 9 | "preview": "astro preview", 10 | "astro": "astro" 11 | }, 12 | "dependencies": { 13 | "@analogjs/astro-angular": "1.9.4", 14 | "@astrojs/check": "^0.9.4", 15 | "@astrojs/mdx": "^4.0.3", 16 | "@astrojs/starlight": "^0.30.3", 17 | "@astrojs/tailwind": "^5.1.4", 18 | "angular-three": "^3.0.0", 19 | "angular-three-cannon": "^3.0.0", 20 | "angular-three-postprocessing": "^3.0.0", 21 | "angular-three-soba": "^3.0.0", 22 | "astro": "^5.1.1", 23 | "sharp": "^0.33.5", 24 | "starlight-blog": "^0.15.0", 25 | "tailwindcss": "^3.4.15" 26 | }, 27 | "nx": {}, 28 | "devDependencies": { 29 | "@astrojs/starlight-tailwind": "^3.0.0", 30 | "@expressive-code/plugin-line-numbers": "^0.38.3" 31 | }, 32 | "web-types": [ 33 | "../../node_modules/angular-three/web-types.json", 34 | "../../node_modules/angular-three-soba/web-types.json" 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /apps/astro-docs/public/bump.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/astro-docs/public/bump.jpg -------------------------------------------------------------------------------- /apps/astro-docs/public/cube/nx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/astro-docs/public/cube/nx.png -------------------------------------------------------------------------------- /apps/astro-docs/public/cube/ny.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/astro-docs/public/cube/ny.png -------------------------------------------------------------------------------- /apps/astro-docs/public/cube/nz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/astro-docs/public/cube/nz.png -------------------------------------------------------------------------------- /apps/astro-docs/public/cube/px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/astro-docs/public/cube/px.png -------------------------------------------------------------------------------- /apps/astro-docs/public/cube/py.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/astro-docs/public/cube/py.png -------------------------------------------------------------------------------- /apps/astro-docs/public/cube/pz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/astro-docs/public/cube/pz.png -------------------------------------------------------------------------------- /apps/astro-docs/src/assets/houston.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/astro-docs/src/assets/houston.webp -------------------------------------------------------------------------------- /apps/astro-docs/src/components/first-scene/first-scene.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core'; 2 | import { extend, NgtCanvas } from 'angular-three'; 3 | import * as THREE from 'three'; 4 | import { scenes } from './scenes'; 5 | 6 | extend(THREE); 7 | 8 | @Component({ 9 | template: ` 10 | 11 | `, 12 | imports: [NgtCanvas], 13 | changeDetection: ChangeDetectionStrategy.OnPush, 14 | host: { class: 'first-scene' }, 15 | }) 16 | export default class FirstScene { 17 | step = input.required(); 18 | sceneGraph = computed(() => scenes[this.step()]); 19 | } 20 | -------------------------------------------------------------------------------- /apps/astro-docs/src/components/first-scene/scene-graph-step-one.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; 2 | 3 | @Component({ 4 | template: ` 5 | 6 | 7 | 8 | `, 9 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 10 | changeDetection: ChangeDetectionStrategy.OnPush, 11 | }) 12 | export class SceneGraphStepOne {} 13 | -------------------------------------------------------------------------------- /apps/astro-docs/src/components/first-scene/scene-graph-step-three.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ChangeDetectionStrategy, 3 | Component, 4 | CUSTOM_ELEMENTS_SCHEMA, 5 | type ElementRef, 6 | signal, 7 | viewChild, 8 | } from '@angular/core'; 9 | import { injectBeforeRender } from 'angular-three'; 10 | import type { Mesh } from 'three'; 11 | 12 | @Component({ 13 | template: ` 14 | 21 | 22 | 23 | 24 | `, 25 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 26 | changeDetection: ChangeDetectionStrategy.OnPush, 27 | }) 28 | export class SceneGraphStepThree { 29 | meshRef = viewChild.required>('mesh'); 30 | 31 | hovered = signal(false); 32 | clicked = signal(false); 33 | 34 | constructor() { 35 | injectBeforeRender(({ delta }) => { 36 | const mesh = this.meshRef().nativeElement; 37 | mesh.rotation.x += delta; 38 | mesh.rotation.y += delta; 39 | }); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /apps/astro-docs/src/components/first-scene/scene-graph-step-two.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, type ElementRef, viewChild } from '@angular/core'; 2 | import { injectBeforeRender } from 'angular-three'; 3 | import type { Mesh } from 'three'; 4 | 5 | @Component({ 6 | template: ` 7 | 8 | 9 | 10 | `, 11 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 12 | changeDetection: ChangeDetectionStrategy.OnPush, 13 | }) 14 | export class SceneGraphStepTwo { 15 | meshRef = viewChild.required>('mesh'); 16 | 17 | constructor() { 18 | injectBeforeRender(({ delta }) => { 19 | const mesh = this.meshRef().nativeElement; 20 | mesh.rotation.x += delta; 21 | mesh.rotation.y += delta; 22 | }); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /apps/astro-docs/src/components/first-scene/scenes.ts: -------------------------------------------------------------------------------- 1 | import { SceneGraphStepFive } from './scene-graph-step-five'; 2 | import { SceneGraphStepFour } from './scene-graph-step-four'; 3 | import { SceneGraphStepOne } from './scene-graph-step-one'; 4 | import { SceneGraphStepSix } from './scene-graph-step-six'; 5 | import { SceneGraphStepThree } from './scene-graph-step-three'; 6 | import { SceneGraphStepTwo } from './scene-graph-step-two'; 7 | 8 | export const scenes = { 9 | stepOne: SceneGraphStepOne, 10 | stepTwo: SceneGraphStepTwo, 11 | stepThree: SceneGraphStepThree, 12 | stepFour: SceneGraphStepFour, 13 | stepFive: SceneGraphStepFive, 14 | stepSix: SceneGraphStepSix, 15 | }; 16 | -------------------------------------------------------------------------------- /apps/astro-docs/src/components/soba/soba-content.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken, signal, type Type, type WritableSignal } from '@angular/core'; 2 | 3 | export const SOBA_CONTENT = new InjectionToken | null>>('SobaContent'); 4 | 5 | const sobaContent = signal | null>(null); 6 | 7 | export function provideSobaContent() { 8 | return { provide: SOBA_CONTENT, useValue: sobaContent }; 9 | } 10 | -------------------------------------------------------------------------------- /apps/astro-docs/src/components/soba/wrapper.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { Tabs, TabItem, Code } from '@astrojs/starlight/components'; 3 | import { type SceneKeys, type SceneOptions, scenes } from './scenes'; 4 | import { SobaWrapper } from './wrapper'; 5 | 6 | interface Props { 7 | scene: SceneKeys; 8 | } 9 | 10 | const { scene } = Astro.props; 11 | 12 | const sceneOptions = (scene.split('.').reduce((acc, cur) => acc[cur], scenes)) as SceneOptions; 13 | --- 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /apps/astro-docs/src/content/config.ts: -------------------------------------------------------------------------------- 1 | import { docsSchema } from '@astrojs/starlight/schema'; 2 | import { defineCollection } from 'astro:content'; 3 | import { blogSchema } from 'starlight-blog/schema'; 4 | 5 | export const collections = { 6 | docs: defineCollection({ 7 | schema: docsSchema({ extend: (context) => blogSchema(context) }), 8 | }), 9 | }; 10 | -------------------------------------------------------------------------------- /apps/astro-docs/src/content/docs/cannon/introduction.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Introduction 3 | description: Introduction to the Angular Three Cannon package 4 | --- 5 | 6 | Angular Three Cannon is an integration of the [Cannon.js](https://github.com/pmndrs/cannon-es) physics engine for use with Angular Three. 7 | 8 | This implementation is based on the [@react-three/cannon](https://github.com/pmndrs/use-cannon) library. 9 | 10 | - [x] Doesn't block the main thread, runs in a web worker 11 | - [x] Supports all the features of cannon-es 12 | 13 | Examples are available at [angular-three-cannon](https://demo.angularthree.org/cannon) 14 | 15 | ## Installation 16 | 17 | ```sh 18 | npm install angular-three-cannon cannon-es @pmndrs/cannon-worker-api 19 | # yarn add angular-three-cannon cannon-es @pmndrs/cannon-worker-api 20 | # pnpm add angular-three-cannon cannon-es @pmndrs/cannon-worker-api 21 | ``` 22 | 23 | ## Compatibility Matrix 24 | 25 | | Angular Three Cannon Version | cannon-es version | @pmndrs/cannon-worker-api version | 26 | | ---------------------------- | ----------------- | --------------------------------- | 27 | | 2.0.0 | ^0.20.0 | ^1.0.0 | 28 | -------------------------------------------------------------------------------- /apps/astro-docs/src/content/docs/core/api/raw-value.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Raw Value 3 | description: Details about the Angular Three `ngt-value` 4 | --- 5 | 6 | There are occasions where we want to **declaratively** set a value on a property of the parent element, we can use `ngt-value` 7 | element to do this. 8 | 9 | ```angular-html 10 | 11 | 12 | 13 | 14 | 15 | ``` 16 | 17 | :::note 18 | 19 | We can achieve the same result by using `parameters` property on the `ngt-point-light` element if we don't have to worry about 20 | the life-cycle of the `ngt-value` or using control-flow with `ngt-value` 21 | 22 | ```angular-html 23 | 24 | ``` 25 | 26 | ::: 27 | -------------------------------------------------------------------------------- /apps/astro-docs/src/content/docs/core/testing/to-graph.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: toGraph 3 | description: Details about the Angular Three Testing `toGraph` function 4 | --- 5 | 6 | `toGraph` is a function that allows you to convert a THREE.js object into a simple `NgtTestGraphObject`. 7 | 8 | This is useful for snapshot testing as it _at least_ provides the scene graph structure. 9 | 10 | :::caution 11 | 12 | In many cases, we can use `toJSON` on the THREE.js object to better structure. However, this is not always possible 13 | 14 | - The `uuid` property will always be different for each test run making it difficult to do snapshot testing 15 | - Some THREE.objects do not have `toJSON` method and will throw an error when we try to call `scene.toJSON()` from the root 16 | 17 | ::: 18 | 19 | ```ts 20 | const { fixture, toGraph } = NgtTestBed.create(SceneGraph); 21 | fixture.detectChanges(); 22 | 23 | expect(toGraph()).toMatchSnapshot(); 24 | 25 | /** 26 | * For a scene with a single mesh 27 | * 28 | * [ 29 | * { 30 | * "type": "Mesh", 31 | * "name": "", 32 | * "children": [] 33 | * } 34 | * ] 35 | */ 36 | ``` 37 | -------------------------------------------------------------------------------- /apps/astro-docs/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | declare module '*.analog' { 5 | import type { Type } from '@angular/core'; 6 | const component: Type; 7 | export default component; 8 | } 9 | 10 | declare module '*?includeContent' { 11 | import type { Type } from '@angular/core'; 12 | const component: Type; 13 | export const content: string; 14 | export default component; 15 | } 16 | -------------------------------------------------------------------------------- /apps/astro-docs/src/tailwind.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /apps/astro-docs/tailwind.config.mjs: -------------------------------------------------------------------------------- 1 | import starlightPlugin from '@astrojs/starlight-tailwind'; 2 | import colors from 'tailwindcss/colors'; 3 | 4 | /** @type {import('tailwindcss').Config} */ 5 | export default { 6 | content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], 7 | theme: { 8 | extend: { 9 | colors: { 10 | // Your preferred accent color. Indigo is closest to Starlight’s defaults. 11 | accent: colors.slate, 12 | // Your preferred gray scale. Zinc is closest to Starlight’s defaults. 13 | gray: colors.zinc, 14 | }, 15 | }, 16 | }, 17 | plugins: [starlightPlugin()], 18 | }; 19 | -------------------------------------------------------------------------------- /apps/astro-docs/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "outDir": "./dist/out-tsc", 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "noImplicitOverride": true, 10 | "noPropertyAccessFromIndexSignature": true, 11 | "noImplicitReturns": true, 12 | "noFallthroughCasesInSwitch": true, 13 | "sourceMap": true, 14 | "declaration": false, 15 | "downlevelIteration": true, 16 | "experimentalDecorators": true, 17 | "moduleResolution": "node", 18 | "importHelpers": true, 19 | "noEmit": false, 20 | "target": "es2020", 21 | "module": "es2020", 22 | "lib": ["es2020", "dom"], 23 | "skipLibCheck": true 24 | }, 25 | "angularCompilerOptions": { 26 | "enableI18nLegacyMessageIdFormat": false, 27 | "strictInjectionParameters": true, 28 | "strictInputAccessModifiers": true, 29 | "strictTemplates": true, 30 | "allowJs": false 31 | }, 32 | "files": [], 33 | "include": ["src/**/*.ts"] 34 | } 35 | -------------------------------------------------------------------------------- /apps/astro-docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "astro/tsconfigs/base" 3 | } 4 | -------------------------------------------------------------------------------- /apps/ionic-app/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | -------------------------------------------------------------------------------- /apps/ionic-app/capacitor.config.ts: -------------------------------------------------------------------------------- 1 | import { CapacitorConfig } from '@capacitor/cli'; 2 | 3 | const config: CapacitorConfig = { 4 | appId: 'io.ionic.starter', 5 | appName: 'ionic-app', 6 | webDir: '../../dist/apps/ionic-app', 7 | bundledWebRuntime: false, 8 | server: { 9 | androidScheme: 'https', 10 | }, 11 | }; 12 | 13 | export default config; 14 | -------------------------------------------------------------------------------- /apps/ionic-app/ionic.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ionic-app", 3 | "integrations": { 4 | "capacitor": {} 5 | }, 6 | "type": "angular" 7 | } 8 | -------------------------------------------------------------------------------- /apps/ionic-app/ios/.gitignore: -------------------------------------------------------------------------------- 1 | App/build 2 | App/Pods 3 | App/output 4 | App/App/public 5 | DerivedData 6 | xcuserdata 7 | 8 | # Cordova plugins for Capacitor 9 | capacitor-cordova-ios-plugins 10 | 11 | # Generated Config files 12 | App/App/capacitor.config.json 13 | App/App/config.xml 14 | -------------------------------------------------------------------------------- /apps/ionic-app/ios/App/App.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /apps/ionic-app/ios/App/App.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /apps/ionic-app/ios/App/App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /apps/ionic-app/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/ionic-app/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png -------------------------------------------------------------------------------- /apps/ionic-app/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "filename": "AppIcon-512@2x.png", 5 | "idiom": "universal", 6 | "platform": "ios", 7 | "size": "1024x1024" 8 | } 9 | ], 10 | "info": { 11 | "author": "xcode", 12 | "version": 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /apps/ionic-app/ios/App/App/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "version": 1, 4 | "author": "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /apps/ionic-app/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "idiom": "universal", 5 | "filename": "splash-2732x2732-2.png", 6 | "scale": "1x" 7 | }, 8 | { 9 | "idiom": "universal", 10 | "filename": "splash-2732x2732-1.png", 11 | "scale": "2x" 12 | }, 13 | { 14 | "idiom": "universal", 15 | "filename": "splash-2732x2732.png", 16 | "scale": "3x" 17 | } 18 | ], 19 | "info": { 20 | "version": 1, 21 | "author": "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /apps/ionic-app/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/ionic-app/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png -------------------------------------------------------------------------------- /apps/ionic-app/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/ionic-app/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png -------------------------------------------------------------------------------- /apps/ionic-app/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/ionic-app/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png -------------------------------------------------------------------------------- /apps/ionic-app/ios/App/App/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /apps/ionic-app/ios/App/Podfile: -------------------------------------------------------------------------------- 1 | require_relative '../../node_modules/@capacitor/ios/scripts/pods_helpers' 2 | 3 | platform :ios, '13.0' 4 | use_frameworks! 5 | 6 | # workaround to avoid Xcode caching of Pods that requires 7 | # Product -> Clean Build Folder after new Cordova plugins installed 8 | # Requires CocoaPods 1.6 or newer 9 | install! 'cocoapods', :disable_input_output_paths => true 10 | 11 | def capacitor_pods 12 | pod 'Capacitor', :path => '../../../../node_modules/.pnpm/@capacitor+ios@5.7.6_@capacitor+core@5.7.6/node_modules/@capacitor/ios' 13 | pod 'CapacitorCordova', :path => '../../../../node_modules/.pnpm/@capacitor+ios@5.7.6_@capacitor+core@5.7.6/node_modules/@capacitor/ios' 14 | 15 | end 16 | 17 | target 'App' do 18 | capacitor_pods 19 | # Add your Pods here 20 | end 21 | 22 | post_install do |installer| 23 | assertDeploymentTarget(installer) 24 | end 25 | -------------------------------------------------------------------------------- /apps/ionic-app/ios/App/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Capacitor (5.7.6): 3 | - CapacitorCordova 4 | - CapacitorCordova (5.7.6) 5 | 6 | DEPENDENCIES: 7 | - "Capacitor (from `../../../../node_modules/.pnpm/@capacitor+ios@5.7.6_@capacitor+core@5.7.6/node_modules/@capacitor/ios`)" 8 | - "CapacitorCordova (from `../../../../node_modules/.pnpm/@capacitor+ios@5.7.6_@capacitor+core@5.7.6/node_modules/@capacitor/ios`)" 9 | 10 | EXTERNAL SOURCES: 11 | Capacitor: 12 | :path: "../../../../node_modules/.pnpm/@capacitor+ios@5.7.6_@capacitor+core@5.7.6/node_modules/@capacitor/ios" 13 | CapacitorCordova: 14 | :path: "../../../../node_modules/.pnpm/@capacitor+ios@5.7.6_@capacitor+core@5.7.6/node_modules/@capacitor/ios" 15 | 16 | SPEC CHECKSUMS: 17 | Capacitor: 6e86d6f68a9348c76b6da7349ab3ee4a9edd3b9a 18 | CapacitorCordova: 46df0372f7768ff20aa659ba1658b5d7315ea42a 19 | 20 | PODFILE CHECKSUM: be78ad99b1cc4b98f749bdf09511117bb977cead 21 | 22 | COCOAPODS: 1.15.2 23 | -------------------------------------------------------------------------------- /apps/ionic-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ionic-app", 3 | "devDependencies": { 4 | "@capacitor/cli": "^5.0.3", 5 | "@capacitor/ios": "../../node_modules/@capacitor/ios", 6 | "@capacitor/android": "../../node_modules/@capacitor/android" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /apps/ionic-app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/ionic-app/public/favicon.ico -------------------------------------------------------------------------------- /apps/ionic-app/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { Component } from '@angular/core'; 3 | import { IonicModule } from '@ionic/angular'; 4 | 5 | @Component({ 6 | selector: 'platform-root', 7 | imports: [CommonModule, IonicModule], 8 | template: ` 9 | 10 | 11 | 12 | `, 13 | styles: ``, 14 | }) 15 | export class AppComponent {} 16 | -------------------------------------------------------------------------------- /apps/ionic-app/src/app/app.config.ts: -------------------------------------------------------------------------------- 1 | import { ApplicationConfig, importProvidersFrom } from '@angular/core'; 2 | import { provideRouter } from '@angular/router'; 3 | import { IonicModule } from '@ionic/angular'; 4 | import { appRoutes } from './app.routes'; 5 | 6 | export const appConfig: ApplicationConfig = { 7 | providers: [provideRouter(appRoutes), importProvidersFrom(IonicModule.forRoot())], 8 | }; 9 | -------------------------------------------------------------------------------- /apps/ionic-app/src/app/app.routes.ts: -------------------------------------------------------------------------------- 1 | import { Routes } from '@angular/router'; 2 | 3 | export const appRoutes: Routes = [ 4 | { 5 | path: 'home', 6 | loadChildren: () => import('./home/home.routes').then((r) => r.routes), 7 | }, 8 | { 9 | path: '', 10 | redirectTo: 'home', 11 | pathMatch: 'full', 12 | }, 13 | ]; 14 | -------------------------------------------------------------------------------- /apps/ionic-app/src/app/home/home.page.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { IonicModule } from '@ionic/angular'; 3 | import { extend, NgtCanvas } from 'angular-three'; 4 | import * as THREE from 'three'; 5 | import { Experience } from './experience'; 6 | 7 | extend(THREE); 8 | 9 | @Component({ 10 | selector: 'platform-home', 11 | imports: [IonicModule, NgtCanvas], 12 | template: ` 13 | 14 |
15 | 16 |
17 |
18 | `, 19 | styles: ` 20 | #container { 21 | text-align: center; 22 | position: absolute; 23 | left: 0; 24 | right: 0; 25 | top: 50%; 26 | height: 100%; 27 | transform: translateY(-50%); 28 | } 29 | `, 30 | }) 31 | export class HomePage { 32 | scene = Experience; 33 | } 34 | -------------------------------------------------------------------------------- /apps/ionic-app/src/app/home/home.routes.ts: -------------------------------------------------------------------------------- 1 | import { Routes } from '@angular/router'; 2 | 3 | export const routes: Routes = [ 4 | { 5 | path: '', 6 | loadComponent: () => import('./home.page').then((p) => p.HomePage), 7 | }, 8 | ]; 9 | -------------------------------------------------------------------------------- /apps/ionic-app/src/assets/icon/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/ionic-app/src/assets/icon/favicon.png -------------------------------------------------------------------------------- /apps/ionic-app/src/assets/shapes.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /apps/ionic-app/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Ionic App 6 | 7 | 8 | 9 | 10 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /apps/ionic-app/src/main.ts: -------------------------------------------------------------------------------- 1 | import { bootstrapApplication } from '@angular/platform-browser'; 2 | import { AppComponent } from './app/app.component'; 3 | import { appConfig } from './app/app.config'; 4 | 5 | bootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err)); 6 | -------------------------------------------------------------------------------- /apps/ionic-app/src/styles.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * App Global CSS 3 | * ---------------------------------------------------------------------------- 4 | * Put style rules here that you want to apply globally. These styles are for 5 | * the entire app and not just one component. Additionally, this file can be 6 | * used as an entry point to import other CSS/Sass files to be included in the 7 | * output CSS. 8 | * For more information on global stylesheets, visit the documentation: 9 | * https://ionicframework.com/docs/layout/global-stylesheets 10 | */ 11 | -------------------------------------------------------------------------------- /apps/ionic-app/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [] 6 | }, 7 | "files": ["src/main.ts"], 8 | "include": ["src/**/*.d.ts"], 9 | "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /apps/ionic-app/tsconfig.editor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["src/**/*.ts"], 4 | "compilerOptions": {}, 5 | "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] 6 | } 7 | -------------------------------------------------------------------------------- /apps/ionic-app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "useDefineForClassFields": false, 5 | "forceConsistentCasingInFileNames": true, 6 | "strict": true, 7 | "noImplicitOverride": true, 8 | "noPropertyAccessFromIndexSignature": true, 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true 11 | }, 12 | "files": [], 13 | "include": [], 14 | "references": [ 15 | { 16 | "path": "./tsconfig.editor.json" 17 | }, 18 | { 19 | "path": "./tsconfig.app.json" 20 | } 21 | ], 22 | "extends": "../../tsconfig.base.json", 23 | "angularCompilerOptions": { 24 | "enableI18nLegacyMessageIdFormat": false, 25 | "strictInjectionParameters": true, 26 | "strictInputAccessModifiers": true, 27 | "strictTemplates": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /apps/kitchen-sink/public/1200px-Starbucks_Logo_ab_2011.svg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/1200px-Starbucks_Logo_ab_2011.svg.png -------------------------------------------------------------------------------- /apps/kitchen-sink/public/911-transformed.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/911-transformed.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/Astronaut-transformed.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/Astronaut-transformed.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/Beetle.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/Beetle.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 2 | -------------------------------------------------------------------------------- /apps/kitchen-sink/public/angular.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/angular.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/bendy.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/bendy.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/blender-threejs-journey-20k-hat-transformed.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/blender-threejs-journey-20k-hat-transformed.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/blender-threejs-journey-20k-transformed.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/blender-threejs-journey-20k-transformed.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/bomb-gp.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/bomb-gp.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/bowl.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/bowl.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/bunny-transformed.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/bunny-transformed.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/bust-1-d.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/bust-1-d.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/bust-2-d.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/bust-2-d.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/bust-3-d.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/bust-3-d.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/bust-4-d.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/bust-4-d.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/bust-5-d.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/bust-5-d.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/coffee-transformed.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/coffee-transformed.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/cup.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/cup.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/diamond.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/diamond.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/dragon_chestplate.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/dragon_chestplate.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/drums-final.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/drums-final.mp3 -------------------------------------------------------------------------------- /apps/kitchen-sink/public/env/skydiving/nx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/env/skydiving/nx.png -------------------------------------------------------------------------------- /apps/kitchen-sink/public/env/skydiving/ny.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/env/skydiving/ny.png -------------------------------------------------------------------------------- /apps/kitchen-sink/public/env/skydiving/nz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/env/skydiving/nz.png -------------------------------------------------------------------------------- /apps/kitchen-sink/public/env/skydiving/px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/env/skydiving/px.png -------------------------------------------------------------------------------- /apps/kitchen-sink/public/env/skydiving/py.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/env/skydiving/py.png -------------------------------------------------------------------------------- /apps/kitchen-sink/public/env/skydiving/pz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/env/skydiving/pz.png -------------------------------------------------------------------------------- /apps/kitchen-sink/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/favicon.ico -------------------------------------------------------------------------------- /apps/kitchen-sink/public/magnet.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/magnet.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/nx-cloud.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/nx-cloud.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/nx.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/nx.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/pingpong.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/pingpong.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/pink-d.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/pink-d.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/rock2/scene.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/rock2/scene.bin -------------------------------------------------------------------------------- /apps/kitchen-sink/public/rock2/textures/08___Default_baseColor.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/rock2/textures/08___Default_baseColor.jpeg -------------------------------------------------------------------------------- /apps/kitchen-sink/public/rock2/textures/08___Default_metallicRoughness.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/rock2/textures/08___Default_metallicRoughness.jpg -------------------------------------------------------------------------------- /apps/kitchen-sink/public/rock2/textures/08___Default_normal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/rock2/textures/08___Default_normal.jpg -------------------------------------------------------------------------------- /apps/kitchen-sink/public/sky-texture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/sky-texture.jpg -------------------------------------------------------------------------------- /apps/kitchen-sink/public/skydiver.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/skydiver.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/snare-final.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/snare-final.mp3 -------------------------------------------------------------------------------- /apps/kitchen-sink/public/spaceship-transformed.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/spaceship-transformed.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/suzanne.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/suzanne.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/synth-final.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/synth-final.mp3 -------------------------------------------------------------------------------- /apps/kitchen-sink/public/texture/skydiver_BaseColor.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/texture/skydiver_BaseColor.webp -------------------------------------------------------------------------------- /apps/kitchen-sink/public/texture/skydiver_Clothes.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/texture/skydiver_Clothes.webp -------------------------------------------------------------------------------- /apps/kitchen-sink/public/texture/skydiver_Metallic.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/texture/skydiver_Metallic.webp -------------------------------------------------------------------------------- /apps/kitchen-sink/public/texture/skydiver_Normal.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/texture/skydiver_Normal.webp -------------------------------------------------------------------------------- /apps/kitchen-sink/public/texture/skydiver_Roughness.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/texture/skydiver_Roughness.webp -------------------------------------------------------------------------------- /apps/kitchen-sink/public/three.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/three.png -------------------------------------------------------------------------------- /apps/kitchen-sink/public/wheel.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/wheel.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/public/ybot.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/public/ybot.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/app.config.ts: -------------------------------------------------------------------------------- 1 | import { ApplicationConfig, provideExperimentalZonelessChangeDetection } from '@angular/core'; 2 | import { provideRouter, withComponentInputBinding } from '@angular/router'; 3 | import { appRoutes } from './app.routes'; 4 | 5 | export const appConfig: ApplicationConfig = { 6 | providers: [ 7 | provideExperimentalZonelessChangeDetection(), 8 | // provideZoneChangeDetection({ eventCoalescing: true, runCoalescing: true }), 9 | provideRouter(appRoutes, withComponentInputBinding()), 10 | ], 11 | }; 12 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/cannon/basic/basic.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { Experience } from './experience'; 4 | import { State } from './state'; 5 | 6 | @Component({ 7 | template: ` 8 | 9 |
10 | 11 | | 12 | 13 |
14 | `, 15 | imports: [NgtCanvas], 16 | changeDetection: ChangeDetectionStrategy.OnPush, 17 | host: { class: 'basic-cannon ' }, 18 | providers: [State], 19 | }) 20 | export default class Basic { 21 | protected scene = Experience; 22 | protected state = inject(State); 23 | } 24 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/cannon/basic/state.ts: -------------------------------------------------------------------------------- 1 | import { signal } from '@angular/core'; 2 | import { createInjectable } from 'ngxtension/create-injectable'; 3 | 4 | export const State = createInjectable( 5 | () => { 6 | const isDebugging = signal(false); 7 | const gravity = signal(-20); 8 | 9 | return { 10 | gravity: gravity.asReadonly(), 11 | isDebugging: isDebugging.asReadonly(), 12 | changeGravity: () => gravity.update((prev) => (prev === -20 ? -10 : -20)), 13 | toggleDebugging: () => isDebugging.update((prev) => !prev), 14 | }; 15 | }, 16 | { providedIn: 'scoped' }, 17 | ); 18 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/cannon/chain/chain.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { Experience } from './experience'; 4 | 5 | @Component({ 6 | template: ` 7 | 8 |
* Click to reset
9 | `, 10 | imports: [NgtCanvas], 11 | changeDetection: ChangeDetectionStrategy.OnPush, 12 | host: { class: 'chain-cannon' }, 13 | }) 14 | export default class Chain { 15 | protected scene = Experience; 16 | } 17 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/cannon/compound/compound.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { Experience } from './experience'; 4 | 5 | @Component({ 6 | template: ` 7 | 8 | `, 9 | imports: [NgtCanvas], 10 | changeDetection: ChangeDetectionStrategy.OnPush, 11 | host: { class: 'compound-cannon' }, 12 | }) 13 | export default class Compound { 14 | protected scene = Experience; 15 | } 16 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/cannon/convexpolyhedron/convexpolyhedron.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { Experience } from './experience'; 4 | 5 | @Component({ 6 | template: ` 7 | 8 |
* Click to invert gravity
9 | `, 10 | imports: [NgtCanvas], 11 | changeDetection: ChangeDetectionStrategy.OnPush, 12 | host: { class: 'convex-cannon' }, 13 | }) 14 | export default class ConvexPolyhedron { 15 | protected scene = Experience; 16 | } 17 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/cannon/cube-heap/cube-heap.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { Experience } from './experience'; 4 | import { shape } from './state'; 5 | 6 | @Component({ 7 | template: ` 8 | 14 | `, 15 | imports: [NgtCanvas], 16 | changeDetection: ChangeDetectionStrategy.OnPush, 17 | host: { class: 'cube-heap-cannon' }, 18 | }) 19 | export default class CubeHeap { 20 | protected scene = Experience; 21 | 22 | onPointerMissed() { 23 | shape.update((prev) => (prev === 'box' ? 'sphere' : 'box')); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/cannon/cube-heap/state.ts: -------------------------------------------------------------------------------- 1 | import { signal } from '@angular/core'; 2 | 3 | export const shape = signal<'box' | 'sphere'>('box'); 4 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/cannon/kinematic-cube/kinematic-cube.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { Experience } from './experience'; 4 | 5 | @Component({ 6 | template: ` 7 | 8 | `, 9 | changeDetection: ChangeDetectionStrategy.OnPush, 10 | imports: [NgtCanvas], 11 | host: { class: 'kinematic-cannon' }, 12 | }) 13 | export default class KinematicCube { 14 | protected scene = Experience; 15 | } 16 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/cannon/monday-morning/monday-morning.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { Experience } from './experience'; 4 | 5 | @Component({ 6 | template: ` 7 | 13 | `, 14 | imports: [NgtCanvas], 15 | changeDetection: ChangeDetectionStrategy.OnPush, 16 | host: { class: 'monday-morning-cannon cursor-none' }, 17 | }) 18 | export default class MondayMorning { 19 | protected scene = Experience; 20 | } 21 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/cannon/ui/position-rotation-input.ts: -------------------------------------------------------------------------------- 1 | import { Directive, input } from '@angular/core'; 2 | import { Triplet } from '@pmndrs/cannon-worker-api'; 3 | 4 | @Directive() 5 | export class PositionRotationInput { 6 | position = input([0, 0, 0]); 7 | rotation = input([0, 0, 0]); 8 | } 9 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/colors.ts: -------------------------------------------------------------------------------- 1 | // From `nice-color-palettes`, this one is index 17 2 | export default ['#99b898', '#fecea8', '#ff847c', '#e84a5f', '#2a363b'] as const; 3 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/misc/aviator/airplane/tire.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, input } from '@angular/core'; 2 | import { NgtArgs, NgtVector3 } from 'angular-three'; 3 | import { COLORS } from '../constants'; 4 | 5 | @Component({ 6 | selector: 'app-tire', 7 | template: ` 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | `, 18 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 19 | changeDetection: ChangeDetectionStrategy.OnPush, 20 | imports: [NgtArgs], 21 | }) 22 | export class Tire { 23 | protected readonly COLORS = COLORS; 24 | 25 | position = input([0, 0, 0]); 26 | scale = input(1); 27 | } 28 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/misc/aviator/airplane/wheel.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, input } from '@angular/core'; 2 | import { NgtArgs, NgtVector3 } from 'angular-three'; 3 | import { COLORS } from '../constants'; 4 | 5 | @Component({ 6 | selector: 'app-wheel', 7 | template: ` 8 | 9 | 10 | 11 | 12 | `, 13 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 14 | changeDetection: ChangeDetectionStrategy.OnPush, 15 | imports: [NgtArgs], 16 | }) 17 | export class Wheel { 18 | protected readonly COLORS = COLORS; 19 | 20 | position = input([0, 0, 0]); 21 | } 22 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/misc/aviator/lights/lights.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; 2 | import { NgtArgs } from 'angular-three'; 3 | 4 | @Component({ 5 | selector: 'app-lights', 6 | template: ` 7 | 8 | 9 | 10 | 11 | 12 | 13 | `, 14 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 15 | changeDetection: ChangeDetectionStrategy.OnPush, 16 | imports: [NgtArgs], 17 | }) 18 | export class Lights { 19 | protected readonly Math = Math; 20 | } 21 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/misc/aviator/obstacle/asteroid.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/src/app/misc/aviator/obstacle/asteroid.ts -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/misc/aviator/obstacle/obstacles.store.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | @Injectable() 4 | export class ObstaclesStore {} 5 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/misc/aviator/overlays/coin-overlay.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, computed, inject } from '@angular/core'; 2 | import { GameStore } from '../game.store'; 3 | 4 | @Component({ 5 | selector: 'app-coin-overlay', 6 | template: ` 7 | {{ coinDisplay() }} 8 | `, 9 | changeDetection: ChangeDetectionStrategy.OnPush, 10 | host: { class: 'flex items-center' }, 11 | }) 12 | export class CoinOverlay { 13 | private gameStore = inject(GameStore); 14 | protected coinDisplay = computed(() => { 15 | const coins = this.gameStore.coins(); 16 | const formattedCoins = coins.toString().padStart(4, '0'); 17 | return formattedCoins.replace(/^(\d)(\d{3})$/, '$1,$2'); 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/misc/misc.routes.ts: -------------------------------------------------------------------------------- 1 | import { Routes } from '@angular/router'; 2 | 3 | const routes: Routes = [ 4 | { 5 | path: 'svg-renderer', 6 | loadComponent: () => import('./svg-renderer/svg-renderer'), 7 | data: { 8 | credits: { 9 | title: 'SVG Renderer w/ Lines', 10 | link: 'https://threejs.org/examples/#svg_lines', 11 | class: 'text-white', 12 | }, 13 | }, 14 | }, 15 | { 16 | path: 'aviator', 17 | loadComponent: () => import('./aviator/aviator'), 18 | data: { 19 | credits: { 20 | title: 'The Aviator', 21 | link: 'https://github.com/yakudoo/TheAviator', 22 | class: 'text-white', 23 | }, 24 | }, 25 | }, 26 | { 27 | path: '', 28 | redirectTo: 'svg-renderer', 29 | pathMatch: 'full', 30 | }, 31 | ]; 32 | 33 | export default routes; 34 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/misc/svg-renderer/svg-renderer.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas, NgtCanvasElement } from 'angular-three'; 3 | import { SVGRenderer } from 'three-stdlib'; 4 | import { Experience } from './experience'; 5 | 6 | @Component({ 7 | template: ` 8 | 13 | `, 14 | imports: [NgtCanvas], 15 | changeDetection: ChangeDetectionStrategy.OnPush, 16 | }) 17 | export default class SVGRendererExample { 18 | sceneGraph = Experience; 19 | 20 | svgRendererFactory = (canvas: NgtCanvasElement) => { 21 | const renderer = new SVGRenderer(); 22 | 23 | if (canvas instanceof HTMLCanvasElement) { 24 | canvas.style.display = 'none'; 25 | canvas.parentElement?.appendChild(renderer.domElement); 26 | } 27 | 28 | return renderer; 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/postprocessing/basic/basic.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { Experience } from './experience'; 4 | 5 | @Component({ 6 | template: ` 7 | 8 | `, 9 | changeDetection: ChangeDetectionStrategy.OnPush, 10 | imports: [NgtCanvas], 11 | host: { class: 'basic-postprocessing' }, 12 | }) 13 | export default class Basic { 14 | protected scene = Experience; 15 | } 16 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/postprocessing/outline/outline.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { Experience } from './experience'; 4 | 5 | @Component({ 6 | template: ` 7 | 8 | `, 9 | changeDetection: ChangeDetectionStrategy.OnPush, 10 | host: { class: 'postprocessing-outline' }, 11 | imports: [NgtCanvas], 12 | }) 13 | export default class PostprocessingOutline { 14 | protected sceneGraph = Experience; 15 | } 16 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/postprocessing/postprocessing.routes.ts: -------------------------------------------------------------------------------- 1 | import { Routes } from '@angular/router'; 2 | 3 | const routes: Routes = [ 4 | { 5 | path: 'basic', 6 | loadComponent: () => import('./basic/basic'), 7 | }, 8 | { 9 | path: 'outline', 10 | loadComponent: () => import('./outline/outline'), 11 | }, 12 | { 13 | path: '', 14 | redirectTo: 'basic', 15 | pathMatch: 'full', 16 | }, 17 | ]; 18 | 19 | export default routes; 20 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/rapier/constants.ts: -------------------------------------------------------------------------------- 1 | import { Basic } from './basic/basic'; 2 | import { ClusterExample } from './cluster/cluster'; 3 | import { InstancedMeshExample } from './instanced-mesh/instanced-mesh'; 4 | import { JointsExample } from './joints/joints'; 5 | import { PerformanceExample } from './performance/performance'; 6 | import { RopeJointExample } from './rope-joint/rope-joint'; 7 | import { SpringExample } from './spring/spring'; 8 | 9 | export const SCENES_MAP = { 10 | basic: Basic, 11 | instancedMesh: InstancedMeshExample, 12 | performance: PerformanceExample, 13 | joints: JointsExample, 14 | cluster: ClusterExample, 15 | ropeJoint: RopeJointExample, 16 | spring: SpringExample, 17 | } as const; 18 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/rapier/rapier.routes.ts: -------------------------------------------------------------------------------- 1 | import { Routes } from '@angular/router'; 2 | 3 | const routes: Routes = [ 4 | { 5 | path: ':scene', 6 | loadComponent: () => import('./wrapper'), 7 | data: { 8 | credits: { 9 | title: 'React Three Rapier', 10 | link: 'https://react-three-rapier.pmnd.rs', 11 | class: 'left-2', 12 | }, 13 | }, 14 | }, 15 | { 16 | path: '', 17 | redirectTo: 'basic', 18 | pathMatch: 'full', 19 | }, 20 | ]; 21 | 22 | export default routes; 23 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/rapier/suzanne.ts: -------------------------------------------------------------------------------- 1 | import { injectGLTF } from 'angular-three-soba/loaders'; 2 | import { Mesh } from 'three'; 3 | import { GLTF } from 'three-stdlib'; 4 | 5 | type SuzanneGLTF = GLTF & { 6 | nodes: { Suzanne: Mesh }; 7 | }; 8 | 9 | export function injectSuzanne() { 10 | return injectGLTF(() => './suzanne.glb'); 11 | } 12 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/rapier/wrapper.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { ToggleButton } from '../toggle-button'; 4 | import { debug, interpolate, paused, RapierWrapperDefault } from './wrapper-default'; 5 | 6 | @Component({ 7 | template: ` 8 | 9 |
10 | 11 | 12 | 13 |
14 | `, 15 | changeDetection: ChangeDetectionStrategy.OnPush, 16 | imports: [NgtCanvas, ToggleButton], 17 | }) 18 | export default class RapierWrapper { 19 | protected sceneGraph = RapierWrapperDefault; 20 | 21 | protected debug = debug; 22 | protected interpolate = interpolate; 23 | protected paused = paused; 24 | } 25 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/routed-rocks/constants.ts: -------------------------------------------------------------------------------- 1 | const colors = [ 2 | { 3 | color: '#042A2B', 4 | label: 'Rich Black', 5 | slug: 'rich-black', 6 | }, 7 | { 8 | color: '#5EB1BF', 9 | label: 'Maximum Blue', 10 | slug: 'maximum-blue', 11 | }, 12 | { 13 | color: '#CDEDF6', 14 | label: 'Light Cyan', 15 | slug: 'light-cyan', 16 | }, 17 | { 18 | color: '#EF7B45', 19 | label: 'Mandarin', 20 | slug: 'mandarin', 21 | }, 22 | { 23 | color: '#D84727', 24 | label: 'Vermilion', 25 | slug: 'vermilion', 26 | }, 27 | ] as const; 28 | 29 | export const menus = colors.map((color, index) => ({ 30 | id: index + 1, 31 | slug: color.slug, 32 | label: color.label, 33 | name: `rock-${color.slug}`, 34 | path: `/routed-rocks/rocks/${color.slug}`, 35 | color: color.color, 36 | angle: ((360 / colors.length) * index * Math.PI) / 180, 37 | })); 38 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/routed-rocks/cursor.ts: -------------------------------------------------------------------------------- 1 | import { DOCUMENT } from '@angular/common'; 2 | import { Directive, ElementRef, inject } from '@angular/core'; 3 | import { getLocalState, injectObjectEvents } from 'angular-three'; 4 | import { Object3D } from 'three'; 5 | 6 | @Directive({ selector: '[cursor]' }) 7 | export class Cursor { 8 | constructor() { 9 | const elementRef = inject>(ElementRef); 10 | const nativeElement = elementRef.nativeElement; 11 | 12 | if (!nativeElement.isObject3D) return; 13 | 14 | const localState = getLocalState(nativeElement); 15 | if (!localState) return; 16 | 17 | const document = inject(DOCUMENT); 18 | 19 | injectObjectEvents(() => nativeElement, { 20 | pointerover: () => { 21 | document.body.style.cursor = 'pointer'; 22 | }, 23 | pointerout: () => { 24 | document.body.style.cursor = 'default'; 25 | }, 26 | }); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/routed-rocks/rocks.routes.ts: -------------------------------------------------------------------------------- 1 | import { Routes } from '@angular/router'; 2 | 3 | const rockRoutes: Routes = [ 4 | { 5 | path: ':colorId', 6 | loadComponent: () => import('./colored-rock'), 7 | }, 8 | ]; 9 | 10 | export default rockRoutes; 11 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/routed-rocks/routed-rocks.routes.ts: -------------------------------------------------------------------------------- 1 | import { Routes } from '@angular/router'; 2 | 3 | const routes: Routes = [ 4 | { 5 | path: 'rocks', 6 | loadComponent: () => import('./rocks'), 7 | loadChildren: () => import('./rocks.routes'), 8 | }, 9 | { 10 | path: '', 11 | redirectTo: 'rocks', 12 | pathMatch: 'full', 13 | }, 14 | ]; 15 | 16 | export default routes; 17 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/routed-rocks/routed-rocks.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { extend, NgtCanvas } from 'angular-three'; 3 | import * as THREE from 'three'; 4 | import { RockStore } from './store'; 5 | 6 | extend(THREE); 7 | 8 | @Component({ 9 | template: ` 10 | 11 | `, 12 | imports: [NgtCanvas], 13 | providers: [RockStore], 14 | changeDetection: ChangeDetectionStrategy.OnPush, 15 | host: { class: 'routed-rocks block h-svh' }, 16 | }) 17 | export default class RoutedRocks {} 18 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/routed-rocks/store.ts: -------------------------------------------------------------------------------- 1 | import { inject, Injectable } from '@angular/core'; 2 | import { toSignal } from '@angular/core/rxjs-interop'; 3 | import { NavigationEnd, Router } from '@angular/router'; 4 | import { filter, map, startWith } from 'rxjs'; 5 | import { menus } from './constants'; 6 | 7 | @Injectable() 8 | export class RockStore { 9 | private router = inject(Router); 10 | 11 | selectedRock = toSignal( 12 | this.router.events.pipe( 13 | filter((ev): ev is NavigationEnd => ev instanceof NavigationEnd), 14 | map((ev) => ev.urlAfterRedirects), 15 | startWith(this.router.url), 16 | map((url) => menus.find((menu) => menu.path === url) || null), 17 | ), 18 | { initialValue: null }, 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/routed/bomb-gp.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/src/app/routed/bomb-gp.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/routed/bomb.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; 2 | import { injectGLTF } from 'angular-three-soba/loaders'; 3 | import { NgtsMeshTransmissionMaterial } from 'angular-three-soba/materials'; 4 | import { Mesh } from 'three'; 5 | import { GLTF } from 'three-stdlib'; 6 | 7 | import bombUrl from './bomb-gp.glb'; 8 | 9 | interface BombGLTF extends GLTF { 10 | nodes: { 11 | Little_Boy_Little_Boy_Material_0: Mesh; 12 | }; 13 | } 14 | 15 | @Component({ 16 | selector: 'app-bomb', 17 | template: ` 18 | @if (gltf(); as gltf) { 19 | 25 | 26 | 27 | } 28 | `, 29 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 30 | changeDetection: ChangeDetectionStrategy.OnPush, 31 | imports: [NgtsMeshTransmissionMaterial], 32 | }) 33 | export default class Bomb { 34 | protected gltf = injectGLTF(() => bombUrl); 35 | } 36 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/routed/current-route.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, input } from '@angular/core'; 2 | import { NgtVector3 } from 'angular-three'; 3 | import { NgtsText } from 'angular-three-soba/abstractions'; 4 | 5 | @Component({ 6 | selector: 'app-current-route', 7 | template: ` 8 | 12 | `, 13 | changeDetection: ChangeDetectionStrategy.OnPush, 14 | imports: [NgtsText], 15 | }) 16 | export class CurrentRoute { 17 | position = input([0, 0, 0]); 18 | text = input.required(); 19 | } 20 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/routed/knot.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; 2 | import { NgtArgs } from 'angular-three'; 3 | import { NgtsMeshTransmissionMaterial } from 'angular-three-soba/materials'; 4 | 5 | @Component({ 6 | selector: 'app-knot', 7 | template: ` 8 | 9 | 10 | 11 | 12 | `, 13 | imports: [NgtArgs, NgtsMeshTransmissionMaterial], 14 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 15 | changeDetection: ChangeDetectionStrategy.OnPush, 16 | }) 17 | export default class Knot {} 18 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/routed/routed.routes.ts: -------------------------------------------------------------------------------- 1 | import { Routes } from '@angular/router'; 2 | 3 | const routes: Routes = [ 4 | { 5 | path: 'knot', 6 | loadComponent: () => import('./knot'), 7 | }, 8 | { 9 | path: 'torus', 10 | loadComponent: () => import('./torus'), 11 | }, 12 | { 13 | path: 'bomb', 14 | loadComponent: () => import('./bomb'), 15 | }, 16 | { 17 | path: '', 18 | redirectTo: 'knot', 19 | pathMatch: 'full', 20 | }, 21 | ]; 22 | 23 | export default routes; 24 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/routed/torus.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; 2 | import { NgtArgs } from 'angular-three'; 3 | import { NgtsMeshTransmissionMaterial } from 'angular-three-soba/materials'; 4 | 5 | @Component({ 6 | selector: 'app-torus', 7 | template: ` 8 | 9 | 10 | 11 | 12 | `, 13 | imports: [NgtArgs, NgtsMeshTransmissionMaterial], 14 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 15 | changeDetection: ChangeDetectionStrategy.OnPush, 16 | }) 17 | export default class Torus {} 18 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/aquarium/aquarium.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { Experience } from './experience'; 4 | 5 | @Component({ 6 | template: ` 7 | 13 | `, 14 | changeDetection: ChangeDetectionStrategy.OnPush, 15 | host: { class: 'aquarium' }, 16 | imports: [NgtCanvas], 17 | }) 18 | export default class Aquarium { 19 | protected sceneGraph = Experience; 20 | } 21 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/aquarium/model_52a_-_kemps_ridley_sea_turtle_no_id-transformed.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/src/app/soba/aquarium/model_52a_-_kemps_ridley_sea_turtle_no_id-transformed.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/aquarium/shapes-transformed.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/src/app/soba/aquarium/shapes-transformed.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/backdrop-cable/backdrop-cable.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { Experience } from './experience'; 4 | 5 | @Component({ 6 | template: ` 7 | 8 | `, 9 | changeDetection: ChangeDetectionStrategy.OnPush, 10 | imports: [NgtCanvas], 11 | host: { class: 'Backdrop-cable' }, 12 | }) 13 | export default class BackdropCable { 14 | protected sceneGraph = Experience; 15 | } 16 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/bruno-simons-20k/bruno-simons-20k.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { ToggleButton } from '../../toggle-button'; 4 | import { debug, Experience, withN8ao } from './experience'; 5 | 6 | @Component({ 7 | template: ` 8 | 15 | 16 |
17 | 18 | 19 |
20 | `, 21 | changeDetection: ChangeDetectionStrategy.OnPush, 22 | host: { class: 'bruno-simons-2k-soba' }, 23 | imports: [NgtCanvas, ToggleButton], 24 | }) 25 | export default class BrunoSimons20k { 26 | protected sceneGraph = Experience; 27 | protected debug = debug; 28 | protected withN8ao = withN8ao; 29 | } 30 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/camera-scroll/experience.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; 2 | import { NgtsEnvironment } from 'angular-three-soba/staging'; 3 | import { Model } from './model'; 4 | 5 | @Component({ 6 | template: ` 7 | 8 | 9 | 10 | `, 11 | imports: [Model, NgtsEnvironment], 12 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 13 | changeDetection: ChangeDetectionStrategy.OnPush, 14 | host: { class: 'camera-scroll-soba-experience' }, 15 | }) 16 | export class Experience { 17 | protected readonly Math = Math; 18 | } 19 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/camera-scroll/model-transformed.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/apps/kitchen-sink/src/app/soba/camera-scroll/model-transformed.glb -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/camera-scroll/overlay.ts: -------------------------------------------------------------------------------- 1 | import { DOCUMENT } from '@angular/common'; 2 | import { ChangeDetectionStrategy, Component, ElementRef, inject, viewChild } from '@angular/core'; 3 | import { SCROLL } from './camera-scroll'; 4 | 5 | @Component({ 6 | selector: 'app-overlay', 7 | templateUrl: './overlay.html', 8 | changeDetection: ChangeDetectionStrategy.OnPush, 9 | styleUrl: './overlay.css', 10 | }) 11 | export class Overlay { 12 | private captionRef = viewChild.required>('caption'); 13 | 14 | private document = inject(DOCUMENT); 15 | private scroll = inject(SCROLL); 16 | 17 | onScroll(event: Event) { 18 | const window = this.document.defaultView; 19 | if (!window) return; 20 | 21 | const target = event.target as HTMLDivElement; 22 | this.scroll.value = target.scrollTop / (target.scrollHeight - window.innerHeight); 23 | this.captionRef().nativeElement.innerText = this.scroll.value.toFixed(2); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/decal/decal.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { Experience } from './experience'; 4 | 5 | @Component({ 6 | template: ` 7 | 8 | `, 9 | changeDetection: ChangeDetectionStrategy.OnPush, 10 | host: { class: 'decal-soba' }, 11 | imports: [NgtCanvas], 12 | }) 13 | export default class Decal { 14 | protected scene = Experience; 15 | } 16 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/hud/hud.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { Experience } from './experience'; 4 | 5 | @Component({ 6 | template: ` 7 | 8 | `, 9 | imports: [NgtCanvas], 10 | changeDetection: ChangeDetectionStrategy.OnPush, 11 | host: { class: 'hud-soba' }, 12 | }) 13 | export default class RenderTexture { 14 | protected scene = Experience; 15 | } 16 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/instanced-vertex-colors/instanced-vertex-colors.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { Experience } from './experience'; 4 | 5 | @Component({ 6 | template: ` 7 | 12 | `, 13 | changeDetection: ChangeDetectionStrategy.OnPush, 14 | imports: [NgtCanvas], 15 | host: { class: 'instanced-vertex-colors-soba' }, 16 | }) 17 | export default class InstancedVertexColors { 18 | protected sceneGraph = Experience; 19 | } 20 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/instances/instances.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { Experience } from './exprience'; 4 | 5 | @Component({ 6 | template: ` 7 | 8 | `, 9 | changeDetection: ChangeDetectionStrategy.OnPush, 10 | host: { class: 'instances-soba' }, 11 | imports: [NgtCanvas], 12 | }) 13 | export default class Instances { 14 | protected scene = Experience; 15 | } 16 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/lod/lod.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { NgtsLoader } from 'angular-three-soba/loaders'; 4 | import { NgtsStats } from 'angular-three-soba/stats'; 5 | import { Experience } from './experience'; 6 | 7 | @Component({ 8 | template: ` 9 | 10 | 11 | `, 12 | changeDetection: ChangeDetectionStrategy.OnPush, 13 | imports: [NgtCanvas, NgtsLoader, NgtsStats], 14 | host: { class: 'lod-soba' }, 15 | }) 16 | export default class LOD { 17 | protected scene = Experience; 18 | } 19 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/lowpoly-earth/lowpoly-earth.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { Experience } from './experience'; 4 | 5 | @Component({ 6 | template: ` 7 | 8 | `, 9 | changeDetection: ChangeDetectionStrategy.OnPush, 10 | host: { class: 'lowpoly-earth-soba' }, 11 | imports: [NgtCanvas], 12 | }) 13 | export default class LowpolyEarth { 14 | protected sceneGraph = Experience; 15 | } 16 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/porsche/color.ts: -------------------------------------------------------------------------------- 1 | import { computed, signal } from '@angular/core'; 2 | 3 | export const color = signal('maroon'); 4 | export const colorAsHex = computed(() => toHex(color())); 5 | 6 | // convert various colors values to hex 7 | function toHex(value: string) { 8 | const ctx = document.createElement('canvas').getContext('2d')!; 9 | ctx.fillStyle = value; 10 | return ctx.fillStyle; 11 | } 12 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/portal-shapes/constants.ts: -------------------------------------------------------------------------------- 1 | import { Experience as BasicExperience } from '../basic/experience'; 2 | import { Experience as BrunoExperience } from '../bruno-simons-20k/experience'; 3 | import { Experience as InstancedVertexColorsExperience } from '../instanced-vertex-colors/experience'; 4 | import { Experience as LodExperience } from '../lod/experience'; 5 | import { Experience as LowpolyEarthExperience } from '../lowpoly-earth/experience'; 6 | import { Experience as ShakyExperience } from '../shaky/experience'; 7 | import { Experience as StarsExperience } from '../stars/experience'; 8 | 9 | export const Scenes = { 10 | basic: BasicExperience, 11 | instancedVertexColors: InstancedVertexColorsExperience, 12 | lowpolyEarth: LowpolyEarthExperience, 13 | shaky: ShakyExperience, 14 | stars: StarsExperience, 15 | lod: LodExperience, 16 | bruno: BrunoExperience, 17 | } as const; 18 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/portal-shapes/portal-shapes.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { Experience } from './experience'; 4 | 5 | @Component({ 6 | template: ` 7 | 8 | double click to zoom in/out 9 | `, 10 | changeDetection: ChangeDetectionStrategy.OnPush, 11 | imports: [NgtCanvas], 12 | }) 13 | export default class PortalShapes { 14 | protected sceneGraph = Experience; 15 | } 16 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/render-texture/render-texture.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { Experience } from './experience'; 4 | 5 | @Component({ 6 | template: ` 7 | 8 | `, 9 | imports: [NgtCanvas], 10 | changeDetection: ChangeDetectionStrategy.OnPush, 11 | host: { class: 'fbo-render-texture' }, 12 | }) 13 | export default class RenderTexture { 14 | protected scene = Experience; 15 | } 16 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/simple-sound-analyser/simple-sound-analyser.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { AudioStore } from './audio.store'; 4 | import { Experience } from './experience'; 5 | import { Overlay } from './overlay'; 6 | 7 | @Component({ 8 | template: ` 9 | 10 | 11 | `, 12 | imports: [NgtCanvas, Overlay], 13 | changeDetection: ChangeDetectionStrategy.OnPush, 14 | host: { class: 'simple-sound-analyser-soba block h-full w-full' }, 15 | styles: ` 16 | :host { 17 | background: linear-gradient(15deg, rgb(82, 81, 88) 0%, rgb(255, 247, 248) 100%); 18 | } 19 | `, 20 | providers: [AudioStore], 21 | }) 22 | export default class SimpleSoundAnalyser { 23 | protected sceneGraph = Experience; 24 | } 25 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/simple-sound-analyser/tracks.ts: -------------------------------------------------------------------------------- 1 | import { computed, signal } from '@angular/core'; 2 | 3 | export const tracks = [ 4 | { sound: 'drums', positionZ: 0.25 }, 5 | { sound: 'synth', positionZ: -0.25 }, 6 | { sound: 'snare', positionZ: 0 }, 7 | ] as const; 8 | 9 | export const zoomIndex = signal(Math.floor(Math.random() * tracks.length)); 10 | export const zoomTrack = computed(() => tracks[zoomIndex()].sound); 11 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/simple-sound-analyser/zoom.ts: -------------------------------------------------------------------------------- 1 | import { Directive, inject, input } from '@angular/core'; 2 | import { injectBeforeRender } from 'angular-three'; 3 | import { PerspectiveCamera } from 'three'; 4 | import { Track } from './track'; 5 | 6 | @Directive({ selector: 'app-track[zoom]' }) 7 | export class Zoom { 8 | enabled = input(false, { alias: 'zoom' }); 9 | 10 | track = inject(Track); 11 | 12 | constructor() { 13 | injectBeforeRender(({ camera }) => { 14 | const enabled = this.enabled(); 15 | if (!enabled) return; 16 | 17 | const audio = this.track.audio(); 18 | if (!audio) return; 19 | 20 | // Set the cameras field of view according to the frequency average 21 | (camera as PerspectiveCamera).fov = 25 - audio.avg / 15; 22 | camera.updateProjectionMatrix(); 23 | }); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/skydiving/skydiving.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { NgtsLoader } from 'angular-three-soba/loaders'; 4 | import { SceneGraph } from './scene-graph'; 5 | 6 | @Component({ 7 | selector: 'app-sky-diving', 8 | template: ` 9 | 10 | 11 | `, 12 | imports: [NgtCanvas, NgtsLoader], 13 | changeDetection: ChangeDetectionStrategy.OnPush, 14 | host: { class: 'skydiving-soba' }, 15 | }) 16 | export default class SkyDiving { 17 | protected sceneGraph = SceneGraph; 18 | } 19 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/skydiving/world.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; 2 | import { NgtArgs } from 'angular-three'; 3 | import { injectTexture } from 'angular-three-soba/loaders'; 4 | import { BackSide } from 'three'; 5 | 6 | @Component({ 7 | selector: 'app-world', 8 | template: ` 9 | 10 | 11 | 12 | 13 | `, 14 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 15 | changeDetection: ChangeDetectionStrategy.OnPush, 16 | imports: [NgtArgs], 17 | }) 18 | export class World { 19 | protected readonly BackSide = BackSide; 20 | protected skyTexture = injectTexture(() => './sky-texture.jpg'); 21 | } 22 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/starbucks/starbucks.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { Experience } from './experience'; 4 | 5 | @Component({ 6 | template: ` 7 | 8 | `, 9 | changeDetection: ChangeDetectionStrategy.OnPush, 10 | imports: [NgtCanvas], 11 | host: { class: 'starbucks-soba' }, 12 | }) 13 | export default class Starbucks { 14 | protected scene = Experience; 15 | } 16 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/soba/stars/stars.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { NgtCanvas } from 'angular-three'; 3 | import { Experience } from './experience'; 4 | 5 | @Component({ 6 | template: ` 7 |
8 |

11 | angular three 12 |

13 |
14 | 15 | `, 16 | changeDetection: ChangeDetectionStrategy.OnPush, 17 | host: { class: 'stars-soba' }, 18 | styles: ` 19 | :host { 20 | display: block; 21 | height: 100%; 22 | width: 100%; 23 | background: #12071f; 24 | } 25 | 26 | h1 { 27 | background: linear-gradient(30deg, #c850c0, #ffcc70); 28 | -webkit-background-clip: text; 29 | -webkit-text-fill-color: transparent; 30 | } 31 | `, 32 | imports: [NgtCanvas], 33 | }) 34 | export default class Stars { 35 | protected sceneGraph = Experience; 36 | } 37 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/app/toggle-button.ts: -------------------------------------------------------------------------------- 1 | import { computed, Directive, model } from '@angular/core'; 2 | 3 | @Directive({ 4 | selector: 'button[toggleButton]', 5 | host: { 6 | class: 'border rounded px-2 py-1', 7 | '(click)': 'onClick()', 8 | '[class]': 'hbClass()', 9 | }, 10 | }) 11 | export class ToggleButton { 12 | value = model.required({ alias: 'toggleButton' }); 13 | 14 | hbClass = computed(() => { 15 | return this.value() ? ['text-white', 'bg-red-600', 'border-red-400'] : ['text-black', 'border-black']; 16 | }); 17 | 18 | onClick() { 19 | this.value.update((prev) => !prev); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Angular Three Demo 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/main.ts: -------------------------------------------------------------------------------- 1 | import { bootstrapApplication } from '@angular/platform-browser'; 2 | import { AppComponent } from './app/app.component'; 3 | import { appConfig } from './app/app.config'; 4 | 5 | bootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err)); 6 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/styles.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /apps/kitchen-sink/src/types.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.blob' { 2 | const url: string; 3 | export default url; 4 | } 5 | 6 | declare module '*.glb' { 7 | const url: string; 8 | export default url; 9 | } 10 | -------------------------------------------------------------------------------- /apps/kitchen-sink/tailwind.config.js: -------------------------------------------------------------------------------- 1 | const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); 2 | const { join } = require('path'); 3 | 4 | /** @type {import('tailwindcss').Config} */ 5 | module.exports = { 6 | content: [join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), ...createGlobPatternsForDependencies(__dirname)], 7 | theme: { 8 | extend: {}, 9 | }, 10 | plugins: [], 11 | }; 12 | -------------------------------------------------------------------------------- /apps/kitchen-sink/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [] 6 | }, 7 | "files": ["src/main.ts"], 8 | "include": ["src/**/*.d.ts"], 9 | "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /apps/kitchen-sink/tsconfig.editor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["src/**/*.ts"], 4 | "compilerOptions": {}, 5 | "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] 6 | } 7 | -------------------------------------------------------------------------------- /apps/kitchen-sink/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "useDefineForClassFields": false, 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "strict": true, 8 | "noImplicitOverride": true, 9 | "noPropertyAccessFromIndexSignature": true, 10 | "noImplicitReturns": true, 11 | "noFallthroughCasesInSwitch": true 12 | }, 13 | "files": [], 14 | "include": [], 15 | "references": [ 16 | { 17 | "path": "./tsconfig.editor.json" 18 | }, 19 | { 20 | "path": "./tsconfig.app.json" 21 | } 22 | ], 23 | "extends": "../../tsconfig.base.json", 24 | "angularCompilerOptions": { 25 | "enableI18nLegacyMessageIdFormat": false, 26 | "strictInjectionParameters": true, 27 | "strictInputAccessModifiers": true, 28 | "strictTemplates": true 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /cz.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('cz-git').UserConfig['prompt']} */ 2 | module.exports = { 3 | types: [ 4 | { value: 'feat', name: 'feat: A new feature', emoji: ':sparkles:' }, 5 | { value: 'fix', name: 'fix: A bug fix', emoji: ':bug:' }, 6 | { value: 'docs', name: 'docs: Documentation only changes', emoji: ':memo:' }, 7 | { 8 | value: 'refactor', 9 | name: 'refactor: A code change that neither fixes a bug nor adds a feature', 10 | emoji: ':recycle:', 11 | }, 12 | { value: 'perf', name: 'perf: A code change that improves performance', emoji: ':zap:' }, 13 | { 14 | value: 'testing', 15 | name: 'testing: Adding missing tests or correcting existing tests', 16 | emoji: ':white_check_mark:', 17 | }, 18 | { value: 'chore', name: "chore: Other changes that don't modify src or test files", emoji: ':hammer:' }, 19 | ], 20 | scopes: [ 21 | { name: 'core' }, 22 | { name: 'soba' }, 23 | { name: 'cannon' }, 24 | { name: 'postprocessing' }, 25 | { name: 'plugin' }, 26 | { name: 'docs' }, 27 | { name: 'testing' }, 28 | ], 29 | }; 30 | -------------------------------------------------------------------------------- /jest.config.ts: -------------------------------------------------------------------------------- 1 | import { getJestProjectsAsync } from '@nx/jest'; 2 | 3 | export default async () => ({ 4 | projects: await getJestProjectsAsync(), 5 | }); 6 | -------------------------------------------------------------------------------- /jest.preset.js: -------------------------------------------------------------------------------- 1 | const nxPreset = require('@nx/jest/preset').default; 2 | 3 | module.exports = { ...nxPreset }; 4 | -------------------------------------------------------------------------------- /libs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/.gitkeep -------------------------------------------------------------------------------- /libs/cannon/body/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/cannon/body/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/body'; 2 | export type * from './lib/types'; 3 | -------------------------------------------------------------------------------- /libs/cannon/constraint/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/cannon/constraint/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/constraint'; 2 | -------------------------------------------------------------------------------- /libs/cannon/debug/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/cannon/debug/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/debug'; 2 | -------------------------------------------------------------------------------- /libs/cannon/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/libs/cannon", 4 | "lib": { 5 | "entryFile": "src/index.ts" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /libs/cannon/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-three-cannon", 3 | "version": "0.0.0-replace", 4 | "publishConfig": { 5 | "access": "public" 6 | }, 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/angular-threejs/angular-three/tree/main/libs/cannon" 10 | }, 11 | "author": { 12 | "name": "Chau Tran", 13 | "email": "nartc7789@gmail.com", 14 | "url": "https://nartc.me" 15 | }, 16 | "description": "Physics Cannon for Angular Three", 17 | "keywords": [ 18 | "angular", 19 | "threejs", 20 | "renderer", 21 | "cannon", 22 | "physics" 23 | ], 24 | "license": "MIT", 25 | "peerDependencies": { 26 | "@angular/common": ">=19.0.0 <20.0.0", 27 | "@angular/core": ">=19.0.0 <20.0.0", 28 | "@pmndrs/cannon-worker-api": "^2.0.0", 29 | "cannon-es": ">=0.20.0 <0.21.0", 30 | "cannon-es-debugger": "^1.0.0", 31 | "three": ">=0.148.0 <0.173.0" 32 | }, 33 | "peerDependenciesMeta": { 34 | "cannon-es-debugger": { 35 | "optional": true 36 | } 37 | }, 38 | "dependencies": { 39 | "tslib": "^2.7.0" 40 | }, 41 | "sideEffects": false 42 | } 43 | -------------------------------------------------------------------------------- /libs/cannon/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cannon", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "libs/cannon/src", 5 | "prefix": "lib", 6 | "projectType": "library", 7 | "tags": [], 8 | "targets": { 9 | "build": { 10 | "executor": "@nx/angular:package", 11 | "outputs": ["{workspaceRoot}/dist/{projectRoot}"], 12 | "options": { 13 | "project": "libs/cannon/ng-package.json" 14 | }, 15 | "configurations": { 16 | "production": { 17 | "tsConfig": "libs/cannon/tsconfig.lib.prod.json" 18 | }, 19 | "development": { 20 | "tsConfig": "libs/cannon/tsconfig.lib.json" 21 | } 22 | }, 23 | "defaultConfiguration": "production" 24 | }, 25 | "test": { 26 | "executor": "@analogjs/vitest-angular:test" 27 | }, 28 | "lint": { 29 | "executor": "@nx/eslint:lint" 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /libs/cannon/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/physics'; 2 | -------------------------------------------------------------------------------- /libs/cannon/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import '@analogjs/vitest-angular/setup-zone'; 2 | 3 | import { getTestBed } from '@angular/core/testing'; 4 | import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; 5 | 6 | getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); 7 | -------------------------------------------------------------------------------- /libs/cannon/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "useDefineForClassFields": false, 5 | "forceConsistentCasingInFileNames": true, 6 | "strict": true, 7 | "noImplicitOverride": true, 8 | "noPropertyAccessFromIndexSignature": true, 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true 11 | }, 12 | "files": [], 13 | "include": [], 14 | "references": [ 15 | { 16 | "path": "./tsconfig.lib.json" 17 | }, 18 | { 19 | "path": "./tsconfig.spec.json" 20 | } 21 | ], 22 | "extends": "../../tsconfig.base.json", 23 | "angularCompilerOptions": { 24 | "enableI18nLegacyMessageIdFormat": false, 25 | "strictInjectionParameters": true, 26 | "strictInputAccessModifiers": true, 27 | "strictTemplates": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /libs/cannon/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "declaration": true, 6 | "declarationMap": true, 7 | "inlineSources": true, 8 | "types": ["node"] 9 | }, 10 | "exclude": ["**/*.spec.ts", "src/test-setup.ts", "**/*.test.ts"], 11 | "include": ["**/*.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /libs/cannon/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.lib.json", 3 | "compilerOptions": { 4 | "declarationMap": false 5 | }, 6 | "angularCompilerOptions": { 7 | "compilationMode": "partial" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /libs/cannon/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "target": "es2016", 6 | "types": ["node", "vitest/globals"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /libs/cannon/vite.config.mts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import angular from '@analogjs/vite-plugin-angular'; 4 | 5 | import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; 6 | 7 | import { defineConfig } from 'vite'; 8 | 9 | // https://vitejs.dev/config/ 10 | export default defineConfig(({ mode }) => { 11 | return { 12 | plugins: [angular(), nxViteTsPaths()], 13 | test: { 14 | globals: true, 15 | environment: 'jsdom', 16 | setupFiles: ['src/test-setup.ts'], 17 | include: ['**/*.spec.ts'], 18 | reporters: ['default'], 19 | }, 20 | define: { 21 | 'import.meta.vitest': mode !== 'production', 22 | }, 23 | }; 24 | }); 25 | -------------------------------------------------------------------------------- /libs/core/nativescript/README.md: -------------------------------------------------------------------------------- 1 | # angular-three/nativescript 2 | 3 | Secondary entry point of `angular-three`. It can be used by importing from `angular-three/nativescript`. 4 | 5 | Depends on `@nativescript/canvas`, `@nativescript/canvas-three`, and `@nativescript/canvas-media`. 6 | -------------------------------------------------------------------------------- /libs/core/nativescript/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/core/nativescript/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/canvas'; 2 | -------------------------------------------------------------------------------- /libs/core/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/libs/core", 4 | "lib": { 5 | "entryFile": "src/index.ts" 6 | }, 7 | "allowedNonPeerDependencies": ["@nx/devkit", "nx", "@phenomnomnominal/tsquery"] 8 | } 9 | -------------------------------------------------------------------------------- /libs/core/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "core", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "libs/core/src", 5 | "prefix": "platform", 6 | "projectType": "library", 7 | "tags": [], 8 | "targets": { 9 | "build": { 10 | "executor": "@nx/angular:package", 11 | "outputs": ["{workspaceRoot}/dist/{projectRoot}"], 12 | "options": { 13 | "project": "libs/core/ng-package.json" 14 | }, 15 | "configurations": { 16 | "production": { 17 | "tsConfig": "libs/core/tsconfig.lib.prod.json" 18 | }, 19 | "development": { 20 | "tsConfig": "libs/core/tsconfig.lib.json" 21 | } 22 | }, 23 | "defaultConfiguration": "production" 24 | }, 25 | "test": { 26 | "executor": "@analogjs/vitest-angular:test" 27 | }, 28 | "lint": { 29 | "executor": "@nx/eslint:lint", 30 | "outputs": ["{options.outputFile}"] 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /libs/core/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/canvas'; 2 | export * from './lib/directives/args'; 3 | export * from './lib/directives/parent'; 4 | export * from './lib/directives/selection'; 5 | export * from './lib/html'; 6 | export * from './lib/instance'; 7 | export * from './lib/loader'; 8 | export * from './lib/loop'; 9 | export * from './lib/pipes/hexify'; 10 | export * from './lib/portal'; 11 | export * from './lib/renderer'; 12 | export * from './lib/roots'; 13 | export * from './lib/routed-scene'; 14 | export * from './lib/store'; 15 | export * from './lib/utils/apply-props'; 16 | export * from './lib/utils/attach'; 17 | export * from './lib/utils/before-render'; 18 | export * from './lib/utils/is'; 19 | export * from './lib/utils/make'; 20 | export * from './lib/utils/object-events'; 21 | export * from './lib/utils/output-ref'; 22 | export * from './lib/utils/parameters'; 23 | export * from './lib/utils/resolve-ref'; 24 | export * from './lib/utils/signal-store'; 25 | export * from './lib/utils/update'; 26 | 27 | export type * from './lib/three-types'; 28 | export type * from './lib/types'; 29 | -------------------------------------------------------------------------------- /libs/core/src/lib/renderer/catalogue.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { Mesh } from 'three'; 3 | import { extend, injectCatalogue } from './catalogue'; 4 | 5 | describe('renderer/catalogue', () => { 6 | test('should extend properly', () => { 7 | TestBed.runInInjectionContext(() => { 8 | const catalogue = injectCatalogue(); 9 | expect(catalogue).toEqual({}); 10 | 11 | extend({ Mesh }); 12 | expect(catalogue).toEqual({ Mesh }); 13 | }); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /libs/core/src/lib/renderer/catalogue.ts: -------------------------------------------------------------------------------- 1 | import { createInjectionToken } from 'ngxtension/create-injection-token'; 2 | 3 | export type NgtAnyConstructor = new (...args: any[]) => any; 4 | 5 | const catalogue: Record = {}; 6 | 7 | export function extend(objects: object): void { 8 | Object.assign(catalogue, objects); 9 | } 10 | 11 | export const [injectCatalogue] = createInjectionToken(() => catalogue); 12 | -------------------------------------------------------------------------------- /libs/core/src/lib/renderer/constants.ts: -------------------------------------------------------------------------------- 1 | export const ROUTED_SCENE = '__ngt_renderer_is_routed_scene__'; 2 | export const HTML = '__ngt_renderer_is_html'; 3 | export const NON_ROOT = '__ngt_renderer_is_non_root__'; 4 | export const SPECIAL_INTERNAL_ADD_COMMENT = '__ngt_renderer_add_comment__'; 5 | export const SPECIAL_INTERNAL_SET_PARENT_COMMENT = '__ngt_renderer_set_parent_comment__'; 6 | export const DOM_PARENT = '__ngt_dom_parent__'; 7 | 8 | export const SPECIAL_DOM_TAG = { 9 | NGT_PORTAL: 'ngt-portal', 10 | NGT_PRIMITIVE: 'ngt-primitive', 11 | NGT_VALUE: 'ngt-value', 12 | } as const; 13 | 14 | export const SPECIAL_PROPERTIES = { 15 | RENDER_PRIORITY: 'priority', 16 | ATTACH: 'attach', 17 | RAW_VALUE: 'rawValue', 18 | PARAMETERS: 'parameters', 19 | } as const; 20 | 21 | export const SPECIAL_EVENTS = { 22 | BEFORE_RENDER: 'beforeRender', 23 | UPDATED: 'updated', 24 | ATTACHED: 'attached', 25 | } as const; 26 | 27 | export const THREE_NATIVE_EVENTS = ['added', 'removed', 'childadded', 'childremoved', 'disposed']; 28 | -------------------------------------------------------------------------------- /libs/core/src/lib/renderer/utils.spec.ts: -------------------------------------------------------------------------------- 1 | import { kebabToPascal } from './utils'; 2 | 3 | describe('renderer/utils', () => { 4 | test(kebabToPascal.name, () => { 5 | expect(kebabToPascal('ngt-mesh')).toEqual('NgtMesh'); 6 | expect(kebabToPascal('ngt-mesh-standard-material')).toEqual('NgtMeshStandardMaterial'); 7 | expect(kebabToPascal('ngt-object-3D')).toEqual('NgtObject3D'); 8 | expect(kebabToPascal('ngt-lOD')).toEqual('NgtLOD'); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /libs/core/src/lib/utils/output-ref.ts: -------------------------------------------------------------------------------- 1 | import { OutputEmitterRef } from '@angular/core'; 2 | 3 | export function getEmitter(emitterRef: OutputEmitterRef | undefined) { 4 | if (!emitterRef || !emitterRef['listeners'] || emitterRef['destroyed']) return undefined; 5 | return emitterRef.emit.bind(emitterRef); 6 | } 7 | 8 | export function hasListener(...emitterRefs: (OutputEmitterRef | undefined)[]) { 9 | return emitterRefs.some( 10 | (emitterRef) => 11 | emitterRef && !emitterRef['destroyed'] && emitterRef['listeners'] && emitterRef['listeners'].length > 0, 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /libs/core/src/lib/utils/resolve-ref.ts: -------------------------------------------------------------------------------- 1 | import { ElementRef } from '@angular/core'; 2 | import { is } from './is'; 3 | 4 | export function resolveRef(ref: ElementRef | TObject | undefined): TObject | undefined { 5 | if (is.ref(ref)) { 6 | return ref.nativeElement; 7 | } 8 | 9 | return ref; 10 | } 11 | -------------------------------------------------------------------------------- /libs/core/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import '@analogjs/vitest-angular/setup-zone'; 2 | 3 | import { getTestBed } from '@angular/core/testing'; 4 | import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; 5 | 6 | getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); 7 | -------------------------------------------------------------------------------- /libs/core/testing/README.md: -------------------------------------------------------------------------------- 1 | # angular-three/testing 2 | 3 | Secondary entry point of `angular-three`. It can be used by importing from `angular-three/testing`. 4 | -------------------------------------------------------------------------------- /libs/core/testing/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/core/testing/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/test-bed'; 2 | export * from './lib/test-canvas'; 3 | -------------------------------------------------------------------------------- /libs/core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "useDefineForClassFields": false, 5 | "forceConsistentCasingInFileNames": true, 6 | "strict": true, 7 | "noImplicitOverride": true, 8 | "noPropertyAccessFromIndexSignature": true, 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true 11 | }, 12 | "files": [], 13 | "include": [], 14 | "references": [ 15 | { 16 | "path": "./tsconfig.lib.json" 17 | }, 18 | { 19 | "path": "./tsconfig.spec.json" 20 | } 21 | ], 22 | "extends": "../../tsconfig.base.json", 23 | "angularCompilerOptions": { 24 | "enableI18nLegacyMessageIdFormat": false, 25 | "strictInjectionParameters": true, 26 | "strictInputAccessModifiers": true, 27 | "strictTemplates": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /libs/core/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "declaration": true, 6 | "declarationMap": true, 7 | "inlineSources": true, 8 | "types": [] 9 | }, 10 | "exclude": ["**/*.spec.ts", "test-setup.ts", "**/*.test.ts"], 11 | "include": ["**/*.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /libs/core/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.lib.json", 3 | "compilerOptions": { 4 | "declarationMap": false 5 | }, 6 | "angularCompilerOptions": { 7 | "compilationMode": "partial" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /libs/core/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "target": "es2016", 6 | "types": ["node", "vitest/globals"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /libs/core/vite.config.mts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import angular from '@analogjs/vite-plugin-angular'; 4 | 5 | import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; 6 | 7 | import { defineConfig } from 'vite'; 8 | 9 | // https://vitejs.dev/config/ 10 | export default defineConfig(({ mode }) => { 11 | return { 12 | plugins: [angular(), nxViteTsPaths()], 13 | test: { 14 | globals: true, 15 | environment: 'jsdom', 16 | setupFiles: ['src/test-setup.ts'], 17 | include: ['**/*.spec.ts'], 18 | reporters: ['default'], 19 | }, 20 | define: { 21 | 'import.meta.vitest': mode !== 'production', 22 | }, 23 | }; 24 | }); 25 | -------------------------------------------------------------------------------- /libs/plugin/README.md: -------------------------------------------------------------------------------- 1 | # plugin 2 | 3 | This library was generated with [Nx](https://nx.dev). 4 | 5 | ## Building 6 | 7 | Run `nx build plugin` to build the library. 8 | 9 | ## Running unit tests 10 | 11 | Run `nx test plugin` to execute the unit tests via [Jest](https://jestjs.io). 12 | -------------------------------------------------------------------------------- /libs/plugin/eslint.config.js: -------------------------------------------------------------------------------- 1 | const { FlatCompat } = require('@eslint/eslintrc'); 2 | const js = require('@eslint/js'); 3 | const baseConfig = require('../../eslint.config.js'); 4 | 5 | const compat = new FlatCompat({ 6 | baseDirectory: __dirname, 7 | recommendedConfig: js.configs.recommended, 8 | }); 9 | 10 | module.exports = [ 11 | ...baseConfig, 12 | { 13 | files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'], 14 | // Override or add rules here 15 | rules: {}, 16 | }, 17 | { 18 | files: ['**/*.ts', '**/*.tsx'], 19 | // Override or add rules here 20 | rules: {}, 21 | }, 22 | { 23 | files: ['**/*.js', '**/*.jsx'], 24 | // Override or add rules here 25 | rules: {}, 26 | }, 27 | { 28 | files: ['**/*.json'], 29 | rules: { 30 | '@nx/dependency-checks': 'error', 31 | }, 32 | languageOptions: { 33 | parser: require('jsonc-eslint-parser'), 34 | }, 35 | }, 36 | { 37 | files: ['./package.json', './generators.json'], 38 | rules: { 39 | '@nx/nx-plugin-checks': 'error', 40 | }, 41 | languageOptions: { 42 | parser: require('jsonc-eslint-parser'), 43 | }, 44 | }, 45 | ]; 46 | -------------------------------------------------------------------------------- /libs/plugin/generators.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-three-plugin", 3 | "generators": { 4 | "init": { 5 | "factory": "./src/generators/init/generator", 6 | "schema": "./src/generators/init/schema.json", 7 | "description": "Init Angular Three with proper packages and config" 8 | }, 9 | "add-soba": { 10 | "factory": "./src/generators/add-soba/generator", 11 | "schema": "./src/generators/add-soba/schema.json", 12 | "description": "Add angular-three-soba to your project" 13 | } 14 | }, 15 | "schematics": { 16 | "ng-add": { 17 | "factory": "./src/generators/init/compat", 18 | "schema": "./src/generators/init/schema.json", 19 | "description": "Add Angular Three with proper packages and config" 20 | }, 21 | "add-soba": { 22 | "factory": "./src/generators/add-soba/compat", 23 | "schema": "./src/generators/add-soba/schema.json", 24 | "description": "Add angular-three-soba to your project" 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/plugin/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'plugin', 4 | preset: '../../jest.preset.js', 5 | transform: { 6 | '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }], 7 | }, 8 | moduleFileExtensions: ['ts', 'js', 'html'], 9 | coverageDirectory: '../../coverage/libs/plugin', 10 | }; 11 | -------------------------------------------------------------------------------- /libs/plugin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "plugin", 3 | "type": "commonjs" 4 | } 5 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/add-soba/compat.ts: -------------------------------------------------------------------------------- 1 | import { convertNxGenerator } from '@nx/devkit'; 2 | import addSoba from './generator'; 3 | 4 | export default convertNxGenerator(addSoba); 5 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/add-soba/generator.spec.ts: -------------------------------------------------------------------------------- 1 | import { Tree } from '@nx/devkit'; 2 | import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; 3 | import { initGenerator } from '../init/generator'; 4 | 5 | describe('add-soba generator', () => { 6 | let tree: Tree; 7 | 8 | beforeEach(() => { 9 | tree = createTreeWithEmptyWorkspace(); 10 | }); 11 | 12 | it('should run successfully', async () => { 13 | await initGenerator(tree, { skipGenerateExperience: true }); 14 | expect(true).toBe(true); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/add-soba/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$id": "AddSoba", 3 | "title": "Add Soba" 4 | } 5 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/init/compat.ts: -------------------------------------------------------------------------------- 1 | import { convertNxGenerator } from '@nx/devkit'; 2 | import init from './generator'; 3 | 4 | export default convertNxGenerator(init); 5 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/init/files/experience/experience.component.ts__tmpl__: -------------------------------------------------------------------------------- 1 | import { CUSTOM_ELEMENTS_SCHEMA, Component, viewChild, ElementRef, ChangeDetectionStrategy } from '@angular/core'; 2 | import { extend, injectBeforeRender } from 'angular-three'; 3 | import { Mesh, BoxGeometry, MeshBasicMaterial } from 'three'; 4 | 5 | extend({ Mesh, BoxGeometry, MeshBasicMaterial }); 6 | 7 | @Component({ 8 | template: ` 9 | 10 | 11 | 12 | 13 | `, 14 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 15 | changeDetection: ChangeDetectionStrategy.OnPush, 16 | }) 17 | export class Experience { 18 | meshRef = viewChild.required>('mesh'); 19 | 20 | constructor() { 21 | injectBeforeRender(({ delta }) => { 22 | const mesh = this.meshRef().nativeElement; 23 | mesh.rotation.x += delta; 24 | mesh.rotation.y += delta; 25 | }) 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/init/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "cli": "nx", 3 | "$id": "Init", 4 | "title": "Init Angular Three", 5 | "type": "object", 6 | "properties": { 7 | "skipGenerateExperience": { 8 | "type": "boolean", 9 | "description": "Skip generating Experience component", 10 | "default": false 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/version.ts: -------------------------------------------------------------------------------- 1 | export const ANGULAR_THREE_VERSION = '^3.0.0'; 2 | export const THREE_VERSION = '^0.171.0'; 3 | export const THREE_TYPE_VERSION = '^0.171.0'; 4 | export const NGXTENSION_VERSION = '^4.0.0'; 5 | 6 | export const SOBA_PEER_DEPENDENCIES = { 7 | 'three-stdlib': '^2.0.0', 8 | '@pmndrs/vanilla': '^1.20.0', 9 | '@monogrid/gainmap-js': '^3.0.0', 10 | 'camera-controls': '^2.8.0', 11 | 'hls.js': '^1.5.0', 12 | maath: '~0.10.0', 13 | meshline: '^3.1.0', 14 | 'stats-gl': '^2.0.0', 15 | 'three-custom-shader-material': '~6.2.0', 16 | 'three-mesh-bvh': '~0.8.0', 17 | 'troika-three-text': '~0.52.0', 18 | } as const; 19 | -------------------------------------------------------------------------------- /libs/plugin/src/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/plugin/src/index.ts -------------------------------------------------------------------------------- /libs/plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "verbatimModuleSyntax": false 7 | }, 8 | "files": [], 9 | "include": [], 10 | "references": [ 11 | { 12 | "path": "./tsconfig.lib.json" 13 | }, 14 | { 15 | "path": "./tsconfig.spec.json" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /libs/plugin/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "declaration": true, 6 | "types": ["node"] 7 | }, 8 | "include": ["src/**/*.ts"], 9 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /libs/plugin/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts", "src/**/*.d.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /libs/postprocessing/n8ao/README.md: -------------------------------------------------------------------------------- 1 | # angular-three-postprocessing/n8ao 2 | 3 | Secondary entry point of `angular-three-postprocessing`. It can be used by importing from `angular-three-postprocessing/n8ao`. 4 | -------------------------------------------------------------------------------- /libs/postprocessing/n8ao/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/postprocessing/n8ao/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/n8ao'; 2 | -------------------------------------------------------------------------------- /libs/postprocessing/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/libs/postprocessing", 4 | "lib": { 5 | "entryFile": "src/index.ts" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /libs/postprocessing/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-three-postprocessing", 3 | "version": "0.0.0-replace", 4 | "publishConfig": { 5 | "access": "public" 6 | }, 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/angular-threejs/angular-three/tree/main/libs/postprocessing" 10 | }, 11 | "author": { 12 | "name": "Chau Tran", 13 | "email": "nartc7789@gmail.com", 14 | "url": "https://nartc.me" 15 | }, 16 | "description": "Postprocessing for Angular Three", 17 | "keywords": [ 18 | "angular", 19 | "threejs", 20 | "renderer", 21 | "postprocessing" 22 | ], 23 | "license": "MIT", 24 | "peerDependencies": { 25 | "@angular/common": ">=19.0.0 <20.0.0", 26 | "@angular/core": ">=19.0.0 <20.0.0", 27 | "maath": ">=0.10.0 <0.11.0", 28 | "n8ao": ">=1.9.4 <2.0.0", 29 | "postprocessing": "^6.0.0", 30 | "three": ">=0.148.0 <0.173.0", 31 | "three-stdlib": "^2.0.0" 32 | }, 33 | "peerDependenciesMeta": { 34 | "n8ao": { 35 | "optional": true 36 | } 37 | }, 38 | "dependencies": { 39 | "tslib": "^2.7.0" 40 | }, 41 | "sideEffects": false, 42 | "web-types": [ 43 | "../../node_modules/angular-three/web-types.json", 44 | "node_modules/angular-three/web-types.json" 45 | ] 46 | } 47 | -------------------------------------------------------------------------------- /libs/postprocessing/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "postprocessing", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "libs/postprocessing/src", 5 | "prefix": "lib", 6 | "projectType": "library", 7 | "tags": [], 8 | "targets": { 9 | "build": { 10 | "executor": "@nx/angular:package", 11 | "outputs": ["{workspaceRoot}/dist/{projectRoot}"], 12 | "options": { 13 | "project": "libs/postprocessing/ng-package.json" 14 | }, 15 | "configurations": { 16 | "production": { 17 | "tsConfig": "libs/postprocessing/tsconfig.lib.prod.json" 18 | }, 19 | "development": { 20 | "tsConfig": "libs/postprocessing/tsconfig.lib.json" 21 | } 22 | }, 23 | "defaultConfiguration": "production" 24 | }, 25 | "test": { 26 | "executor": "@analogjs/vitest-angular:test" 27 | }, 28 | "lint": { 29 | "executor": "@nx/eslint:lint" 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /libs/postprocessing/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/effect'; 2 | export * from './lib/effect-composer'; 3 | export * from './lib/effects'; 4 | -------------------------------------------------------------------------------- /libs/postprocessing/src/lib/effects/bloom.ts: -------------------------------------------------------------------------------- 1 | import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, inject, input } from '@angular/core'; 2 | import { NgtArgs, extend } from 'angular-three'; 3 | import { BlendFunction, BloomEffect, BloomEffectOptions } from 'postprocessing'; 4 | import { NgtpEffect, NgtpEffectBlendMode, provideDefaultEffectOptions } from '../effect'; 5 | 6 | extend({ BloomEffect }); 7 | 8 | @Component({ 9 | selector: 'ngtp-bloom', 10 | template: ` 11 | 12 | 13 | 14 | 15 | `, 16 | imports: [NgtArgs, NgtpEffectBlendMode], 17 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 18 | changeDetection: ChangeDetectionStrategy.OnPush, 19 | hostDirectives: [{ directive: NgtpEffect, inputs: ['blendFunction', 'opacity'] }], 20 | providers: [provideDefaultEffectOptions({ blendFunction: BlendFunction.ADD })], 21 | }) 22 | export class NgtpBloom { 23 | effect = inject(NgtpEffect, { host: true }); 24 | options = input({} as Omit); 25 | } 26 | -------------------------------------------------------------------------------- /libs/postprocessing/src/lib/effects/brightness-contrast.ts: -------------------------------------------------------------------------------- 1 | import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, inject, input } from '@angular/core'; 2 | import { NgtArgs, extend } from 'angular-three'; 3 | import { BrightnessContrastEffect } from 'postprocessing'; 4 | import { NgtpEffect, NgtpEffectBlendMode } from '../effect'; 5 | 6 | extend({ BrightnessContrastEffect }); 7 | 8 | export type BrightnessEffectOptions = NonNullable[0]>; 9 | 10 | @Component({ 11 | selector: 'ngtp-brightness-contrast', 12 | template: ` 13 | 14 | 15 | 16 | 17 | `, 18 | imports: [NgtArgs, NgtpEffectBlendMode], 19 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 20 | changeDetection: ChangeDetectionStrategy.OnPush, 21 | hostDirectives: [{ directive: NgtpEffect, inputs: ['blendFunction', 'opacity'] }], 22 | }) 23 | export class NgtpBrightnessContrast { 24 | effect = inject(NgtpEffect, { host: true }); 25 | options = input({} as Omit); 26 | } 27 | -------------------------------------------------------------------------------- /libs/postprocessing/src/lib/effects/chromatic-abberation.ts: -------------------------------------------------------------------------------- 1 | import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, inject, input } from '@angular/core'; 2 | import { NgtArgs, extend } from 'angular-three'; 3 | import { ChromaticAberrationEffect } from 'postprocessing'; 4 | import { NgtpEffect, NgtpEffectBlendMode } from '../effect'; 5 | 6 | extend({ ChromaticAberrationEffect }); 7 | 8 | export type ChromaticAberrationEffectOptions = Partial< 9 | NonNullable[0]> 10 | >; 11 | 12 | @Component({ 13 | selector: 'ngtp-chromatic-aberration', 14 | template: ` 15 | 16 | 17 | 18 | 19 | `, 20 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 21 | changeDetection: ChangeDetectionStrategy.OnPush, 22 | imports: [NgtArgs, NgtpEffectBlendMode], 23 | hostDirectives: [{ directive: NgtpEffect, inputs: ['blendFunction', 'opacity'] }], 24 | }) 25 | export class NgtpChromaticAberration { 26 | effect = inject(NgtpEffect, { host: true }); 27 | options = input({} as Omit); 28 | } 29 | -------------------------------------------------------------------------------- /libs/postprocessing/src/lib/effects/color-average.ts: -------------------------------------------------------------------------------- 1 | import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, input } from '@angular/core'; 2 | import { NgtArgs, extend } from 'angular-three'; 3 | import { mergeInputs } from 'ngxtension/inject-inputs'; 4 | import { BlendFunction, ColorAverageEffect } from 'postprocessing'; 5 | 6 | extend({ ColorAverageEffect }); 7 | 8 | @Component({ 9 | selector: 'ngtp-color-average', 10 | template: ` 11 | 12 | 13 | 14 | `, 15 | imports: [NgtArgs], 16 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 17 | changeDetection: ChangeDetectionStrategy.OnPush, 18 | }) 19 | export class NgtpColorAverage { 20 | options = input( 21 | { blendFunction: BlendFunction.NORMAL }, 22 | { transform: mergeInputs({ blendFunction: BlendFunction.NORMAL }) }, 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /libs/postprocessing/src/lib/effects/color-depth.ts: -------------------------------------------------------------------------------- 1 | import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, inject, input } from '@angular/core'; 2 | import { NgtArgs, extend } from 'angular-three'; 3 | import { ColorDepthEffect } from 'postprocessing'; 4 | import { NgtpEffect, NgtpEffectBlendMode } from '../effect'; 5 | 6 | extend({ ColorDepthEffect }); 7 | 8 | export type ColorDepthEffectOptions = Partial[0]>>; 9 | 10 | @Component({ 11 | selector: 'ngtp-color-depth', 12 | template: ` 13 | 14 | 15 | 16 | 17 | `, 18 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 19 | changeDetection: ChangeDetectionStrategy.OnPush, 20 | imports: [NgtArgs, NgtpEffectBlendMode], 21 | hostDirectives: [{ directive: NgtpEffect, inputs: ['blendFunction', 'opacity'] }], 22 | }) 23 | export class NgtpColorDepth { 24 | effect = inject(NgtpEffect, { host: true }); 25 | options = input({} as Omit); 26 | } 27 | -------------------------------------------------------------------------------- /libs/postprocessing/src/lib/effects/depth.ts: -------------------------------------------------------------------------------- 1 | import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, inject, input } from '@angular/core'; 2 | import { NgtArgs, extend } from 'angular-three'; 3 | import { DepthEffect } from 'postprocessing'; 4 | import { NgtpEffect, NgtpEffectBlendMode } from '../effect'; 5 | 6 | extend({ DepthEffect }); 7 | 8 | export type DepthEffectOptions = Partial[0]>>; 9 | 10 | @Component({ 11 | selector: 'ngtp-depth', 12 | template: ` 13 | 14 | 15 | 16 | 17 | `, 18 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 19 | changeDetection: ChangeDetectionStrategy.OnPush, 20 | imports: [NgtArgs, NgtpEffectBlendMode], 21 | hostDirectives: [{ directive: NgtpEffect, inputs: ['blendFunction', 'opacity'] }], 22 | }) 23 | export class NgtpDepth { 24 | effect = inject(NgtpEffect, { host: true }); 25 | options = input({} as Omit); 26 | } 27 | -------------------------------------------------------------------------------- /libs/postprocessing/src/lib/effects/dot-screen.ts: -------------------------------------------------------------------------------- 1 | import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, inject, input } from '@angular/core'; 2 | import { NgtArgs, extend } from 'angular-three'; 3 | import { DotScreenEffect } from 'postprocessing'; 4 | import { NgtpEffect, NgtpEffectBlendMode } from '../effect'; 5 | 6 | extend({ DotScreenEffect }); 7 | 8 | export type DotScreenEffectOptions = Partial[0]>>; 9 | 10 | @Component({ 11 | selector: 'ngtp-dot-screen', 12 | template: ` 13 | 14 | 15 | 16 | 17 | `, 18 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 19 | changeDetection: ChangeDetectionStrategy.OnPush, 20 | imports: [NgtArgs, NgtpEffectBlendMode], 21 | hostDirectives: [{ directive: NgtpEffect, inputs: ['blendFunction', 'opacity'] }], 22 | }) 23 | export class NgtpDotScreen { 24 | effect = inject(NgtpEffect, { host: true }); 25 | options = input({} as Omit); 26 | } 27 | -------------------------------------------------------------------------------- /libs/postprocessing/src/lib/effects/fxaa.ts: -------------------------------------------------------------------------------- 1 | import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, inject, input } from '@angular/core'; 2 | import { NgtArgs, extend } from 'angular-three'; 3 | import { FXAAEffect } from 'postprocessing'; 4 | import { NgtpEffect, NgtpEffectBlendMode } from '../effect'; 5 | 6 | extend({ FXAAEffect }); 7 | 8 | export type FXAAEffectOptions = Partial[0]>>; 9 | 10 | @Component({ 11 | selector: 'ngtp-fxaa', 12 | template: ` 13 | 14 | 15 | 16 | 17 | `, 18 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 19 | changeDetection: ChangeDetectionStrategy.OnPush, 20 | imports: [NgtArgs, NgtpEffectBlendMode], 21 | hostDirectives: [{ directive: NgtpEffect, inputs: ['blendFunction', 'opacity'] }], 22 | }) 23 | export class NgtpFXAA { 24 | effect = inject(NgtpEffect, { host: true }); 25 | options = input({} as Omit); 26 | } 27 | -------------------------------------------------------------------------------- /libs/postprocessing/src/lib/effects/hue-saturation.ts: -------------------------------------------------------------------------------- 1 | import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, inject, input } from '@angular/core'; 2 | import { NgtArgs, extend } from 'angular-three'; 3 | import { HueSaturationEffect } from 'postprocessing'; 4 | import { NgtpEffect, NgtpEffectBlendMode } from '../effect'; 5 | 6 | extend({ HueSaturationEffect }); 7 | 8 | export type HueSaturationEffectOptions = Partial[0]>>; 9 | 10 | @Component({ 11 | selector: 'ngtp-hue-saturation', 12 | template: ` 13 | 14 | 15 | 16 | 17 | `, 18 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 19 | changeDetection: ChangeDetectionStrategy.OnPush, 20 | imports: [NgtArgs, NgtpEffectBlendMode], 21 | hostDirectives: [{ directive: NgtpEffect, inputs: ['blendFunction', 'opacity'] }], 22 | }) 23 | export class NgtpHueSaturation { 24 | effect = inject(NgtpEffect, { host: true }); 25 | options = input({} as Omit); 26 | } 27 | -------------------------------------------------------------------------------- /libs/postprocessing/src/lib/effects/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ascii'; 2 | export * from './bloom'; 3 | export * from './brightness-contrast'; 4 | export * from './chromatic-abberation'; 5 | export * from './color-average'; 6 | export * from './color-depth'; 7 | export * from './depth'; 8 | export * from './depth-of-field'; 9 | export * from './dot-screen'; 10 | export * from './fxaa'; 11 | export * from './glitch'; 12 | export * from './god-rays'; 13 | export * from './grid'; 14 | export * from './hue-saturation'; 15 | export * from './lens-flare'; 16 | export * from './lut'; 17 | export * from './noise'; 18 | export * from './outline'; 19 | export * from './pixelation'; 20 | export * from './scanline'; 21 | export * from './sepia'; 22 | export * from './shock-wave'; 23 | export * from './smaa'; 24 | export * from './tilt-shift'; 25 | export * from './tilt-shift-2'; 26 | export * from './tone-mapping'; 27 | export * from './vignette'; 28 | export * from './water'; 29 | -------------------------------------------------------------------------------- /libs/postprocessing/src/lib/effects/noise.ts: -------------------------------------------------------------------------------- 1 | import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, inject, input } from '@angular/core'; 2 | import { NgtArgs, extend } from 'angular-three'; 3 | import { BlendFunction, NoiseEffect } from 'postprocessing'; 4 | import { NgtpEffect, NgtpEffectBlendMode, provideDefaultEffectOptions } from '../effect'; 5 | 6 | extend({ NoiseEffect }); 7 | 8 | export type NoiseEffectOptions = Partial[0]>>; 9 | 10 | @Component({ 11 | selector: 'ngtp-noise', 12 | template: ` 13 | 14 | 15 | 16 | 17 | `, 18 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 19 | changeDetection: ChangeDetectionStrategy.OnPush, 20 | imports: [NgtArgs, NgtpEffectBlendMode], 21 | hostDirectives: [{ directive: NgtpEffect, inputs: ['blendFunction', 'opacity'] }], 22 | providers: [provideDefaultEffectOptions({ blendFunction: BlendFunction.COLOR_DODGE })], 23 | }) 24 | export class NgtpNoise { 25 | effect = inject(NgtpEffect, { host: true }); 26 | options = input({} as Omit); 27 | } 28 | -------------------------------------------------------------------------------- /libs/postprocessing/src/lib/effects/pixelation.ts: -------------------------------------------------------------------------------- 1 | import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, computed, effect, input } from '@angular/core'; 2 | import { NgtArgs, pick } from 'angular-three'; 3 | import { mergeInputs } from 'ngxtension/inject-inputs'; 4 | import { PixelationEffect } from 'postprocessing'; 5 | 6 | export interface PixelationOptions { 7 | granularity: number; 8 | } 9 | @Component({ 10 | selector: 'ngtp-pixelation', 11 | template: ` 12 | 13 | `, 14 | changeDetection: ChangeDetectionStrategy.OnPush, 15 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 16 | imports: [NgtArgs], 17 | }) 18 | export class NgtpPixelation { 19 | options = input({ granularity: 5 } as PixelationOptions, { transform: mergeInputs({ granularity: 5 }) }); 20 | private granularity = pick(this.options, 'granularity'); 21 | 22 | effect = computed(() => new PixelationEffect(this.granularity())); 23 | 24 | constructor() { 25 | effect((onCleanup) => { 26 | const effect = this.effect(); 27 | onCleanup(() => effect.dispose()); 28 | }); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /libs/postprocessing/src/lib/effects/sepia.ts: -------------------------------------------------------------------------------- 1 | import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, inject, input } from '@angular/core'; 2 | import { NgtArgs, extend } from 'angular-three'; 3 | import { SepiaEffect } from 'postprocessing'; 4 | import { NgtpEffect, NgtpEffectBlendMode } from '../effect'; 5 | 6 | extend({ SepiaEffect }); 7 | 8 | export type SepiaEffectOptions = Partial[0]>>; 9 | 10 | @Component({ 11 | selector: 'ngtp-sepia', 12 | template: ` 13 | 14 | 15 | 16 | 17 | `, 18 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 19 | changeDetection: ChangeDetectionStrategy.OnPush, 20 | imports: [NgtArgs, NgtpEffectBlendMode], 21 | hostDirectives: [{ directive: NgtpEffect, inputs: ['blendFunction', 'opacity'] }], 22 | }) 23 | export class NgtpSepia { 24 | effect = inject(NgtpEffect, { host: true }); 25 | options = input({} as Omit); 26 | } 27 | -------------------------------------------------------------------------------- /libs/postprocessing/src/lib/effects/shock-wave.ts: -------------------------------------------------------------------------------- 1 | import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, inject, input } from '@angular/core'; 2 | import { NgtArgs, extend } from 'angular-three'; 3 | import { ShockWaveEffect } from 'postprocessing'; 4 | import { NgtpEffect, NgtpEffectBlendMode } from '../effect'; 5 | 6 | extend({ ShockWaveEffect }); 7 | 8 | export type ShockWaveEffectOptions = Partial[0]>>; 9 | 10 | @Component({ 11 | selector: 'ngtp-shock-wave', 12 | template: ` 13 | 14 | 15 | 16 | 17 | `, 18 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 19 | changeDetection: ChangeDetectionStrategy.OnPush, 20 | imports: [NgtArgs, NgtpEffectBlendMode], 21 | hostDirectives: [{ directive: NgtpEffect, inputs: ['blendFunction', 'opacity'] }], 22 | }) 23 | export class NgtpShockWave { 24 | effect = inject(NgtpEffect, { host: true }); 25 | options = input({} as Omit); 26 | } 27 | -------------------------------------------------------------------------------- /libs/postprocessing/src/lib/effects/smaa.ts: -------------------------------------------------------------------------------- 1 | import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, inject, input } from '@angular/core'; 2 | import { NgtArgs, extend } from 'angular-three'; 3 | import { SMAAEffect } from 'postprocessing'; 4 | import { NgtpEffect, NgtpEffectBlendMode } from '../effect'; 5 | 6 | extend({ SMAAEffect }); 7 | 8 | export type SMAAEffectOptions = Partial[0]>>; 9 | 10 | @Component({ 11 | selector: 'ngtp-smaa', 12 | template: ` 13 | 14 | 15 | 16 | 17 | `, 18 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 19 | changeDetection: ChangeDetectionStrategy.OnPush, 20 | imports: [NgtArgs, NgtpEffectBlendMode], 21 | hostDirectives: [{ directive: NgtpEffect, inputs: ['blendFunction', 'opacity'] }], 22 | }) 23 | export class NgtpSMAA { 24 | effect = inject(NgtpEffect, { host: true }); 25 | options = input({} as Omit); 26 | } 27 | -------------------------------------------------------------------------------- /libs/postprocessing/src/lib/effects/tone-mapping.ts: -------------------------------------------------------------------------------- 1 | import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, inject, input } from '@angular/core'; 2 | import { NgtArgs, extend } from 'angular-three'; 3 | import { ToneMappingEffect } from 'postprocessing'; 4 | import { NgtpEffect, NgtpEffectBlendMode } from '../effect'; 5 | 6 | extend({ ToneMappingEffect }); 7 | 8 | export type ToneMappingEffectOptions = NonNullable[0]>; 9 | 10 | @Component({ 11 | selector: 'ngtp-tone-mapping', 12 | template: ` 13 | 14 | 15 | 16 | 17 | `, 18 | imports: [NgtArgs, NgtpEffectBlendMode], 19 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 20 | changeDetection: ChangeDetectionStrategy.OnPush, 21 | hostDirectives: [{ directive: NgtpEffect, inputs: ['blendFunction', 'opacity'] }], 22 | }) 23 | export class NgtpToneMapping { 24 | effect = inject(NgtpEffect, { host: true }); 25 | options = input({} as Omit); 26 | } 27 | -------------------------------------------------------------------------------- /libs/postprocessing/src/lib/effects/vignette.ts: -------------------------------------------------------------------------------- 1 | import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, inject, input } from '@angular/core'; 2 | import { NgtArgs, extend } from 'angular-three'; 3 | import { VignetteEffect } from 'postprocessing'; 4 | import { NgtpEffect, NgtpEffectBlendMode } from '../effect'; 5 | 6 | extend({ VignetteEffect }); 7 | 8 | export type VignetteEffectOptions = Partial[0]>>; 9 | 10 | @Component({ 11 | selector: 'ngtp-vignette', 12 | template: ` 13 | 14 | 15 | 16 | 17 | `, 18 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 19 | changeDetection: ChangeDetectionStrategy.OnPush, 20 | imports: [NgtArgs, NgtpEffectBlendMode], 21 | hostDirectives: [{ directive: NgtpEffect, inputs: ['blendFunction', 'opacity'] }], 22 | }) 23 | export class NgtpVignette { 24 | effect = inject(NgtpEffect, { host: true }); 25 | options = input({} as Omit); 26 | } 27 | -------------------------------------------------------------------------------- /libs/postprocessing/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import '@analogjs/vitest-angular/setup-zone'; 2 | 3 | import { getTestBed } from '@angular/core/testing'; 4 | import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; 5 | 6 | getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); 7 | -------------------------------------------------------------------------------- /libs/postprocessing/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "useDefineForClassFields": false, 5 | "forceConsistentCasingInFileNames": true, 6 | "strict": true, 7 | "noImplicitOverride": true, 8 | "noPropertyAccessFromIndexSignature": true, 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true 11 | }, 12 | "files": [], 13 | "include": [], 14 | "references": [ 15 | { 16 | "path": "./tsconfig.lib.json" 17 | }, 18 | { 19 | "path": "./tsconfig.spec.json" 20 | } 21 | ], 22 | "extends": "../../tsconfig.base.json", 23 | "angularCompilerOptions": { 24 | "enableI18nLegacyMessageIdFormat": false, 25 | "strictInjectionParameters": true, 26 | "strictInputAccessModifiers": true, 27 | "strictTemplates": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /libs/postprocessing/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "declaration": true, 6 | "declarationMap": true, 7 | "inlineSources": true, 8 | "types": [] 9 | }, 10 | "exclude": ["**/*.spec.ts", "test-setup.ts", "**/*.test.ts"], 11 | "include": ["**/*.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /libs/postprocessing/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.lib.json", 3 | "compilerOptions": { 4 | "declarationMap": false 5 | }, 6 | "angularCompilerOptions": { 7 | "compilationMode": "partial" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /libs/postprocessing/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "target": "es2016", 6 | "types": ["node", "vitest/globals"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /libs/postprocessing/vite.config.mts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import angular from '@analogjs/vite-plugin-angular'; 4 | 5 | import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; 6 | 7 | import { defineConfig } from 'vite'; 8 | 9 | // https://vitejs.dev/config/ 10 | export default defineConfig(({ mode }) => { 11 | return { 12 | plugins: [angular(), nxViteTsPaths()], 13 | test: { 14 | globals: true, 15 | environment: 'jsdom', 16 | setupFiles: ['src/test-setup.ts'], 17 | include: ['**/*.spec.ts'], 18 | reporters: ['default'], 19 | }, 20 | define: { 21 | 'import.meta.vitest': mode !== 'production', 22 | }, 23 | }; 24 | }); 25 | -------------------------------------------------------------------------------- /libs/rapier/README.md: -------------------------------------------------------------------------------- 1 | # rapier 2 | 3 | This library was generated with [Nx](https://nx.dev). 4 | 5 | ## Running unit tests 6 | 7 | Run `nx test rapier` to execute the unit tests. 8 | -------------------------------------------------------------------------------- /libs/rapier/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/libs/rapier", 4 | "lib": { 5 | "entryFile": "src/index.ts" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /libs/rapier/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-three-rapier", 3 | "version": "0.0.0-replace", 4 | "publishConfig": { 5 | "access": "public" 6 | }, 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/angular-threejs/angular-three/tree/main/libs/rapier" 10 | }, 11 | "author": { 12 | "name": "Chau Tran", 13 | "email": "nartc7789@gmail.com", 14 | "url": "https://nartc.me" 15 | }, 16 | "description": "Physics Rapier for Angular Three", 17 | "keywords": [ 18 | "angular", 19 | "threejs", 20 | "renderer", 21 | "rapier", 22 | "physics" 23 | ], 24 | "license": "MIT", 25 | "peerDependencies": { 26 | "@angular/common": ">=19.0.0 <20.0.0", 27 | "@angular/core": ">=19.0.0 <20.0.0", 28 | "@dimforge/rapier3d-compat": "~0.14.0", 29 | "three": ">=0.148.0 <0.173.0" 30 | }, 31 | "dependencies": { 32 | "tslib": "^2.7.0" 33 | }, 34 | "sideEffects": false, 35 | "web-types": [ 36 | "../../node_modules/angular-three/web-types.json" 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /libs/rapier/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rapier", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "libs/rapier/src", 5 | "prefix": "lib", 6 | "projectType": "library", 7 | "tags": [], 8 | "targets": { 9 | "build": { 10 | "executor": "@nx/angular:package", 11 | "outputs": ["{workspaceRoot}/dist/{projectRoot}"], 12 | "options": { 13 | "project": "libs/rapier/ng-package.json" 14 | }, 15 | "configurations": { 16 | "production": { 17 | "tsConfig": "libs/rapier/tsconfig.lib.prod.json" 18 | }, 19 | "development": { 20 | "tsConfig": "libs/rapier/tsconfig.lib.json" 21 | } 22 | }, 23 | "defaultConfiguration": "production" 24 | }, 25 | "test": { 26 | "executor": "@analogjs/vitest-angular:test" 27 | }, 28 | "lint": { 29 | "executor": "@nx/eslint:lint" 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /libs/rapier/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/colliders'; 2 | export * from './lib/instanced-rigid-bodies'; 3 | export * from './lib/joints'; 4 | export * from './lib/mesh-collider'; 5 | export * from './lib/physics'; 6 | export * from './lib/rigid-body'; 7 | 8 | export type * from './lib/types'; 9 | -------------------------------------------------------------------------------- /libs/rapier/src/lib/shared.ts: -------------------------------------------------------------------------------- 1 | import { Euler, Matrix4, Object3D, Quaternion, Vector3 } from 'three'; 2 | 3 | export const _quaternion = new Quaternion(); 4 | export const _euler = new Euler(); 5 | export const _vector3 = new Vector3(); 6 | export const _object3d = new Object3D(); 7 | export const _matrix4 = new Matrix4(); 8 | export const _position = new Vector3(); 9 | export const _rotation = new Quaternion(); 10 | export const _scale = new Vector3(); 11 | -------------------------------------------------------------------------------- /libs/rapier/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import '@analogjs/vitest-angular/setup-zone'; 2 | 3 | import { getTestBed } from '@angular/core/testing'; 4 | import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; 5 | 6 | getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); 7 | -------------------------------------------------------------------------------- /libs/rapier/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "forceConsistentCasingInFileNames": true, 5 | "strict": true, 6 | "noImplicitOverride": true, 7 | "noPropertyAccessFromIndexSignature": true, 8 | "noImplicitReturns": true, 9 | "noFallthroughCasesInSwitch": true 10 | }, 11 | "files": [], 12 | "include": [], 13 | "references": [ 14 | { 15 | "path": "./tsconfig.lib.json" 16 | }, 17 | { 18 | "path": "./tsconfig.spec.json" 19 | } 20 | ], 21 | "extends": "../../tsconfig.base.json", 22 | "angularCompilerOptions": { 23 | "enableI18nLegacyMessageIdFormat": false, 24 | "strictInjectionParameters": true, 25 | "strictInputAccessModifiers": true, 26 | "strictTemplates": true 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /libs/rapier/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "declaration": true, 6 | "declarationMap": true, 7 | "inlineSources": true, 8 | "types": ["node"] 9 | }, 10 | "exclude": ["**/*.spec.ts", "src/test-setup.ts", "**/*.test.ts"], 11 | "include": ["**/*.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /libs/rapier/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.lib.json", 3 | "compilerOptions": { 4 | "declarationMap": false 5 | }, 6 | "angularCompilerOptions": { 7 | "compilationMode": "partial" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /libs/rapier/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "target": "es2016", 6 | "types": ["node", "vitest/globals"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /libs/rapier/vite.config.mts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import angular from '@analogjs/vite-plugin-angular'; 4 | 5 | import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; 6 | 7 | import { defineConfig } from 'vite'; 8 | 9 | // https://vitejs.dev/config/ 10 | export default defineConfig(({ mode }) => { 11 | return { 12 | plugins: [angular(), nxViteTsPaths()], 13 | test: { 14 | globals: true, 15 | environment: 'jsdom', 16 | setupFiles: ['src/test-setup.ts'], 17 | include: ['**/*.spec.ts'], 18 | reporters: ['default'], 19 | }, 20 | define: { 21 | 'import.meta.vitest': mode !== 'production', 22 | }, 23 | }; 24 | }); 25 | -------------------------------------------------------------------------------- /libs/soba/.storybook/documentation-template.mdx: -------------------------------------------------------------------------------- 1 | import { Meta, Title, Subtitle, Description, Primary, Controls } from '@storybook/blocks'; 2 | 3 | {/\* 4 | 5 | - 👇 The isTemplate property is required to tell Storybook that this is a template 6 | - See https://storybook.js.org/docs/api/doc-blocks/doc-block-meta 7 | - to learn how to use 8 | \*/} 9 | 10 | 11 | 12 | 13 | <Subtitle /> 14 | <Description /> 15 | 16 | ## Default implementation 17 | 18 | <Primary /> 19 | 20 | ## Available controls for story 21 | 22 | <Controls /> 23 | -------------------------------------------------------------------------------- /libs/soba/.storybook/main.ts: -------------------------------------------------------------------------------- 1 | import { StorybookConfig } from '@storybook/angular'; 2 | 3 | const config: StorybookConfig = { 4 | stories: ['../**/*.mdx', '../**/*.stories.@(js|ts)'], 5 | addons: ['@storybook/addon-essentials', 'storybook-addon-deep-controls', '@chromatic-com/storybook'], 6 | staticDirs: ['./public', './public/cube'], 7 | framework: '@storybook/angular', 8 | docs: {}, 9 | }; 10 | 11 | export default config; 12 | -------------------------------------------------------------------------------- /libs/soba/.storybook/manager-head.html: -------------------------------------------------------------------------------- 1 | <title>Angular Three Documentation 2 | 3 | 4 | 5 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /libs/soba/.storybook/manager.ts: -------------------------------------------------------------------------------- 1 | import { addons } from '@storybook/manager-api'; 2 | import theme from './theme'; 3 | 4 | addons.setConfig({ theme }); 5 | 6 | // NOTE: this is to keep the addons width at 300 by default 7 | const storybookLayout = JSON.parse(localStorage['storybook-layout'] || '{}'); 8 | const newLayout = { resizerNav: { x: 300, y: 0 } }; 9 | localStorage['storybook-layout'] = JSON.stringify({ ...storybookLayout, ...newLayout }); 10 | -------------------------------------------------------------------------------- /libs/soba/.storybook/preview-body.html: -------------------------------------------------------------------------------- 1 | 45 | -------------------------------------------------------------------------------- /libs/soba/.storybook/preview.ts: -------------------------------------------------------------------------------- 1 | import { Preview } from '@storybook/angular'; 2 | 3 | export default { 4 | parameters: { 5 | deepControls: { enabled: true }, 6 | docs: { 7 | // page: DocumentationTemplate, 8 | }, 9 | }, 10 | tags: ['autodocs'], 11 | } as Preview; 12 | -------------------------------------------------------------------------------- /libs/soba/.storybook/public/LittlestTokyo-transformed.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/LittlestTokyo-transformed.glb -------------------------------------------------------------------------------- /libs/soba/.storybook/public/NORM.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/NORM.jpg -------------------------------------------------------------------------------- /libs/soba/.storybook/public/aobox-transformed.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/aobox-transformed.glb -------------------------------------------------------------------------------- /libs/soba/.storybook/public/archer.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/archer.glb -------------------------------------------------------------------------------- /libs/soba/.storybook/public/compressed.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/compressed.glb -------------------------------------------------------------------------------- /libs/soba/.storybook/public/cube/nx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/cube/nx.png -------------------------------------------------------------------------------- /libs/soba/.storybook/public/cube/ny.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/cube/ny.png -------------------------------------------------------------------------------- /libs/soba/.storybook/public/cube/nz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/cube/nz.png -------------------------------------------------------------------------------- /libs/soba/.storybook/public/cube/px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/cube/px.png -------------------------------------------------------------------------------- /libs/soba/.storybook/public/cube/py.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/cube/py.png -------------------------------------------------------------------------------- /libs/soba/.storybook/public/cube/pz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/cube/pz.png -------------------------------------------------------------------------------- /libs/soba/.storybook/public/decals/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/decals/react.png -------------------------------------------------------------------------------- /libs/soba/.storybook/public/decals/three.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/decals/three.png -------------------------------------------------------------------------------- /libs/soba/.storybook/public/dflat.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/dflat.glb -------------------------------------------------------------------------------- /libs/soba/.storybook/public/dist_map.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/dist_map.jpeg -------------------------------------------------------------------------------- /libs/soba/.storybook/public/gainmap/potsdamer_platz_1k.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/gainmap/potsdamer_platz_1k.jpg -------------------------------------------------------------------------------- /libs/soba/.storybook/public/gelatinous_cube.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/gelatinous_cube.glb -------------------------------------------------------------------------------- /libs/soba/.storybook/public/glass-transformed.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/glass-transformed.glb -------------------------------------------------------------------------------- /libs/soba/.storybook/public/roughness_floor.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/roughness_floor.jpeg -------------------------------------------------------------------------------- /libs/soba/.storybook/public/shoe.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/shoe.glb -------------------------------------------------------------------------------- /libs/soba/.storybook/public/suzanne.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/suzanne.glb -------------------------------------------------------------------------------- /libs/soba/.storybook/public/textures/grassy_cobble/grassy_cobblestone_ao_2k.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/textures/grassy_cobble/grassy_cobblestone_ao_2k.jpg -------------------------------------------------------------------------------- /libs/soba/.storybook/public/textures/grassy_cobble/grassy_cobblestone_diff_2k.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/textures/grassy_cobble/grassy_cobblestone_diff_2k.jpg -------------------------------------------------------------------------------- /libs/soba/.storybook/public/textures/grassy_cobble/grassy_cobblestone_nor_gl_2k.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/textures/grassy_cobble/grassy_cobblestone_nor_gl_2k.jpg -------------------------------------------------------------------------------- /libs/soba/.storybook/public/textures/grassy_cobble/grassy_cobblestone_rough_2k.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/textures/grassy_cobble/grassy_cobblestone_rough_2k.jpg -------------------------------------------------------------------------------- /libs/soba/.storybook/public/textures/other/leaves.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/textures/other/leaves.jpg -------------------------------------------------------------------------------- /libs/soba/.storybook/public/ybot.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-threejs/angular-three/dd0836fe363a59df3bdaa80eff188d90a6279712/libs/soba/.storybook/public/ybot.glb -------------------------------------------------------------------------------- /libs/soba/.storybook/theme.ts: -------------------------------------------------------------------------------- 1 | import { create } from '@storybook/theming'; 2 | 3 | export default create({ 4 | base: 'light', 5 | brandTitle: 'Angular Three - Soba', 6 | brandUrl: 'https://github.com/angular-threejs/angular-three', 7 | brandImage: './angular-three.svg', 8 | brandTarget: '_self', 9 | }); 10 | -------------------------------------------------------------------------------- /libs/soba/.storybook/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "emitDecoratorMetadata": true 5 | }, 6 | "exclude": ["../**/*.spec.ts"], 7 | "include": [ 8 | "../src/**/*.stories.ts", 9 | "../src/**/*.stories.js", 10 | "../src/**/*.stories.jsx", 11 | "../src/**/*.stories.tsx", 12 | "../src/**/*.stories.mdx", 13 | "*.js", 14 | "*.ts" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /libs/soba/abstractions/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/soba/abstractions/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/billboard'; 2 | export * from './lib/catmull-rom-line'; 3 | export * from './lib/cubic-bezier-line'; 4 | export * from './lib/edges'; 5 | export * from './lib/gradient-texture'; 6 | export * from './lib/grid'; 7 | export * from './lib/helper'; 8 | export * from './lib/line'; 9 | export * from './lib/prism-geometry'; 10 | export * from './lib/quadratic-bezier-line'; 11 | export * from './lib/rounded-box'; 12 | export * from './lib/text'; 13 | export * from './lib/text-3d'; 14 | -------------------------------------------------------------------------------- /libs/soba/abstractions/src/lib/__snapshots__/helper.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 | 3 | exports[`NgtsHelper > should render properly 1`] = ` 4 | [ 5 | { 6 | "children": [ 7 | { 8 | "children": [], 9 | "name": "", 10 | "type": "Object3D", 11 | }, 12 | ], 13 | "name": "", 14 | "type": "Mesh", 15 | }, 16 | { 17 | "children": [], 18 | "name": "", 19 | "type": "BoxHelper", 20 | }, 21 | ] 22 | `; 23 | -------------------------------------------------------------------------------- /libs/soba/abstractions/src/lib/__snapshots__/line.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 | 3 | exports[`NgtsLine > should render properly 1`] = ` 4 | [ 5 | { 6 | "children": [], 7 | "name": "", 8 | "type": "Line2", 9 | }, 10 | ] 11 | `; 12 | 13 | exports[`NgtsLine > should render properly with segments 1`] = ` 14 | [ 15 | { 16 | "children": [], 17 | "name": "", 18 | "type": "Line2", 19 | }, 20 | ] 21 | `; 22 | -------------------------------------------------------------------------------- /libs/soba/abstractions/src/lib/__snapshots__/prism-geometry.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 | 3 | exports[`NgtsPrismGeometry > should render properly 1`] = ` 4 | [ 5 | { 6 | "children": [], 7 | "name": "", 8 | "type": "Mesh", 9 | }, 10 | ] 11 | `; 12 | -------------------------------------------------------------------------------- /libs/soba/abstractions/src/lib/__snapshots__/rounded-box.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 | 3 | exports[`NgtsRoundedBox > should render properly 1`] = ` 4 | [ 5 | { 6 | "children": [], 7 | "name": "", 8 | "type": "Mesh", 9 | }, 10 | ] 11 | `; 12 | -------------------------------------------------------------------------------- /libs/soba/abstractions/src/lib/__snapshots__/text.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 | 3 | exports[`NgtsText > should render properly 1`] = ` 4 | [ 5 | { 6 | "children": [], 7 | "name": "", 8 | "type": "Mesh", 9 | }, 10 | ] 11 | `; 12 | -------------------------------------------------------------------------------- /libs/soba/abstractions/src/lib/grid.spec.ts: -------------------------------------------------------------------------------- 1 | // TODO (chau): re-enable this test once importing three/examples/jsm is solved 2 | describe.skip('NgtsGrid', () => { 3 | it.skip('should render properly', async () => { 4 | // const { scene, fixture } = NgtTestBed.create(NgtsGrid); 5 | // fixture.detectChanges(); 6 | // 7 | // expect(scene.children.length).toEqual(1); 8 | // expect(scene.toJSON()).toMatchSnapshot(); 9 | expect(true).toBe(true); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /libs/soba/abstractions/src/lib/helper.spec.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; 2 | import { NgtTestBed } from 'angular-three/testing'; 3 | import { BoxHelper } from 'three'; 4 | import { NgtsHelper } from './helper'; 5 | 6 | describe(NgtsHelper.name, () => { 7 | @Component({ 8 | template: ` 9 | 10 | 11 | 12 | 13 | `, 14 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 15 | changeDetection: ChangeDetectionStrategy.OnPush, 16 | imports: [NgtsHelper], 17 | }) 18 | class SceneGraph { 19 | protected readonly BoxHelper = BoxHelper; 20 | } 21 | 22 | it('should render properly', async () => { 23 | const { scene, fixture, toGraph } = NgtTestBed.create(SceneGraph); 24 | fixture.detectChanges(); 25 | 26 | expect(scene.children.length).toEqual(2); 27 | expect(scene.children[1].type).toEqual('BoxHelper'); 28 | expect(toGraph()).toMatchSnapshot(); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /libs/soba/abstractions/src/lib/line.spec.ts: -------------------------------------------------------------------------------- 1 | import { NgtTestBed } from 'angular-three/testing'; 2 | import { Line2, LineGeometry, LineSegments2, LineSegmentsGeometry } from 'three-stdlib'; 3 | import { NgtsLine } from './line'; 4 | 5 | describe(NgtsLine.name, () => { 6 | it('should render properly', async () => { 7 | const { scene, fixture, toGraph } = NgtTestBed.create(NgtsLine); 8 | fixture.detectChanges(); 9 | 10 | expect(scene.children.length).toEqual(1); 11 | const line = scene.children[0] as Line2; 12 | expect(line).toBeInstanceOf(Line2); 13 | expect(line.geometry).toBeInstanceOf(LineGeometry); 14 | expect(toGraph()).toMatchSnapshot(); 15 | }); 16 | 17 | it('should render properly with segments', async () => { 18 | const { scene, fixture, toGraph } = NgtTestBed.create(NgtsLine); 19 | fixture.componentRef.setInput('segments', true); 20 | fixture.detectChanges(); 21 | 22 | expect(scene.children.length).toEqual(1); 23 | const line = scene.children[0] as LineSegments2; 24 | expect(line).toBeInstanceOf(LineSegments2); 25 | expect(line.isLineSegments2).toEqual(true); 26 | expect(line.geometry).toBeInstanceOf(LineSegmentsGeometry); 27 | expect(toGraph()).toMatchSnapshot(); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /libs/soba/abstractions/src/lib/prism-geometry.spec.ts: -------------------------------------------------------------------------------- 1 | import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; 2 | import { NgtTestBed } from 'angular-three/testing'; 3 | import { ExtrudeGeometry, Mesh } from 'three'; 4 | import { NgtsPrismGeometry } from './prism-geometry'; 5 | 6 | describe(NgtsPrismGeometry.name, () => { 7 | @Component({ 8 | template: ` 9 | 10 | 18 | 19 | `, 20 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 21 | imports: [NgtsPrismGeometry], 22 | }) 23 | class SceneGraph {} 24 | 25 | it('should render properly', async () => { 26 | const { scene, fixture, toGraph } = NgtTestBed.create(SceneGraph); 27 | fixture.detectChanges(); 28 | 29 | expect(scene.children.length).toEqual(1); 30 | const mesh = scene.children[0] as Mesh; 31 | 32 | expect(mesh.geometry.type).toEqual('ExtrudeGeometry'); 33 | expect(toGraph()).toMatchSnapshot(); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /libs/soba/abstractions/src/lib/rounded-box.spec.ts: -------------------------------------------------------------------------------- 1 | import { NgtTestBed } from 'angular-three/testing'; 2 | import { ExtrudeGeometry, Mesh } from 'three'; 3 | import { NgtsRoundedBox } from './rounded-box'; 4 | 5 | describe(NgtsRoundedBox.name, () => { 6 | it('should render properly', async () => { 7 | const { scene, fixture, toGraph } = NgtTestBed.create(NgtsRoundedBox); 8 | fixture.detectChanges(); 9 | 10 | expect(scene.children.length).toEqual(1); 11 | const mesh = scene.children[0] as Mesh; 12 | expect(mesh.geometry).toBeInstanceOf(ExtrudeGeometry); 13 | expect(toGraph()).toMatchSnapshot(); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /libs/soba/abstractions/src/lib/text.spec.ts: -------------------------------------------------------------------------------- 1 | import { NgtTestBed } from 'angular-three/testing'; 2 | import { NgtsText } from './text'; 3 | 4 | describe(NgtsText.name, () => { 5 | it('should render properly', async () => { 6 | const { scene, fixture, toGraph } = NgtTestBed.create(NgtsText); 7 | fixture.componentRef.setInput('text', 'hello'); 8 | fixture.detectChanges(); 9 | 10 | expect(scene.children.length).toEqual(1); 11 | expect(toGraph()).toMatchSnapshot(); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /libs/soba/cameras/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/soba/cameras/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/camera-content'; 2 | export * from './lib/cube-camera'; 3 | export * from './lib/orthographic-camera'; 4 | export * from './lib/perspective-camera'; 5 | -------------------------------------------------------------------------------- /libs/soba/cameras/src/lib/camera-content.ts: -------------------------------------------------------------------------------- 1 | import { Directive, Signal } from '@angular/core'; 2 | import { Texture } from 'three'; 3 | 4 | @Directive({ selector: 'ng-template[cameraContent]' }) 5 | export class NgtsCameraContent { 6 | static ngTemplateContextGuard(_: NgtsCameraContent, ctx: unknown): ctx is { $implicit: Signal } { 7 | return true; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /libs/soba/controls/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/soba/controls/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/camera-controls'; 2 | export * from './lib/orbit-controls'; 3 | export * from './lib/scroll-controls'; 4 | -------------------------------------------------------------------------------- /libs/soba/gizmos/README.md: -------------------------------------------------------------------------------- 1 | # angular-three-soba/gizmos 2 | 3 | Secondary entry point of `angular-three-soba`. It can be used by importing from `angular-three-soba/gizmos`. 4 | -------------------------------------------------------------------------------- /libs/soba/gizmos/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/soba/gizmos/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/gizmo-helper/gizmo-helper'; 2 | export { NgtsGizmoViewcube, NgtsGizmoViewcubeOptions } from './lib/gizmo-helper/gizmo-viewcube'; 3 | export { NgtsGizmoViewport, NgtsGizmoViewportOptions } from './lib/gizmo-helper/gizmo-viewport'; 4 | export * from './lib/pivot-controls/pivot-controls'; 5 | export * from './lib/transform-controls'; 6 | -------------------------------------------------------------------------------- /libs/soba/loaders/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/soba/loaders/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/fbx-loader'; 2 | export * from './lib/font-loader'; 3 | export * from './lib/gltf-loader'; 4 | export * from './lib/loader'; 5 | export * from './lib/progress'; 6 | export * from './lib/texture-loader'; 7 | -------------------------------------------------------------------------------- /libs/soba/loaders/src/lib/fbx-loader.ts: -------------------------------------------------------------------------------- 1 | import { Injector } from '@angular/core'; 2 | import { injectLoader } from 'angular-three'; 3 | import { assertInjector } from 'ngxtension/assert-injector'; 4 | import { FBXLoader } from 'three-stdlib'; 5 | 6 | function _injectFBX>( 7 | input: () => TUrl, 8 | { injector }: { injector?: Injector } = {}, 9 | ) { 10 | return assertInjector(_injectFBX, injector, () => { 11 | return injectLoader(() => FBXLoader, input); 12 | }); 13 | } 14 | 15 | _injectFBX.preload = >(input: () => TUrl) => { 16 | injectLoader.preload(() => FBXLoader, input); 17 | }; 18 | 19 | export type NgtsFBXLoader = typeof _injectFBX; 20 | export const injectFBX: NgtsFBXLoader = _injectFBX; 21 | -------------------------------------------------------------------------------- /libs/soba/loaders/src/lib/loader.css: -------------------------------------------------------------------------------- 1 | .ngts-loader-container { 2 | --ngts-loader-container-opacity: 0; 3 | position: absolute; 4 | top: 0; 5 | left: 0; 6 | width: 100%; 7 | height: 100%; 8 | background: #171717; 9 | display: flex; 10 | align-items: center; 11 | justify-content: center; 12 | transition: opacity 300ms ease; 13 | z-index: 1000; 14 | opacity: var(--ngts-loader-container-opacity); 15 | } 16 | 17 | .ngts-loader-inner { 18 | width: 100px; 19 | height: 3px; 20 | background: #272727; 21 | text-align: center; 22 | } 23 | 24 | .ngts-loader-bar { 25 | --ngts-loader-bar-scale: 0; 26 | height: 3px; 27 | width: 100px; 28 | background: white; 29 | transition: transform 200ms; 30 | transform-origin: left center; 31 | transform: scaleX(var(--ngts-loader-bar-scale)); 32 | } 33 | 34 | .ngts-loader-data { 35 | display: inline-block; 36 | position: relative; 37 | font-variant-numeric: tabular-nums; 38 | margin-top: 0.8em; 39 | color: #f0f0f0; 40 | font-size: 0.6em; 41 | font-family: -apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', 'Helvetica Neue', Helvetica, Arial, Roboto, 42 | Ubuntu, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; 43 | white-space: nowrap; 44 | } 45 | -------------------------------------------------------------------------------- /libs/soba/materials/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/soba/materials/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/custom-shader-material'; 2 | export * from './lib/mesh-distort-material'; 3 | export * from './lib/mesh-portal-material'; 4 | export * from './lib/mesh-reflector-material'; 5 | export * from './lib/mesh-refraction-material'; 6 | export * from './lib/mesh-transmission-material'; 7 | export * from './lib/mesh-wobble-material'; 8 | export * from './lib/point-material'; 9 | -------------------------------------------------------------------------------- /libs/soba/materials/src/lib/point-material.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, DestroyRef, inject, input } from '@angular/core'; 2 | import { NgtArgs, NgtAttachable } from 'angular-three'; 3 | import { PointMaterial } from 'angular-three-soba/shaders'; 4 | import { PointsMaterialParameters } from 'three'; 5 | 6 | @Component({ 7 | selector: 'ngts-point-material', 8 | template: ` 9 | 10 | 11 | 12 | `, 13 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 14 | changeDetection: ChangeDetectionStrategy.OnPush, 15 | imports: [NgtArgs], 16 | }) 17 | export class NgtsPointMaterial { 18 | attach = input('material'); 19 | options = input({} as PointsMaterialParameters); 20 | 21 | material = new PointMaterial(this.options()); 22 | 23 | constructor() { 24 | inject(DestroyRef).onDestroy(() => this.material.dispose()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /libs/soba/misc/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/soba/misc/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/animations'; 2 | export * from './lib/bake-shadows'; 3 | export * from './lib/computed-attribute'; 4 | export * from './lib/constants'; 5 | export * from './lib/decal'; 6 | export * from './lib/deprecated'; 7 | export * from './lib/depth-buffer'; 8 | export * from './lib/fbo'; 9 | export * from './lib/html/html'; 10 | export * from './lib/html/html-content'; 11 | export * from './lib/intersect'; 12 | export * from './lib/preload'; 13 | export * from './lib/sampler'; 14 | export * from './lib/scale-factor'; 15 | -------------------------------------------------------------------------------- /libs/soba/misc/src/lib/bake-shadows.ts: -------------------------------------------------------------------------------- 1 | import { Directive, effect } from '@angular/core'; 2 | import { injectStore } from 'angular-three'; 3 | 4 | @Directive({ selector: 'ngts-bake-shadows' }) 5 | export class NgtsBakeShadows { 6 | constructor() { 7 | const store = injectStore(); 8 | const gl = store.select('gl'); 9 | effect((onCleanup) => { 10 | const _gl = gl(); 11 | _gl.shadowMap.autoUpdate = false; 12 | _gl.shadowMap.needsUpdate = true; 13 | onCleanup(() => { 14 | _gl.shadowMap.autoUpdate = _gl.shadowMap.needsUpdate = true; 15 | }); 16 | }); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /libs/soba/misc/src/lib/constants.ts: -------------------------------------------------------------------------------- 1 | import { REVISION } from 'three'; 2 | 3 | export function getVersion() { 4 | return parseInt(REVISION.replace(/\D+/g, '')); 5 | } 6 | -------------------------------------------------------------------------------- /libs/soba/misc/src/lib/deprecated.ts: -------------------------------------------------------------------------------- 1 | import { BufferAttribute } from 'three'; 2 | 3 | /** 4 | * NOTE: Sets `BufferAttribute.updateRange` since r159. 5 | */ 6 | export const setUpdateRange = (attribute: BufferAttribute, updateRange: { offset: number; count: number }): void => { 7 | if ('updateRanges' in attribute) { 8 | // attribute.updateRanges[0] = updateRange; 9 | attribute.addUpdateRange(updateRange.offset, updateRange.count); 10 | } else { 11 | Object.assign(attribute, { updateRange }); 12 | } 13 | }; 14 | 15 | export const LinearEncoding = 3000; 16 | export const sRGBEncoding = 3001; 17 | 18 | /** 19 | * NOTE: TextureEncoding was deprecated in r152, and removed in r162. 20 | */ 21 | export type TextureEncoding = typeof LinearEncoding | typeof sRGBEncoding; 22 | -------------------------------------------------------------------------------- /libs/soba/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/libs/soba", 4 | "lib": { 5 | "entryFile": "src/index.ts" 6 | }, 7 | "assets": [ 8 | { 9 | "input": "./shaders/assets/", 10 | "glob": "**/*", 11 | "output": "assets" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /libs/soba/performances/README.md: -------------------------------------------------------------------------------- 1 | # angular-three-soba/performances 2 | 3 | Secondary entry point of `angular-three-soba`. It can be used by importing from `angular-three-soba/performances`. 4 | -------------------------------------------------------------------------------- /libs/soba/performances/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/soba/performances/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/adaptive-dpr'; 2 | export * from './lib/adaptive-events'; 3 | export * from './lib/detailed'; 4 | export * from './lib/instances/instances'; 5 | export * from './lib/points/points'; 6 | export * from './lib/segments/segments'; 7 | -------------------------------------------------------------------------------- /libs/soba/performances/src/lib/adaptive-events.ts: -------------------------------------------------------------------------------- 1 | import { DestroyRef, Directive, effect, inject } from '@angular/core'; 2 | import { injectStore } from 'angular-three'; 3 | 4 | @Directive({ selector: 'ngts-adaptive-events' }) 5 | export class NgtsAdaptiveEvents { 6 | constructor() { 7 | const store = injectStore(); 8 | const current = store.select('performance', 'current'); 9 | const currentEnabled = store.snapshot.events.enabled; 10 | 11 | effect((onCleanup) => { 12 | const _current = current(); 13 | onCleanup(() => store.snapshot.setEvents({ enabled: _current === 1 })); 14 | }); 15 | 16 | inject(DestroyRef).onDestroy(() => { 17 | store.snapshot.setEvents({ enabled: currentEnabled }); 18 | }); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/soba/performances/src/lib/segments/segment-object.ts: -------------------------------------------------------------------------------- 1 | import { NgtNode } from 'angular-three'; 2 | import { Color, Vector3 } from 'three'; 3 | 4 | export type NgtSegmentObject = NgtNode; 5 | 6 | export class SegmentObject { 7 | color: Color; 8 | start: Vector3; 9 | end: Vector3; 10 | 11 | constructor() { 12 | this.color = new Color('white'); 13 | this.start = new Vector3(0, 0, 0); 14 | this.end = new Vector3(0, 0, 0); 15 | } 16 | } 17 | 18 | declare global { 19 | interface HTMLElementTagNameMap { 20 | /** 21 | * @rawOptions start|color|end 22 | */ 23 | 'ngt-segment-object': NgtSegmentObject; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /libs/soba/shaders/README.md: -------------------------------------------------------------------------------- 1 | # angular-three-soba/shaders 2 | 3 | Secondary entry point of `angular-three-soba`. It can be used by importing from `angular-three-soba/shaders`. 4 | -------------------------------------------------------------------------------- /libs/soba/shaders/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/soba/shaders/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/grid-material'; 2 | export * from './lib/mesh-refraction-material'; 3 | export * from './lib/point-material'; 4 | -------------------------------------------------------------------------------- /libs/soba/src/cameras/orthographic-camera.stories.ts: -------------------------------------------------------------------------------- 1 | import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; 2 | import { NgtArgs } from 'angular-three'; 3 | import { NgtsOrthographicCamera } from 'angular-three-soba/cameras'; 4 | import { makeDecorators, makeStoryObject } from '../setup-canvas'; 5 | import { positions } from './positions'; 6 | 7 | @Component({ 8 | template: ` 9 | 10 | 11 | 12 | @for (position of positions(); track position.id) { 13 | 14 | 15 | 16 | 17 | } 18 | 19 | `, 20 | imports: [NgtsOrthographicCamera, NgtArgs], 21 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 22 | }) 23 | class DefaultOrthographicCameraStory { 24 | positions = positions; 25 | } 26 | 27 | export default { 28 | title: 'Camera/OrthographicCamera', 29 | decorators: makeDecorators(), 30 | }; 31 | 32 | export const Default = makeStoryObject(DefaultOrthographicCameraStory); 33 | -------------------------------------------------------------------------------- /libs/soba/src/cameras/perspective-camera.stories.ts: -------------------------------------------------------------------------------- 1 | import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; 2 | import { NgtArgs } from 'angular-three'; 3 | import { NgtsPerspectiveCamera } from 'angular-three-soba/cameras'; 4 | import { makeDecorators, makeStoryObject } from '../setup-canvas'; 5 | import { positions } from './positions'; 6 | 7 | @Component({ 8 | template: ` 9 | 10 | 11 | 12 | @for (position of positions(); track position.id) { 13 | 14 | 15 | 16 | 17 | } 18 | 19 | `, 20 | imports: [NgtsPerspectiveCamera, NgtArgs], 21 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 22 | }) 23 | class DefaultPerspectiveCameraStory { 24 | positions = positions; 25 | } 26 | 27 | export default { 28 | title: 'Camera/PerspectiveCamera', 29 | decorators: makeDecorators(), 30 | }; 31 | 32 | export const Default = makeStoryObject(DefaultPerspectiveCameraStory); 33 | -------------------------------------------------------------------------------- /libs/soba/src/cameras/positions.ts: -------------------------------------------------------------------------------- 1 | import { computed } from '@angular/core'; 2 | 3 | const NUM = 3; 4 | 5 | export interface Position { 6 | id: string; 7 | position: [number, number, number]; 8 | } 9 | 10 | export const positions = computed(() => { 11 | const pos: Position[] = []; 12 | const half = (NUM - 1) / 2; 13 | 14 | for (let x = 0; x < NUM; x++) { 15 | for (let y = 0; y < NUM; y++) { 16 | pos.push({ 17 | id: `${x}-${y}`, 18 | position: [(x - half) * 4, (y - half) * 4, 0], 19 | }); 20 | } 21 | } 22 | 23 | return pos; 24 | }); 25 | -------------------------------------------------------------------------------- /libs/soba/src/index.ts: -------------------------------------------------------------------------------- 1 | export default void 0; 2 | -------------------------------------------------------------------------------- /libs/soba/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import '@analogjs/vitest-angular/setup-zone'; 2 | import 'vitest-webgl-canvas-mock'; 3 | 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; 6 | 7 | getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); 8 | -------------------------------------------------------------------------------- /libs/soba/src/types.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.glsl' { 2 | const content: string; 3 | export default content; 4 | } 5 | -------------------------------------------------------------------------------- /libs/soba/staging/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/soba/staging/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/accumulative-shadows'; 2 | export * from './lib/backdrop'; 3 | export * from './lib/bb-anchor'; 4 | export * from './lib/bounds'; 5 | export * from './lib/camera-shake'; 6 | export * from './lib/caustics'; 7 | export * from './lib/center'; 8 | export * from './lib/contact-shadows'; 9 | export * from './lib/environment/environment'; 10 | export * from './lib/environment/inject-environment'; 11 | export * from './lib/float'; 12 | export * from './lib/lightformer'; 13 | export * from './lib/mask'; 14 | export * from './lib/matcap-texture'; 15 | export * from './lib/normal-texture'; 16 | export * from './lib/randomized-lights'; 17 | export * from './lib/render-texture'; 18 | export * from './lib/sky'; 19 | export { NgtsSpotLight, NgtsSpotLightOptions, NgtsSpotLightShadow } from './lib/spot-light'; 20 | export * from './lib/stage'; 21 | -------------------------------------------------------------------------------- /libs/soba/stats/README.md: -------------------------------------------------------------------------------- 1 | # angular-three-soba/stats 2 | 3 | Secondary entry point of `angular-three-soba`. It can be used by importing from `angular-three-soba/stats`. 4 | -------------------------------------------------------------------------------- /libs/soba/stats/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/soba/stats/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/stats'; 2 | -------------------------------------------------------------------------------- /libs/soba/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "useDefineForClassFields": false, 5 | "forceConsistentCasingInFileNames": true, 6 | "strict": true, 7 | "noImplicitOverride": true, 8 | "noPropertyAccessFromIndexSignature": true, 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true 11 | }, 12 | "files": [], 13 | "include": [], 14 | "references": [ 15 | { 16 | "path": "./tsconfig.lib.json" 17 | }, 18 | { 19 | "path": "./tsconfig.spec.json" 20 | }, 21 | { 22 | "path": "./.storybook/tsconfig.json" 23 | } 24 | ], 25 | "extends": "../../tsconfig.base.json", 26 | "angularCompilerOptions": { 27 | "enableI18nLegacyMessageIdFormat": false, 28 | "strictInjectionParameters": true, 29 | "strictInputAccessModifiers": true, 30 | "strictTemplates": true 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /libs/soba/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "declaration": true, 6 | "declarationMap": true, 7 | "inlineSources": true, 8 | "types": [] 9 | }, 10 | "exclude": ["**/*.spec.ts", "test-setup.ts", "**/*.test.ts", "**/*.stories.ts", "**/*.stories.js"], 11 | "include": ["**/*.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /libs/soba/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.lib.json", 3 | "compilerOptions": { 4 | "declarationMap": false 5 | }, 6 | "angularCompilerOptions": { 7 | "compilationMode": "partial" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /libs/soba/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "target": "es2016", 6 | "types": ["node", "vitest/globals"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /libs/soba/vanilla-exports/README.md: -------------------------------------------------------------------------------- 1 | # angular-three-soba/vanilla-exports 2 | 3 | Secondary entry point of `angular-three-soba`. It can be used by importing from `angular-three-soba/vanilla-exports`. 4 | -------------------------------------------------------------------------------- /libs/soba/vanilla-exports/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/soba/vitest.config.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import angular from '@analogjs/vite-plugin-angular'; 4 | 5 | import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; 6 | 7 | import { defineConfig } from 'vite'; 8 | 9 | // https://vitejs.dev/config/ 10 | export default defineConfig(({ mode }) => { 11 | return { 12 | plugins: [angular(), nxViteTsPaths()], 13 | test: { 14 | globals: true, 15 | environment: 'jsdom', 16 | setupFiles: ['src/test-setup.ts'], 17 | include: ['**/*.spec.ts'], 18 | reporters: ['default'], 19 | hideSkippedTests: true, 20 | passWithNoTests: true, 21 | }, 22 | define: { 23 | 'import.meta.vitest': mode !== 'production', 24 | }, 25 | }; 26 | }); 27 | -------------------------------------------------------------------------------- /migrations.json: -------------------------------------------------------------------------------- 1 | { 2 | "migrations": [ 3 | { 4 | "cli": "nx", 5 | "version": "20.4.0-beta.1", 6 | "requires": { "@angular/core": ">=19.1.0" }, 7 | "description": "Update the @angular/cli package version to ~19.1.0.", 8 | "factory": "./src/migrations/update-20-4-0/update-angular-cli", 9 | "package": "@nx/angular", 10 | "name": "update-angular-cli-version-19-1-0" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - apps/astro-docs 3 | -------------------------------------------------------------------------------- /tools/tsconfig.tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../dist/out-tsc/tools", 5 | "rootDir": ".", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": ["node"], 9 | "importHelpers": false 10 | }, 11 | "include": ["**/*.ts"] 12 | } 13 | --------------------------------------------------------------------------------