diff --git a/Dockerfile b/Dockerfile index 4a80c22..c32e53c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ ARG NEEDLE_APP=MenuScene -FROM node:22-alpine AS builder +FROM node:22 AS builder ARG NEEDLE_APP WORKDIR /src diff --git a/Needle/MenuScene/dist/assets/MenuScene.glb b/Needle/MenuScene/dist/assets/MenuScene.glb index 6f54354..a57c507 100644 Binary files a/Needle/MenuScene/dist/assets/MenuScene.glb and b/Needle/MenuScene/dist/assets/MenuScene.glb differ diff --git a/Needle/MenuScene/dist/include/poster.webp b/Needle/MenuScene/dist/include/poster.webp index e136f53..706de64 100644 Binary files a/Needle/MenuScene/dist/include/poster.webp and b/Needle/MenuScene/dist/include/poster.webp differ diff --git a/Needle/MenuScene/include/poster.webp b/Needle/MenuScene/include/poster.webp index 749fd3c..10d47e3 100644 --- a/Needle/MenuScene/include/poster.webp +++ b/Needle/MenuScene/include/poster.webp @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aa2a970d9cbc1163c124fea1d4084c8f5eb5f13a917b6f87ad390cdeb351dfd2 -size 10228 +oid sha256:040eaa6fc1886df527c36ba590d5bcb97a956283e8685eb8ec0427c301d9becc +size 10526 diff --git a/Needle/MenuScene/src/assetPicker.ts b/Needle/MenuScene/src/assetPicker.ts index 1484f99..50daade 100644 --- a/Needle/MenuScene/src/assetPicker.ts +++ b/Needle/MenuScene/src/assetPicker.ts @@ -19,7 +19,7 @@ function initAssetPicker(): void { const labelEl = document.querySelector("#asset-picker-label"); const indexEl = document.querySelector("#asset-picker-index"); - if (!needle || !prev || !next || !arBtn || !labelEl || !indexEl) return; + if (!needle || !prev || !next || !labelEl || !indexEl) return; let menuController: MenuController | null = null; let immersiveSessionActive = false; @@ -43,10 +43,12 @@ function initAssetPicker(): void { prev.disabled = !canNav; next.disabled = !canNav; - arBtn.disabled = - !arSupported || - arStarting || - immersiveSessionActive; + if (arBtn) { + arBtn.disabled = + !arSupported || + arStarting || + immersiveSessionActive; + } }; const bindMenuController = async (): Promise => { @@ -88,7 +90,7 @@ function initAssetPicker(): void { prev.addEventListener("click", () => requestNavigate(-1)); next.addEventListener("click", () => requestNavigate(1)); - arBtn.addEventListener("click", () => void startAr()); + arBtn?.addEventListener("click", () => void startAr()); needle.addEventListener("enter-ar", () => { immersiveSessionActive = true; diff --git a/Needle/MenuScene/src/disableCameraControls.ts b/Needle/MenuScene/src/disableCameraControls.ts new file mode 100644 index 0000000..200a092 --- /dev/null +++ b/Needle/MenuScene/src/disableCameraControls.ts @@ -0,0 +1,27 @@ +import { onStart, OrbitControls } from "@needle-tools/engine"; + +/** + * Turn off orbit / pan / zoom from the exported scene (Main Camera often has {@link OrbitControls}). + * `` only skips auto-injected controls; Unity-serialized ones + * must be disabled in code. + */ +onStart((context) => { + const oc = context.scene.getComponentInChildren(OrbitControls); + if (!oc) return; + + oc.enableRotate = false; + oc.enablePan = false; + oc.enableZoom = false; + oc.enableKeys = false; + oc.autoRotate = false; + oc.middleClickToFocus = false; + oc.doubleClickToFocus = false; + oc.clickBackgroundToFitScene = 0; + + const three = oc.controls; + if (three) { + three.enabled = false; + } + + oc.enabled = false; +}); diff --git a/Needle/MenuScene/src/generated/gen.js b/Needle/MenuScene/src/generated/gen.js index 3c80780..b6cbb97 100644 --- a/Needle/MenuScene/src/generated/gen.js +++ b/Needle/MenuScene/src/generated/gen.js @@ -19,7 +19,7 @@ document.addEventListener("DOMContentLoaded", () => const needleEngine = document.querySelector("needle-engine"); if(needleEngine && needleEngine.getAttribute("src") === null) { - needleEngine.setAttribute("hash", "1776659726595"); + needleEngine.setAttribute("hash", "1776799769658"); needleEngine.setAttribute("src", JSON.stringify(needle_exported_files)); } }); diff --git a/Needle/MenuScene/src/main.ts b/Needle/MenuScene/src/main.ts index 322d8be..6ee3a3a 100644 --- a/Needle/MenuScene/src/main.ts +++ b/Needle/MenuScene/src/main.ts @@ -1,4 +1,5 @@ import("@needle-tools/engine") /* async import of needle engine */; +import "./disableCameraControls"; import "./dishMeshFallback"; import "./enableXR"; import "./assetPicker"; \ No newline at end of file diff --git a/Needle/MenuScene/src/scripts/MenuController.ts b/Needle/MenuScene/src/scripts/MenuController.ts index 0811e1b..061dd1b 100644 --- a/Needle/MenuScene/src/scripts/MenuController.ts +++ b/Needle/MenuScene/src/scripts/MenuController.ts @@ -26,13 +26,16 @@ export class MenuController extends Behaviour { @serializable(Object3D) webXROrigin?: Object3D; - /** Local-space vertical bob amplitude (meters). Set to 0 to disable. */ + /** + * Local-space vertical bob amplitude (meters). Set to 0 to disable. + * Peak-to-peak motion is 2× this value; 0.004 ≈ 8 mm total — subtle but visible. + */ @serializable() - dishBobAmplitude = 0.05; + dishBobAmplitude = 0.004; /** Bob angular speed (radians per second). */ @serializable() - dishBobSpeed = 2.5; + dishBobSpeed = 1.0; private usdzExporter?: USDZExporter; diff --git a/Needle/MenuScene/src/styles/style.css b/Needle/MenuScene/src/styles/style.css index f751a3e..aa7798b 100644 --- a/Needle/MenuScene/src/styles/style.css +++ b/Needle/MenuScene/src/styles/style.css @@ -63,16 +63,6 @@ needle-engine { cursor: not-allowed; } -#asset-picker #asset-picker-ar { - background: #34c759; - color: #0a0a0c; -} - -#asset-picker #asset-picker-ar:disabled { - background: #3a3a3e; - color: rgba(255, 255, 255, 0.5); -} - #asset-picker .asset-picker__label { flex: 1; min-width: 0; diff --git a/Needle/SampleScene/index.html b/Needle/SampleScene/index.html index 5d15a97..a97848e 100644 --- a/Needle/SampleScene/index.html +++ b/Needle/SampleScene/index.html @@ -20,14 +20,13 @@ - +
-
diff --git a/Needle/SampleScene/src/assetPicker.ts b/Needle/SampleScene/src/assetPicker.ts index 74c889e..7065506 100644 --- a/Needle/SampleScene/src/assetPicker.ts +++ b/Needle/SampleScene/src/assetPicker.ts @@ -19,7 +19,7 @@ function initAssetPicker(): void { const labelEl = document.querySelector("#asset-picker-label"); const indexEl = document.querySelector("#asset-picker-index"); - if (!needle || !prev || !next || !arBtn || !labelEl || !indexEl) return; + if (!needle || !prev || !next || !labelEl || !indexEl) return; let menuController: MenuController | null = null; let immersiveSessionActive = false; @@ -43,10 +43,12 @@ function initAssetPicker(): void { prev.disabled = !canNav; next.disabled = !canNav; - arBtn.disabled = - !arSupported || - arStarting || - immersiveSessionActive; + if (arBtn) { + arBtn.disabled = + !arSupported || + arStarting || + immersiveSessionActive; + } }; const bindMenuController = async (): Promise => { @@ -88,7 +90,7 @@ function initAssetPicker(): void { prev.addEventListener("click", () => requestNavigate(-1)); next.addEventListener("click", () => requestNavigate(1)); - arBtn.addEventListener("click", () => void startAr()); + arBtn?.addEventListener("click", () => void startAr()); needle.addEventListener("enter-ar", () => { immersiveSessionActive = true; diff --git a/Needle/SampleScene/src/disableCameraControls.ts b/Needle/SampleScene/src/disableCameraControls.ts new file mode 100644 index 0000000..42e08a4 --- /dev/null +++ b/Needle/SampleScene/src/disableCameraControls.ts @@ -0,0 +1,27 @@ +import { onStart, OrbitControls } from "@needle-tools/engine"; + +/** + * Turn off orbit / pan / zoom from the exported scene. + * `` only skips auto-injected controls; Unity-serialized ones + * must be disabled in code. + */ +onStart((context) => { + const oc = context.scene.getComponentInChildren(OrbitControls); + if (!oc) return; + + oc.enableRotate = false; + oc.enablePan = false; + oc.enableZoom = false; + oc.enableKeys = false; + oc.autoRotate = false; + oc.middleClickToFocus = false; + oc.doubleClickToFocus = false; + oc.clickBackgroundToFitScene = 0; + + const three = oc.controls; + if (three) { + three.enabled = false; + } + + oc.enabled = false; +}); diff --git a/Needle/SampleScene/src/generated/gen.js b/Needle/SampleScene/src/generated/gen.js new file mode 100644 index 0000000..14b7421 --- /dev/null +++ b/Needle/SampleScene/src/generated/gen.js @@ -0,0 +1,27 @@ +/* +* Developer Information: +* This file was generated using Unity 6000.4.3f1. +* Do not modify this file manually. + +* Instead of using generated code you can also load the 3D scene like this: +* (When you're working with Unity the glTF file name will always match your scene or prefab's name) +*/ + +globalThis["needle:dependencies:ready"] = import("./register_types.ts") + +/** @type {string[]} */ +export const needle_exported_files = new Array(); +globalThis["needle:codegen_files"] = needle_exported_files; +import "../../assets/SampleScene.glb?url"; +needle_exported_files.push("./assets/SampleScene.glb"); +document.addEventListener("DOMContentLoaded", () => +{ + const needleEngine = document.querySelector("needle-engine"); + if(needleEngine && needleEngine.getAttribute("src") === null) + { + needleEngine.setAttribute("hash", "1776607707382"); + needleEngine.setAttribute("src", JSON.stringify(needle_exported_files)); + } +}); + +console.log("Made\ with\ ♥\ by\ 🌵\ Needle\ -\ https://needle\.tools\ —\ Version\ 5\.0\.3"); diff --git a/Needle/SampleScene/src/generated/meta.json b/Needle/SampleScene/src/generated/meta.json new file mode 100644 index 0000000..4822b59 --- /dev/null +++ b/Needle/SampleScene/src/generated/meta.json @@ -0,0 +1,16 @@ +{ + "sceneName": "Sample Scene", + "meta": null, + "absolutePath": "https://localhost:3000", + "deployOnly": false, + "needleEditor": null, + "gzip": true, + "generator": "Unity 6000.4.3f1, Needle Engine Integration @5.0.3", + "license": { + "team": "org_vl8u9dsjhx6b" + }, + "allowHotReload": true, + "developmentBuild": false, + "facebookInstantGames": null, + "useRapier": true +} \ No newline at end of file diff --git a/Needle/SampleScene/src/generated/register_types.ts b/Needle/SampleScene/src/generated/register_types.ts new file mode 100644 index 0000000..8414840 --- /dev/null +++ b/Needle/SampleScene/src/generated/register_types.ts @@ -0,0 +1,10 @@ +/* eslint-disable */ +import { TypeStore } from "@needle-tools/engine"; + +import { ARObjectController } from "../scripts/ARObjectController.js"; +import { MenuController } from "../scripts/MenuController.js"; +import { PostProcessingVolumeController } from "../scripts/PostProcessingVolumeController.js"; + +TypeStore.add("ARObjectController", ARObjectController); +TypeStore.add("MenuController", MenuController); +TypeStore.add("PostProcessingVolumeController", PostProcessingVolumeController); diff --git a/Needle/SampleScene/src/main.ts b/Needle/SampleScene/src/main.ts index 30960c7..a260383 100644 --- a/Needle/SampleScene/src/main.ts +++ b/Needle/SampleScene/src/main.ts @@ -1,3 +1,4 @@ import("@needle-tools/engine") /* async import of needle engine */; +import "./disableCameraControls"; import "./enableXR"; import "./assetPicker"; \ No newline at end of file diff --git a/Needle/SampleScene/src/scripts/MenuController.ts b/Needle/SampleScene/src/scripts/MenuController.ts index c10f7a8..cc21d67 100644 --- a/Needle/SampleScene/src/scripts/MenuController.ts +++ b/Needle/SampleScene/src/scripts/MenuController.ts @@ -26,13 +26,16 @@ export class MenuController extends Behaviour { @serializable(Object3D) webXROrigin?: Object3D; - /** Local-space vertical bob amplitude (meters). Set to 0 to disable. */ + /** + * Local-space vertical bob amplitude (meters). Set to 0 to disable. + * Peak-to-peak motion is 2× this value; 0.004 ≈ 8 mm total — subtle but visible. + */ @serializable() - dishBobAmplitude = 0.05; + dishBobAmplitude = 0.004; /** Bob angular speed (radians per second). */ @serializable() - dishBobSpeed = 2.5; + dishBobSpeed = 1.0; private usdzExporter?: USDZExporter; diff --git a/Needle/SampleScene/src/styles/style.css b/Needle/SampleScene/src/styles/style.css index f751a3e..aa7798b 100644 --- a/Needle/SampleScene/src/styles/style.css +++ b/Needle/SampleScene/src/styles/style.css @@ -63,16 +63,6 @@ needle-engine { cursor: not-allowed; } -#asset-picker #asset-picker-ar { - background: #34c759; - color: #0a0a0c; -} - -#asset-picker #asset-picker-ar:disabled { - background: #3a3a3e; - color: rgba(255, 255, 255, 0.5); -} - #asset-picker .asset-picker__label { flex: 1; min-width: 0;