sceneview-mcp 3.5.4 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -10
- package/dist/advanced-guides.js +22 -22
- package/dist/debug-issue.js +18 -20
- package/dist/extra-guides.js +6 -6
- package/dist/generate-scene.js +5 -5
- package/dist/guides.js +21 -22
- package/dist/index.js +16 -16
- package/dist/issues.js +7 -7
- package/dist/migrate-code.js +19 -25
- package/dist/migration.js +25 -25
- package/dist/platform-setup.js +14 -15
- package/dist/samples.js +92 -92
- package/dist/validator.js +10 -11
- package/llms.txt +378 -82
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -39,14 +39,14 @@ catch {
|
|
|
39
39
|
API_DOCS = "SceneView API docs not found. Run `npm run prepare` to bundle llms.txt.";
|
|
40
40
|
}
|
|
41
41
|
const NODE_SECTIONS = parseNodeSections(API_DOCS);
|
|
42
|
-
const server = new Server({ name: "sceneview-mcp", version: "3.
|
|
42
|
+
const server = new Server({ name: "sceneview-mcp", version: "3.6.0" }, { capabilities: { resources: {}, tools: {} } });
|
|
43
43
|
// ─── Resources ───────────────────────────────────────────────────────────────
|
|
44
44
|
server.setRequestHandler(ListResourcesRequestSchema, async () => ({
|
|
45
45
|
resources: [
|
|
46
46
|
{
|
|
47
47
|
uri: "sceneview://api",
|
|
48
48
|
name: "SceneView API Reference",
|
|
49
|
-
description: "Complete SceneView 3.
|
|
49
|
+
description: "Complete SceneView 3.6.0 API — Scene, ARScene, SceneScope DSL, ARSceneScope DSL, node types, resource loading, camera, gestures, math types, threading rules, and common patterns. Read this before writing any SceneView code.",
|
|
50
50
|
mimeType: "text/markdown",
|
|
51
51
|
},
|
|
52
52
|
{
|
|
@@ -514,7 +514,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
514
514
|
? [
|
|
515
515
|
`**SPM dependency:**`,
|
|
516
516
|
`\`\`\`swift`,
|
|
517
|
-
`.package(url: "${sample.spmDependency ?? sample.dependency}", from: "3.
|
|
517
|
+
`.package(url: "${sample.spmDependency ?? sample.dependency}", from: "3.6.0")`,
|
|
518
518
|
`\`\`\``,
|
|
519
519
|
]
|
|
520
520
|
: [
|
|
@@ -587,7 +587,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
587
587
|
`### build.gradle.kts`,
|
|
588
588
|
`\`\`\`kotlin`,
|
|
589
589
|
`dependencies {`,
|
|
590
|
-
` implementation("io.github.sceneview:sceneview:3.
|
|
590
|
+
` implementation("io.github.sceneview:sceneview:3.6.0")`,
|
|
591
591
|
`}`,
|
|
592
592
|
`\`\`\``,
|
|
593
593
|
``,
|
|
@@ -608,7 +608,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
608
608
|
`### build.gradle.kts`,
|
|
609
609
|
`\`\`\`kotlin`,
|
|
610
610
|
`dependencies {`,
|
|
611
|
-
` implementation("io.github.sceneview:arsceneview:3.
|
|
611
|
+
` implementation("io.github.sceneview:arsceneview:3.6.0")`,
|
|
612
612
|
`}`,
|
|
613
613
|
`\`\`\``,
|
|
614
614
|
``,
|
|
@@ -721,7 +721,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
721
721
|
`\`\`\``,
|
|
722
722
|
`https://github.com/sceneview/sceneview`,
|
|
723
723
|
`\`\`\``,
|
|
724
|
-
`Set version rule to **"from: 3.
|
|
724
|
+
`Set version rule to **"from: 3.6.0"**.`,
|
|
725
725
|
``,
|
|
726
726
|
`Or in Package.swift:`,
|
|
727
727
|
`\`\`\`swift`,
|
|
@@ -732,7 +732,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
732
732
|
` name: "MyApp",`,
|
|
733
733
|
` platforms: [.iOS(.v17), .macOS(.v14), .visionOS(.v1)],`,
|
|
734
734
|
` dependencies: [`,
|
|
735
|
-
` .package(url: "https://github.com/sceneview/sceneview", from: "3.
|
|
735
|
+
` .package(url: "https://github.com/sceneview/sceneview", from: "3.6.0")`,
|
|
736
736
|
` ],`,
|
|
737
737
|
` targets: [`,
|
|
738
738
|
` .executableTarget(`,
|
|
@@ -803,7 +803,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
803
803
|
`### 1. Add SPM Dependency`,
|
|
804
804
|
``,
|
|
805
805
|
`\`\`\`swift`,
|
|
806
|
-
`.package(url: "https://github.com/sceneview/sceneview", from: "3.
|
|
806
|
+
`.package(url: "https://github.com/sceneview/sceneview", from: "3.6.0")`,
|
|
807
807
|
`\`\`\``,
|
|
808
808
|
``,
|
|
809
809
|
`### 2. Minimum Platform`,
|
|
@@ -1083,15 +1083,15 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1083
1083
|
// ── list_platforms ────────────────────────────────────────────────────────
|
|
1084
1084
|
case "list_platforms": {
|
|
1085
1085
|
const platforms = [
|
|
1086
|
-
{ platform: "Android", renderer: "Filament", framework: "Jetpack Compose", status: "Stable", version: "3.
|
|
1087
|
-
{ platform: "Android TV", renderer: "Filament", framework: "Compose TV", status: "Alpha", version: "3.
|
|
1086
|
+
{ platform: "Android", renderer: "Filament", framework: "Jetpack Compose", status: "Stable", version: "3.6.0", dependency: "io.github.sceneview:sceneview:3.6.0", features: ["3D", "AR (ARCore)", "Model loading (GLB/glTF)", "Geometry nodes", "Physics", "Gestures"] },
|
|
1087
|
+
{ platform: "Android TV", renderer: "Filament", framework: "Compose TV", status: "Alpha", version: "3.6.0", dependency: "io.github.sceneview:sceneview:3.6.0", features: ["3D", "D-pad controls", "Auto-rotation", "Model loading"] },
|
|
1088
1088
|
{ platform: "Android XR", renderer: "Jetpack XR SceneCore", framework: "Compose XR", status: "Planned", version: "-", dependency: "-", features: ["Spatial computing", "Hand tracking", "Passthrough"] },
|
|
1089
|
-
{ platform: "iOS", renderer: "RealityKit", framework: "SwiftUI", status: "Alpha", version: "3.
|
|
1090
|
-
{ platform: "macOS", renderer: "RealityKit", framework: "SwiftUI", status: "Alpha", version: "3.
|
|
1091
|
-
{ platform: "visionOS", renderer: "RealityKit", framework: "SwiftUI", status: "Alpha", version: "3.
|
|
1092
|
-
{ platform: "Web", renderer: "Filament.js (WASM)", framework: "Kotlin/JS", status: "Alpha", version: "3.
|
|
1093
|
-
{ platform: "Desktop", renderer: "Software / Filament JNI", framework: "Compose Desktop", status: "Alpha", version: "3.
|
|
1094
|
-
{ platform: "Flutter", renderer: "Filament / RealityKit", framework: "PlatformView", status: "Alpha", version: "3.
|
|
1089
|
+
{ platform: "iOS", renderer: "RealityKit", framework: "SwiftUI", status: "Alpha", version: "3.6.0", dependency: "SceneViewSwift (SPM)", features: ["3D", "AR (ARKit)", "16 node types", "USDZ models"] },
|
|
1090
|
+
{ platform: "macOS", renderer: "RealityKit", framework: "SwiftUI", status: "Alpha", version: "3.6.0", dependency: "SceneViewSwift (SPM)", features: ["3D", "Orbit camera", "USDZ models"] },
|
|
1091
|
+
{ platform: "visionOS", renderer: "RealityKit", framework: "SwiftUI", status: "Alpha", version: "3.6.0", dependency: "SceneViewSwift (SPM)", features: ["3D", "Immersive spaces", "Hand tracking (planned)"] },
|
|
1092
|
+
{ platform: "Web", renderer: "Filament.js (WASM)", framework: "Kotlin/JS", status: "Alpha", version: "3.6.0", dependency: "@sceneview/sceneview-web", features: ["3D", "WebXR AR/VR", "GLB models", "WebGL2"] },
|
|
1093
|
+
{ platform: "Desktop", renderer: "Software / Filament JNI", framework: "Compose Desktop", status: "Alpha", version: "3.6.0", dependency: "sceneview-desktop (local)", features: ["3D", "Software renderer", "Wireframe"] },
|
|
1094
|
+
{ platform: "Flutter", renderer: "Filament / RealityKit", framework: "PlatformView", status: "Alpha", version: "3.6.0", dependency: "flutter pub: sceneview", features: ["3D", "AR", "Android + iOS bridge"] },
|
|
1095
1095
|
];
|
|
1096
1096
|
const lines = [
|
|
1097
1097
|
"## SceneView Supported Platforms\n",
|
package/dist/issues.js
CHANGED
|
@@ -20,7 +20,7 @@ export const COMMON_ISSUES = [
|
|
|
20
20
|
title: "LightNode configuration silently ignored",
|
|
21
21
|
symptom: "Light has no effect. Model is completely dark despite having a LightNode in the scene.",
|
|
22
22
|
cause: "`LightNode`'s `apply` is a **named parameter**, not a trailing lambda. Writing `LightNode(...) { intensity(100_000f) }` silently ignores the block — Kotlin treats it as a trailing lambda to a different parameter.",
|
|
23
|
-
solution: "Change `LightNode(
|
|
23
|
+
solution: "Change `LightNode(type) { intensity(...) }` to `LightNode(type = ..., apply = { intensity(100_000f) })`.",
|
|
24
24
|
category: "api-misuse",
|
|
25
25
|
},
|
|
26
26
|
{
|
|
@@ -65,10 +65,10 @@ export const COMMON_ISSUES = [
|
|
|
65
65
|
},
|
|
66
66
|
{
|
|
67
67
|
id: "scene-missing-engine",
|
|
68
|
-
title: "
|
|
69
|
-
symptom: "Compilation error or runtime crash because `
|
|
70
|
-
cause: "In SceneView 3.0, the engine is explicit. `
|
|
71
|
-
solution: "Add `val engine = rememberEngine()` and pass it: `
|
|
68
|
+
title: "SceneView composable crashes — missing engine parameter",
|
|
69
|
+
symptom: "Compilation error or runtime crash because `SceneView(...)` doesn't have an engine.",
|
|
70
|
+
cause: "In SceneView 3.0, the engine is explicit. `SceneView()` requires `engine = rememberEngine()`.",
|
|
71
|
+
solution: "Add `val engine = rememberEngine()` and pass it: `SceneView(engine = engine, modifier = Modifier.fillMaxSize())`.",
|
|
72
72
|
category: "api-misuse",
|
|
73
73
|
},
|
|
74
74
|
{
|
|
@@ -76,7 +76,7 @@ export const COMMON_ISSUES = [
|
|
|
76
76
|
title: "Out of memory with multiple Engine instances",
|
|
77
77
|
symptom: "App uses excessive memory, eventually crashes with OOM. GPU memory grows continuously.",
|
|
78
78
|
cause: "Each `Engine.create()` or `rememberEngine()` allocates GPU resources. Multiple engines in different composables waste GPU memory.",
|
|
79
|
-
solution: "Use a single `rememberEngine()` at the top level and pass it down to all
|
|
79
|
+
solution: "Use a single `rememberEngine()` at the top level and pass it down to all SceneView composables. Never create more than one Engine per app.",
|
|
80
80
|
category: "performance",
|
|
81
81
|
},
|
|
82
82
|
{
|
|
@@ -134,7 +134,7 @@ export async function fetchKnownIssues() {
|
|
|
134
134
|
const response = await fetch("https://api.github.com/repos/sceneview/sceneview/issues?state=open&per_page=30", {
|
|
135
135
|
headers: {
|
|
136
136
|
Accept: "application/vnd.github+json",
|
|
137
|
-
"User-Agent": "sceneview-mcp/3.4
|
|
137
|
+
"User-Agent": "sceneview-mcp/3.5.4",
|
|
138
138
|
"X-GitHub-Api-Version": "2022-11-28",
|
|
139
139
|
},
|
|
140
140
|
});
|
package/dist/migrate-code.js
CHANGED
|
@@ -7,16 +7,10 @@
|
|
|
7
7
|
const MIGRATION_RULES = [
|
|
8
8
|
// ── Composable renames ──────────────────────────────────────────────────
|
|
9
9
|
{
|
|
10
|
-
id: "rename-
|
|
11
|
-
pattern: /\bSceneView\s*\(/g,
|
|
12
|
-
replacement: "Scene(",
|
|
13
|
-
explanation: "`SceneView(...)` renamed to `Scene(...)` in 3.0.",
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
id: "rename-arsceneview-to-arscene",
|
|
10
|
+
id: "rename-arsceneview-capitalization",
|
|
17
11
|
pattern: /\bArSceneView\s*\(/g,
|
|
18
|
-
replacement: "
|
|
19
|
-
explanation: "`ArSceneView(...)` renamed to `
|
|
12
|
+
replacement: "ARSceneView(",
|
|
13
|
+
explanation: "`ArSceneView(...)` renamed to `ARSceneView(...)` in 3.0 (capitalization fix).",
|
|
20
14
|
},
|
|
21
15
|
// ── Model loading ──────────────────────────────────────────────────────
|
|
22
16
|
{
|
|
@@ -94,8 +88,8 @@ const MIGRATION_RULES = [
|
|
|
94
88
|
{
|
|
95
89
|
id: "replace-addChildNode",
|
|
96
90
|
pattern: /(\w+)\.addChildNode\((\w+)\)/g,
|
|
97
|
-
replacement: "// $1.addChildNode($2) — in 3.0, declare nodes as composables inside
|
|
98
|
-
explanation: "Imperative `addChildNode` replaced by declarative composable DSL. Declare nodes inside `
|
|
91
|
+
replacement: "// $1.addChildNode($2) — in 3.0, declare nodes as composables inside SceneView { } instead of adding imperatively",
|
|
92
|
+
explanation: "Imperative `addChildNode` replaced by declarative composable DSL. Declare nodes inside `SceneView { }` content block.",
|
|
99
93
|
},
|
|
100
94
|
// ── AR worldPosition → AnchorNode ──────────────────────────────────────
|
|
101
95
|
{
|
|
@@ -108,8 +102,8 @@ const MIGRATION_RULES = [
|
|
|
108
102
|
{
|
|
109
103
|
id: "replace-camera-manipulator",
|
|
110
104
|
pattern: /setCameraManipulator\(([^)]*)\)/g,
|
|
111
|
-
replacement: "// setCameraManipulator removed — use cameraManipulator = rememberCameraManipulator() on
|
|
112
|
-
explanation: "`setCameraManipulator` replaced by `cameraManipulator = rememberCameraManipulator()` parameter on `
|
|
105
|
+
replacement: "// setCameraManipulator removed — use cameraManipulator = rememberCameraManipulator() on SceneView",
|
|
106
|
+
explanation: "`setCameraManipulator` replaced by `cameraManipulator = rememberCameraManipulator()` parameter on `SceneView`.",
|
|
113
107
|
},
|
|
114
108
|
// ── Material loading ──────────────────────────────────────────────────
|
|
115
109
|
{
|
|
@@ -122,8 +116,8 @@ const MIGRATION_RULES = [
|
|
|
122
116
|
{
|
|
123
117
|
id: "replace-setBackground",
|
|
124
118
|
pattern: /\bsetBackground\s*\(\s*([^)]+)\s*\)/g,
|
|
125
|
-
replacement: "// setBackground($1) removed — use
|
|
126
|
-
explanation: "`setBackground` removed. Use the `environment` parameter on `
|
|
119
|
+
replacement: "// setBackground($1) removed — use SceneView(environment = ...) for background or skybox",
|
|
120
|
+
explanation: "`setBackground` removed. Use the `environment` parameter on `SceneView` for backgrounds and skyboxes.",
|
|
127
121
|
},
|
|
128
122
|
// ── Node.setRenderable → ModelNode ──────────────────────────────────
|
|
129
123
|
{
|
|
@@ -136,8 +130,8 @@ const MIGRATION_RULES = [
|
|
|
136
130
|
{
|
|
137
131
|
id: "replace-onUpdate",
|
|
138
132
|
pattern: /\.onUpdate\s*=\s*\{/g,
|
|
139
|
-
replacement: "// .onUpdate removed — use
|
|
140
|
-
explanation: "`.onUpdate` removed. Use the `onFrame` callback parameter on `
|
|
133
|
+
replacement: "// .onUpdate removed — use SceneView(onFrame = {",
|
|
134
|
+
explanation: "`.onUpdate` removed. Use the `onFrame` callback parameter on `SceneView(onFrame = { ... })`.",
|
|
141
135
|
},
|
|
142
136
|
// ── Node.setParent → composable DSL ──────────────────────────────────
|
|
143
137
|
{
|
|
@@ -150,15 +144,15 @@ const MIGRATION_RULES = [
|
|
|
150
144
|
{
|
|
151
145
|
id: "replace-arfragment",
|
|
152
146
|
pattern: /\bArFragment\b/g,
|
|
153
|
-
replacement: "/* ArFragment removed — use
|
|
154
|
-
explanation: "`ArFragment` (Android View-based) removed. Use `
|
|
147
|
+
replacement: "/* ArFragment removed — use ARSceneView composable in Jetpack Compose */",
|
|
148
|
+
explanation: "`ArFragment` (Android View-based) removed. Use `ARSceneView(...)` composable in Jetpack Compose.",
|
|
155
149
|
},
|
|
156
150
|
// ── onTapArPlane → onTouchEvent ─────────────────────────────────────
|
|
157
151
|
{
|
|
158
152
|
id: "replace-onTapArPlane",
|
|
159
153
|
pattern: /\.onTapArPlane\s*\{/g,
|
|
160
|
-
replacement: "// .onTapArPlane removed — use
|
|
161
|
-
explanation: "`.onTapArPlane` removed. Use `
|
|
154
|
+
replacement: "// .onTapArPlane removed — use ARSceneView(onTouchEvent = { hitResult, motionEvent ->",
|
|
155
|
+
explanation: "`.onTapArPlane` removed. Use `ARSceneView(onTouchEvent = { hitResult, motionEvent -> ... })` and call `hitResult.createAnchor()` yourself.",
|
|
162
156
|
},
|
|
163
157
|
];
|
|
164
158
|
export function migrateCode(code) {
|
|
@@ -207,14 +201,14 @@ export function migrateCode(code) {
|
|
|
207
201
|
if (code.includes("rememberEngine") && !result.includes("rememberEngine")) {
|
|
208
202
|
// Already using 3.0 style
|
|
209
203
|
}
|
|
210
|
-
if (code.includes("
|
|
211
|
-
warnings.push("`
|
|
204
|
+
if (code.includes("SceneView(") && !code.includes("engine")) {
|
|
205
|
+
warnings.push("`SceneView(...)` requires an explicit `engine` parameter in 3.0. Add `val engine = rememberEngine()` and pass it.");
|
|
212
206
|
}
|
|
213
|
-
if (/node\w*\.destroy\(\)/.test(code) && /
|
|
207
|
+
if (/node\w*\.destroy\(\)/.test(code) && /SceneView\s*[({]/.test(code)) {
|
|
214
208
|
warnings.push("Manual `node.destroy()` calls inside composable Scenes should be removed — Compose manages node lifecycle automatically.");
|
|
215
209
|
}
|
|
216
210
|
if (code.includes("ArFragment")) {
|
|
217
|
-
warnings.push("`ArFragment` is the old Android View-based AR component. In 3.0, use the `
|
|
211
|
+
warnings.push("`ArFragment` is the old Android View-based AR component. In 3.0, use the `ARSceneView` composable in Jetpack Compose instead.");
|
|
218
212
|
}
|
|
219
213
|
if (code.includes("Dispatchers.IO") && (code.includes("modelLoader") || code.includes("materialLoader"))) {
|
|
220
214
|
warnings.push("**CRITICAL**: Filament calls (modelLoader, materialLoader) on `Dispatchers.IO` will cause SIGABRT. Use `Dispatchers.Main` or `rememberModelInstance` in composables.");
|
package/dist/migration.js
CHANGED
|
@@ -8,8 +8,8 @@ SceneView 3.0 is a full rewrite from Android Views to **Jetpack Compose**. Nearl
|
|
|
8
8
|
|
|
9
9
|
| 2.x | 3.0 |
|
|
10
10
|
|-----|-----|
|
|
11
|
-
| \`io.github.sceneview:sceneview:2.x.x\` | \`io.github.sceneview:sceneview:3.
|
|
12
|
-
| \`io.github.sceneview:arsceneview:2.x.x\` | \`io.github.sceneview:arsceneview:3.
|
|
11
|
+
| \`io.github.sceneview:sceneview:2.x.x\` | \`io.github.sceneview:sceneview:3.6.0\` |
|
|
12
|
+
| \`io.github.sceneview:arsceneview:2.x.x\` | \`io.github.sceneview:arsceneview:3.6.0\` |
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
@@ -17,8 +17,8 @@ SceneView 3.0 is a full rewrite from Android Views to **Jetpack Compose**. Nearl
|
|
|
17
17
|
|
|
18
18
|
| 2.x | 3.0 |
|
|
19
19
|
|-----|-----|
|
|
20
|
-
| \`SceneView(…)\` | \`
|
|
21
|
-
| \`ArSceneView(…)\` | \`
|
|
20
|
+
| \`SceneView(…)\` | \`SceneView(…)\` |
|
|
21
|
+
| \`ArSceneView(…)\` | \`ARSceneView(…)\` |
|
|
22
22
|
|
|
23
23
|
**Before:**
|
|
24
24
|
\`\`\`kotlin
|
|
@@ -28,7 +28,7 @@ SceneView(modifier = Modifier.fillMaxSize())
|
|
|
28
28
|
**After:**
|
|
29
29
|
\`\`\`kotlin
|
|
30
30
|
val engine = rememberEngine()
|
|
31
|
-
|
|
31
|
+
SceneView(modifier = Modifier.fillMaxSize(), engine = engine)
|
|
32
32
|
\`\`\`
|
|
33
33
|
|
|
34
34
|
---
|
|
@@ -62,7 +62,7 @@ LaunchedEffect(Unit) {
|
|
|
62
62
|
|
|
63
63
|
**After:**
|
|
64
64
|
\`\`\`kotlin
|
|
65
|
-
|
|
65
|
+
SceneView(engine = engine, modelLoader = modelLoader) {
|
|
66
66
|
rememberModelInstance(modelLoader, "models/chair.glb")?.let { instance ->
|
|
67
67
|
ModelNode(modelInstance = instance, scaleToUnits = 1.0f)
|
|
68
68
|
}
|
|
@@ -73,7 +73,7 @@ Scene(engine = engine, modelLoader = modelLoader) {
|
|
|
73
73
|
|
|
74
74
|
## 5. Node hierarchy — imperative → declarative DSL
|
|
75
75
|
|
|
76
|
-
In 2.x nodes were added imperatively (\`scene.addChild(node)\`). In 3.0 nodes are declared as composables inside \`
|
|
76
|
+
In 2.x nodes were added imperatively (\`scene.addChild(node)\`). In 3.0 nodes are declared as composables inside \`SceneView { }\` or \`ARSceneView { }\`.
|
|
77
77
|
|
|
78
78
|
**Before:**
|
|
79
79
|
\`\`\`kotlin
|
|
@@ -88,7 +88,7 @@ sceneView.addChildNode(modelNode)
|
|
|
88
88
|
|
|
89
89
|
**After:**
|
|
90
90
|
\`\`\`kotlin
|
|
91
|
-
|
|
91
|
+
SceneView(engine = engine, modelLoader = modelLoader) {
|
|
92
92
|
rememberModelInstance(modelLoader, "models/chair.glb")?.let { instance ->
|
|
93
93
|
ModelNode(modelInstance = instance, scaleToUnits = 1f)
|
|
94
94
|
}
|
|
@@ -131,7 +131,7 @@ ViewRenderable.builder()
|
|
|
131
131
|
|
|
132
132
|
// After
|
|
133
133
|
val windowManager = rememberViewNodeManager()
|
|
134
|
-
|
|
134
|
+
SceneView(viewNodeWindowManager = windowManager) {
|
|
135
135
|
ViewNode(windowManager = windowManager) {
|
|
136
136
|
Card { Text("Hello 3D World!") }
|
|
137
137
|
}
|
|
@@ -172,7 +172,7 @@ LightNode(
|
|
|
172
172
|
\`\`\`kotlin
|
|
173
173
|
// 3.0
|
|
174
174
|
val environmentLoader = rememberEnvironmentLoader(engine)
|
|
175
|
-
|
|
175
|
+
SceneView(
|
|
176
176
|
environment = rememberEnvironment(environmentLoader) {
|
|
177
177
|
environmentLoader.createHDREnvironment("environments/sky_2k.hdr") ?: createEnvironment(environmentLoader)
|
|
178
178
|
}
|
|
@@ -183,10 +183,10 @@ Scene(
|
|
|
183
183
|
|
|
184
184
|
## 9. AR session configuration
|
|
185
185
|
|
|
186
|
-
In 3.0 \`sessionConfiguration\` is a lambda parameter on \`
|
|
186
|
+
In 3.0 \`sessionConfiguration\` is a lambda parameter on \`ARSceneView\` (not a separate builder).
|
|
187
187
|
|
|
188
188
|
\`\`\`kotlin
|
|
189
|
-
|
|
189
|
+
ARSceneView(
|
|
190
190
|
engine = engine,
|
|
191
191
|
modelLoader = modelLoader,
|
|
192
192
|
sessionConfiguration = { session, config ->
|
|
@@ -213,10 +213,10 @@ Plain nodes whose \`worldPosition\` is set manually will drift when ARCore remap
|
|
|
213
213
|
|
|
214
214
|
## 11. Shadows
|
|
215
215
|
|
|
216
|
-
In 3.0, \`
|
|
216
|
+
In 3.0, \`ARSceneView\` has shadows enabled by default via \`createARView()\`. For \`SceneView\` (3D only), shadows are disabled by default — enable with:
|
|
217
217
|
|
|
218
218
|
\`\`\`kotlin
|
|
219
|
-
|
|
219
|
+
SceneView(
|
|
220
220
|
view = rememberView(engine).also { it.setShadowingEnabled(true) },
|
|
221
221
|
…
|
|
222
222
|
)
|
|
@@ -228,15 +228,15 @@ Scene(
|
|
|
228
228
|
|
|
229
229
|
| 2.x | 3.0 |
|
|
230
230
|
|-----|-----|
|
|
231
|
-
| \`CameraManipulator\` set on the View | \`cameraManipulator = rememberCameraManipulator()\` on \`
|
|
232
|
-
| Custom camera via \`setCameraNode\` | \`cameraNode = rememberCameraNode(engine) { … }\` on \`
|
|
231
|
+
| \`CameraManipulator\` set on the View | \`cameraManipulator = rememberCameraManipulator()\` on \`SceneView\` |
|
|
232
|
+
| Custom camera via \`setCameraNode\` | \`cameraNode = rememberCameraNode(engine) { … }\` on \`SceneView\` |
|
|
233
233
|
|
|
234
234
|
---
|
|
235
235
|
|
|
236
236
|
## Checklist
|
|
237
237
|
|
|
238
|
-
- [ ] Replace \`SceneView(…)\` → \`
|
|
239
|
-
- [ ] Replace \`ArSceneView(…)\` → \`
|
|
238
|
+
- [ ] Replace \`SceneView(…)\` → \`SceneView(engine = rememberEngine(), …)\`
|
|
239
|
+
- [ ] Replace \`ArSceneView(…)\` → \`ARSceneView(engine = rememberEngine(), …)\`
|
|
240
240
|
- [ ] Replace \`modelLoader.loadModelAsync\` → \`rememberModelInstance\`
|
|
241
241
|
- [ ] Add null-check on every \`rememberModelInstance\` result
|
|
242
242
|
- [ ] Replace \`TransformableNode\` → \`isEditable = true\`
|
|
@@ -245,7 +245,7 @@ Scene(
|
|
|
245
245
|
- [ ] Fix \`LightNode { … }\` → \`LightNode(apply = { … })\`
|
|
246
246
|
- [ ] Remove manual \`engine.destroy()\` calls
|
|
247
247
|
- [ ] Replace manual \`worldPosition\` in AR → \`AnchorNode\`
|
|
248
|
-
- [ ] Replace \`ArFragment\` → \`
|
|
248
|
+
- [ ] Replace \`ArFragment\` → \`ARSceneView()\` composable
|
|
249
249
|
- [ ] Replace \`onTapArPlane\` → \`onTouchEvent\`
|
|
250
250
|
- [ ] Replace \`setRenderable\` → \`ModelNode(modelInstance = ...)\`
|
|
251
251
|
- [ ] Replace \`setParent\` → nest composable nodes inside parent
|
|
@@ -273,8 +273,8 @@ Scene(
|
|
|
273
273
|
|
|
274
274
|
| 2.x | 3.0 |
|
|
275
275
|
|-----|-----|
|
|
276
|
-
| \`ArFragment\` in XML layout | \`
|
|
277
|
-
| \`arFragment.setOnTapArPlaneListener\` | \`
|
|
276
|
+
| \`ArFragment\` in XML layout | \`ARSceneView()\` composable |
|
|
277
|
+
| \`arFragment.setOnTapArPlaneListener\` | \`ARSceneView(onTouchEvent = { … })\` |
|
|
278
278
|
| \`arFragment.arSceneView\` | Direct access via composable params |
|
|
279
279
|
|
|
280
280
|
---
|
|
@@ -284,7 +284,7 @@ Scene(
|
|
|
284
284
|
| 2.x | 3.0 |
|
|
285
285
|
|-----|-----|
|
|
286
286
|
| \`node.setParent(parentNode)\` | Nest composable nodes inside parent's content block |
|
|
287
|
-
| \`sceneView.scene.addChild(node)\` | Declare nodes inside \`
|
|
287
|
+
| \`sceneView.scene.addChild(node)\` | Declare nodes inside \`SceneView { }\` content block |
|
|
288
288
|
|
|
289
289
|
---
|
|
290
290
|
|
|
@@ -295,13 +295,13 @@ If migrating from Google Sceneform 1.x (the original \`com.google.ar.sceneform\`
|
|
|
295
295
|
| Sceneform 1.x | SceneView 3.0 |
|
|
296
296
|
|---|---|
|
|
297
297
|
| \`com.google.ar.sceneform.*\` imports | \`io.github.sceneview.*\` imports |
|
|
298
|
-
| \`ArFragment\` + XML | \`
|
|
298
|
+
| \`ArFragment\` + XML | \`ARSceneView()\` composable |
|
|
299
299
|
| \`ModelRenderable.builder().setSource()\` | \`rememberModelInstance(modelLoader, "file.glb")\` |
|
|
300
300
|
| \`ViewRenderable.builder().setView()\` | \`ViewNode { ComposeContent() }\` |
|
|
301
|
-
| \`Node().setParent(scene)\` | Declare nodes inside \`
|
|
301
|
+
| \`Node().setParent(scene)\` | Declare nodes inside \`SceneView { }\` |
|
|
302
302
|
| \`TransformableNode(transformSystem)\` | \`ModelNode(isEditable = true)\` |
|
|
303
303
|
| \`node.localPosition = Vector3()\` | \`position = Position(x, y, z)\` on node composable |
|
|
304
|
-
| \`ArSceneView\` (View) | \`
|
|
304
|
+
| \`ArSceneView\` (View) | \`ARSceneView()\` (Composable) |
|
|
305
305
|
| Java callbacks | Kotlin coroutines + Compose state |
|
|
306
306
|
|
|
307
307
|
**Key differences from Sceneform:**
|
package/dist/platform-setup.js
CHANGED
|
@@ -12,7 +12,7 @@ const ANDROID_3D = `## SceneView Android — 3D Setup
|
|
|
12
12
|
\`\`\`kotlin
|
|
13
13
|
// build.gradle.kts (app module)
|
|
14
14
|
dependencies {
|
|
15
|
-
implementation("io.github.sceneview:sceneview:3.
|
|
15
|
+
implementation("io.github.sceneview:sceneview:3.6.0")
|
|
16
16
|
}
|
|
17
17
|
\`\`\`
|
|
18
18
|
|
|
@@ -39,7 +39,7 @@ fun My3DScreen() {
|
|
|
39
39
|
val modelLoader = rememberModelLoader(engine)
|
|
40
40
|
val environmentLoader = rememberEnvironmentLoader(engine)
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
SceneView(
|
|
43
43
|
modifier = Modifier.fillMaxSize(),
|
|
44
44
|
engine = engine,
|
|
45
45
|
modelLoader = modelLoader,
|
|
@@ -57,7 +57,6 @@ fun My3DScreen() {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
LightNode(
|
|
60
|
-
engine = engine,
|
|
61
60
|
type = LightManager.Type.DIRECTIONAL,
|
|
62
61
|
apply = {
|
|
63
62
|
intensity(100_000f)
|
|
@@ -88,7 +87,7 @@ const ANDROID_AR = `## SceneView Android — AR Setup
|
|
|
88
87
|
\`\`\`kotlin
|
|
89
88
|
// build.gradle.kts (app module)
|
|
90
89
|
dependencies {
|
|
91
|
-
implementation("io.github.sceneview:arsceneview:3.
|
|
90
|
+
implementation("io.github.sceneview:arsceneview:3.6.0")
|
|
92
91
|
// arsceneview includes sceneview transitively
|
|
93
92
|
}
|
|
94
93
|
\`\`\`
|
|
@@ -127,7 +126,7 @@ fun MyARScreen() {
|
|
|
127
126
|
|
|
128
127
|
val modelInstance = rememberModelInstance(modelLoader, "models/robot.glb")
|
|
129
128
|
|
|
130
|
-
|
|
129
|
+
ARSceneView(
|
|
131
130
|
modifier = Modifier.fillMaxSize(),
|
|
132
131
|
engine = engine,
|
|
133
132
|
modelLoader = modelLoader,
|
|
@@ -178,7 +177,7 @@ In Xcode: **File > Add Package Dependencies** > paste:
|
|
|
178
177
|
\`\`\`
|
|
179
178
|
https://github.com/sceneview/sceneview
|
|
180
179
|
\`\`\`
|
|
181
|
-
Set version rule to **"from: 3.
|
|
180
|
+
Set version rule to **"from: 3.6.0"**.
|
|
182
181
|
|
|
183
182
|
Or in Package.swift:
|
|
184
183
|
\`\`\`swift
|
|
@@ -189,7 +188,7 @@ let package = Package(
|
|
|
189
188
|
name: "MyApp",
|
|
190
189
|
platforms: [.iOS(.v18), .macOS(.v15), .visionOS(.v1)],
|
|
191
190
|
dependencies: [
|
|
192
|
-
.package(url: "https://github.com/sceneview/sceneview", from: "3.
|
|
191
|
+
.package(url: "https://github.com/sceneview/sceneview", from: "3.6.0")
|
|
193
192
|
],
|
|
194
193
|
targets: [
|
|
195
194
|
.executableTarget(
|
|
@@ -274,7 +273,7 @@ const IOS_AR = `## SceneViewSwift — iOS AR Setup
|
|
|
274
273
|
### 1. SPM Dependency
|
|
275
274
|
|
|
276
275
|
\`\`\`swift
|
|
277
|
-
.package(url: "https://github.com/sceneview/sceneview", from: "3.
|
|
276
|
+
.package(url: "https://github.com/sceneview/sceneview", from: "3.6.0")
|
|
278
277
|
\`\`\`
|
|
279
278
|
|
|
280
279
|
### 2. Info.plist — Camera Permission (Required)
|
|
@@ -418,7 +417,7 @@ SceneView Flutter uses **PlatformView** to embed native SceneView (Android: Fila
|
|
|
418
417
|
\`\`\`yaml
|
|
419
418
|
# pubspec.yaml
|
|
420
419
|
dependencies:
|
|
421
|
-
sceneview_flutter: ^3.
|
|
420
|
+
sceneview_flutter: ^3.6.0
|
|
422
421
|
\`\`\`
|
|
423
422
|
|
|
424
423
|
### 2. Android Setup
|
|
@@ -477,7 +476,7 @@ const FLUTTER_AR = `## SceneView Flutter — AR Setup
|
|
|
477
476
|
|
|
478
477
|
\`\`\`yaml
|
|
479
478
|
dependencies:
|
|
480
|
-
sceneview_flutter: ^3.
|
|
479
|
+
sceneview_flutter: ^3.6.0
|
|
481
480
|
\`\`\`
|
|
482
481
|
|
|
483
482
|
### 2. Android Manifest
|
|
@@ -633,7 +632,7 @@ plugins {
|
|
|
633
632
|
|
|
634
633
|
dependencies {
|
|
635
634
|
implementation(compose.desktop.currentOs)
|
|
636
|
-
implementation("io.github.sceneview:sceneview-desktop:3.
|
|
635
|
+
implementation("io.github.sceneview:sceneview-desktop:3.6.0") // when published
|
|
637
636
|
}
|
|
638
637
|
\`\`\`
|
|
639
638
|
|
|
@@ -684,7 +683,7 @@ SceneView on Android TV uses the same Filament renderer as mobile Android, with
|
|
|
684
683
|
|
|
685
684
|
\`\`\`kotlin
|
|
686
685
|
dependencies {
|
|
687
|
-
implementation("io.github.sceneview:sceneview:3.
|
|
686
|
+
implementation("io.github.sceneview:sceneview:3.6.0")
|
|
688
687
|
implementation("androidx.leanback:leanback:1.0.0")
|
|
689
688
|
implementation("androidx.tv:tv-foundation:1.0.0-alpha10")
|
|
690
689
|
}
|
|
@@ -723,7 +722,7 @@ fun TVModelViewer() {
|
|
|
723
722
|
}
|
|
724
723
|
}
|
|
725
724
|
) {
|
|
726
|
-
|
|
725
|
+
SceneView(
|
|
727
726
|
modifier = Modifier.fillMaxSize(),
|
|
728
727
|
engine = engine,
|
|
729
728
|
modelLoader = modelLoader
|
|
@@ -749,14 +748,14 @@ const SETUPS = {
|
|
|
749
748
|
android: {
|
|
750
749
|
name: "Android (Jetpack Compose)",
|
|
751
750
|
renderer: "Filament (OpenGL ES / Vulkan)",
|
|
752
|
-
status: "Stable (v3.
|
|
751
|
+
status: "Stable (v3.6.0)",
|
|
753
752
|
guide3d: ANDROID_3D,
|
|
754
753
|
guideAr: ANDROID_AR,
|
|
755
754
|
},
|
|
756
755
|
ios: {
|
|
757
756
|
name: "iOS / macOS / visionOS (SwiftUI)",
|
|
758
757
|
renderer: "RealityKit (Metal)",
|
|
759
|
-
status: "Alpha (v3.
|
|
758
|
+
status: "Alpha (v3.6.0)",
|
|
760
759
|
guide3d: IOS_3D,
|
|
761
760
|
guideAr: IOS_AR,
|
|
762
761
|
},
|