sceneview-mcp 3.5.4 → 3.5.5

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 CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/sceneview-mcp?color=6c35aa)](https://www.npmjs.com/package/sceneview-mcp)
6
6
  [![npm downloads](https://img.shields.io/npm/dm/sceneview-mcp?color=blue)](https://www.npmjs.com/package/sceneview-mcp)
7
- [![Tests](https://img.shields.io/badge/tests-858%20passing-brightgreen)](#quality)
7
+ [![Tests](https://img.shields.io/badge/tests-2360%20passing-brightgreen)](#quality)
8
8
  [![MCP](https://img.shields.io/badge/MCP-v1.12-blue)](https://modelcontextprotocol.io/)
9
9
  [![Registry](https://img.shields.io/badge/MCP%20Registry-listed-blueviolet)](https://registry.modelcontextprotocol.io)
10
10
  [![License](https://img.shields.io/badge/License-MIT-green)](./LICENSE)
@@ -12,7 +12,7 @@
12
12
 
13
13
  The official [Model Context Protocol](https://modelcontextprotocol.io/) server for **[SceneView](https://sceneview.github.io)** -- the cross-platform 3D & AR SDK for Android (Jetpack Compose + Filament), iOS/macOS/visionOS (SwiftUI + RealityKit), and Web (Filament.js + WebXR).
14
14
 
15
- Connect it to Claude, Cursor, Windsurf, or any MCP client. The assistant gets 22 specialized tools, 33 compilable code samples, a full API reference, and a code validator -- so it writes correct, working 3D/AR code on the first try.
15
+ Connect it to Claude, Cursor, Windsurf, or any MCP client. The assistant gets 26 specialized tools, 33 compilable code samples, a full API reference, and a code validator -- so it writes correct, working 3D/AR code on the first try.
16
16
 
17
17
  > **Disclaimer:** Generated code is provided "as is" without warranty. Always review before production use. See [TERMS.md](./TERMS.md) and [PRIVACY.md](./PRIVACY.md).
18
18
 
@@ -84,7 +84,7 @@ Same JSON config as above. The server communicates via **stdio** using the stand
84
84
 
85
85
  ## What you get
86
86
 
87
- ### 22 tools
87
+ ### 26 tools
88
88
 
89
89
  | Tool | What it does |
90
90
  |---|---|
@@ -115,7 +115,7 @@ Same JSON config as above. The server communicates via **stdio** using the stand
115
115
 
116
116
  | Resource URI | What it provides |
117
117
  |---|---|
118
- | `sceneview://api` | Complete SceneView 3.5.0 API reference (the full `llms.txt`) |
118
+ | `sceneview://api` | Complete SceneView 3.6.0 API reference (the full `llms.txt`) |
119
119
  | `sceneview://known-issues` | Live open issues from GitHub (cached 10 min) |
120
120
 
121
121
  ---
@@ -155,7 +155,7 @@ The assistant calls `render_3d_preview` and returns an interactive link to a bro
155
155
  - Have no knowledge of SceneView's iOS/Swift API at all
156
156
 
157
157
  **With** this MCP server, AI assistants:
158
- - Always use the current SceneView 3.5.0 API surface
158
+ - Always use the current SceneView 3.6.0 API surface
159
159
  - Generate correct **Compose-native** 3D/AR code for Android
160
160
  - Generate correct **SwiftUI-native** code for iOS/macOS/visionOS
161
161
  - Know about all 26+ node types and their exact parameters
@@ -166,7 +166,7 @@ The assistant calls `render_3d_preview` and returns an interactive link to a bro
166
166
 
167
167
  ## Quality
168
168
 
169
- The MCP server is tested with **858 unit tests** across 22 test suites covering:
169
+ The MCP server is tested with **2360 unit tests** across 98 test suites covering:
170
170
 
171
171
  - Every tool response (correct output, error handling, edge cases)
172
172
  - All 33 code samples (compilable structure, correct imports, no deprecated APIs)
@@ -176,7 +176,7 @@ The MCP server is tested with **858 unit tests** across 22 test suites covering:
176
176
 
177
177
  ```
178
178
  Test Files 22 passed (22)
179
- Tests 858 passed (858)
179
+ Tests 2360 passed (2360)
180
180
  Duration 624ms
181
181
  ```
182
182
 
@@ -228,7 +228,7 @@ The only network call is to the GitHub API (for known issues). All other tools w
228
228
  cd mcp
229
229
  npm install
230
230
  npm run prepare # Copy llms.txt + build TypeScript
231
- npm test # 858 tests
231
+ npm test # 2360 tests
232
232
  npm run dev # Start with tsx (hot reload)
233
233
  ```
234
234
 
@@ -237,7 +237,7 @@ npm run dev # Start with tsx (hot reload)
237
237
  ```
238
238
  mcp/
239
239
  src/
240
- index.ts # MCP server entry point (22 tools, 2 resources)
240
+ index.ts # MCP server entry point (26 tools, 2 resources)
241
241
  samples.ts # 33 compilable code samples (Kotlin + Swift)
242
242
  validator.ts # Code validator (15+ rules, Kotlin + Swift)
243
243
  node-reference.ts # Node type parser (extracts from llms.txt)
@@ -254,7 +254,7 @@ mcp/
254
254
  1. Fork the repository
255
255
  2. Create a feature branch
256
256
  3. Add tests for new tools or rules
257
- 4. Run `npm test` -- all 858+ tests must pass
257
+ 4. Run `npm test` -- all 2360+ tests must pass
258
258
  5. Submit a pull request
259
259
 
260
260
  See [CONTRIBUTING.md](../CONTRIBUTING.md) for the full guide.
@@ -17,7 +17,7 @@ fun AnimatedModelScreen() {
17
17
  val modelLoader = rememberModelLoader(engine)
18
18
  val modelInstance = rememberModelInstance(modelLoader, "models/character.glb")
19
19
 
20
- Scene(engine = engine) {
20
+ SceneView(engine = engine) {
21
21
  modelInstance?.let { instance ->
22
22
  ModelNode(
23
23
  modelInstance = instance,
@@ -39,7 +39,7 @@ fun ManualAnimationScreen() {
39
39
  val modelLoader = rememberModelLoader(engine)
40
40
  val modelInstance = rememberModelInstance(modelLoader, "models/robot.glb")
41
41
 
42
- Scene(
42
+ SceneView(
43
43
  engine = engine,
44
44
  onFrame = { frameTimeNanos ->
45
45
  modelInstance?.let { instance ->
@@ -101,7 +101,7 @@ fun SpringAnimatedNode() {
101
101
  )
102
102
  }
103
103
 
104
- Scene(
104
+ SceneView(
105
105
  engine = engine,
106
106
  onFrame = { _ ->
107
107
  springY.target = targetY
@@ -156,7 +156,7 @@ fun PropertyAnimationDemo() {
156
156
  label = "rotY"
157
157
  )
158
158
 
159
- Scene(engine = engine) {
159
+ SceneView(engine = engine) {
160
160
  modelInstance?.let { instance ->
161
161
  ModelNode(
162
162
  modelInstance = instance,
@@ -203,7 +203,7 @@ fun SmoothFollowDemo() {
203
203
  val smoothPosition = remember { SmoothTransform(smoothTime = 0.3f) }
204
204
  var targetPosition by remember { mutableStateOf(Position(0f, 1f, 0f)) }
205
205
 
206
- Scene(
206
+ SceneView(
207
207
  engine = engine,
208
208
  onFrame = { _ ->
209
209
  smoothPosition.target = targetPosition
@@ -231,7 +231,7 @@ fun ARAnimatedModel() {
231
231
  val modelInstance = rememberModelInstance(modelLoader, "models/dancing_character.glb")
232
232
  var anchor by remember { mutableStateOf<Anchor?>(null) }
233
233
 
234
- ARScene(
234
+ ARSceneView(
235
235
  engine = engine,
236
236
  modelLoader = modelLoader,
237
237
  planeRenderer = true,
@@ -282,7 +282,7 @@ fun EditableModelScreen() {
282
282
  val modelLoader = rememberModelLoader(engine)
283
283
  val modelInstance = rememberModelInstance(modelLoader, "models/chair.glb")
284
284
 
285
- Scene(engine = engine) {
285
+ SceneView(engine = engine) {
286
286
  modelInstance?.let { instance ->
287
287
  ModelNode(
288
288
  modelInstance = instance,
@@ -306,7 +306,7 @@ fun EditableModelScreen() {
306
306
 
307
307
  ## 2. Custom Gesture Handling with \`onTouchEvent\`
308
308
 
309
- For full control, use the \`onTouchEvent\` callback on \`Scene\` or \`ARScene\`.
309
+ For full control, use the \`onTouchEvent\` callback on \`SceneView\` or \`ARSceneView\`.
310
310
 
311
311
  \`\`\`kotlin
312
312
  @Composable
@@ -316,7 +316,7 @@ fun CustomGestureScreen() {
316
316
  val modelInstance = rememberModelInstance(modelLoader, "models/robot.glb")
317
317
  var selectedNode by remember { mutableStateOf<ModelNode?>(null) }
318
318
 
319
- Scene(
319
+ SceneView(
320
320
  engine = engine,
321
321
  onTouchEvent = { event, hitResult ->
322
322
  when (event.action) {
@@ -359,7 +359,7 @@ fun TapToPlaceAR() {
359
359
  val modelInstance = rememberModelInstance(modelLoader, "models/furniture.glb")
360
360
  var anchor by remember { mutableStateOf<Anchor?>(null) }
361
361
 
362
- ARScene(
362
+ ARSceneView(
363
363
  engine = engine,
364
364
  modelLoader = modelLoader,
365
365
  planeRenderer = true,
@@ -398,7 +398,7 @@ fun DragToRotateScreen() {
398
398
  var lastX by remember { mutableFloatStateOf(0f) }
399
399
  val sensitivity = 0.5f
400
400
 
401
- Scene(
401
+ SceneView(
402
402
  engine = engine,
403
403
  onTouchEvent = { event, _ ->
404
404
  when (event.action) {
@@ -443,7 +443,7 @@ fun PinchToScaleScreen() {
443
443
  currentScale = (currentScale * detector.scaleFactor).coerceIn(minScale, maxScale)
444
444
  }
445
445
 
446
- Scene(
446
+ SceneView(
447
447
  engine = engine,
448
448
  onTouchEvent = { event, _ ->
449
449
  scaleDetector.onTouchEvent(event)
@@ -471,7 +471,7 @@ fun MultiModelSelectionScreen() {
471
471
  val table = rememberModelInstance(modelLoader, "models/table.glb")
472
472
  var selectedModel by remember { mutableStateOf<String?>(null) }
473
473
 
474
- Scene(engine = engine) {
474
+ SceneView(engine = engine) {
475
475
  chair?.let { instance ->
476
476
  ModelNode(
477
477
  modelInstance = instance,
@@ -510,7 +510,7 @@ fun SurfaceCursorAR() {
510
510
  val modelLoader = rememberModelLoader(engine)
511
511
  val cursorModel = rememberModelInstance(modelLoader, "models/cursor_ring.glb")
512
512
 
513
- ARScene(
513
+ ARSceneView(
514
514
  engine = engine,
515
515
  modelLoader = modelLoader,
516
516
  planeRenderer = true
@@ -560,7 +560,7 @@ fun LODModelDemo() {
560
560
  // Filament picks the appropriate LOD automatically based on screen coverage
561
561
  val modelInstance = rememberModelInstance(modelLoader, "models/building_lod.glb")
562
562
 
563
- Scene(engine = engine) {
563
+ SceneView(engine = engine) {
564
564
  modelInstance?.let { instance ->
565
565
  ModelNode(
566
566
  modelInstance = instance,
@@ -619,8 +619,8 @@ fun MyApp() {
619
619
 
620
620
  // Pass engine and modelLoader to all scenes
621
621
  NavHost(...) {
622
- composable("scene1") { Scene1(engine, modelLoader) }
623
- composable("scene2") { Scene2(engine, modelLoader) }
622
+ composable("scene1") { SceneScreen1(engine, modelLoader) }
623
+ composable("scene2") { SceneScreen2(engine, modelLoader) }
624
624
  }
625
625
  }
626
626
 
@@ -628,7 +628,7 @@ fun MyApp() {
628
628
  @Composable
629
629
  fun BadScene() {
630
630
  val engine = rememberEngine() // creates new engine each time!
631
- Scene(engine = engine) { /* ... */ }
631
+ SceneView(engine = engine) { /* ... */ }
632
632
  }
633
633
  \`\`\`
634
634
 
@@ -636,7 +636,7 @@ fun BadScene() {
636
636
 
637
637
  \`\`\`kotlin
638
638
  // WRONG — creates new Position every frame
639
- Scene(
639
+ SceneView(
640
640
  engine = engine,
641
641
  onFrame = { _ ->
642
642
  node.position = Position(x, y, z) // allocation every frame!
@@ -645,7 +645,7 @@ Scene(
645
645
 
646
646
  // CORRECT — reuse mutable position
647
647
  val position = remember { MutablePosition() }
648
- Scene(
648
+ SceneView(
649
649
  engine = engine,
650
650
  onFrame = { _ ->
651
651
  position.set(x, y, z)
@@ -701,7 +701,7 @@ fun InstancedTreesScene() {
701
701
  val modelLoader = rememberModelLoader(engine)
702
702
  val treeInstance = rememberModelInstance(modelLoader, "models/tree.glb")
703
703
 
704
- Scene(engine = engine) {
704
+ SceneView(engine = engine) {
705
705
  // Each ModelNode with the same modelInstance shares GPU mesh data
706
706
  // Filament handles instancing internally when using the same asset
707
707
  treeInstance?.let { instance ->
@@ -748,7 +748,7 @@ val environment = rememberEnvironment(engine, "environments/sky_2k.hdr")
748
748
 
749
749
  \`\`\`kotlin
750
750
  // Disable post-processing for simpler scenes (saves ~2ms per frame)
751
- Scene(
751
+ SceneView(
752
752
  engine = engine,
753
753
  postProcessing = false // skips bloom, SSAO, tone mapping
754
754
  ) {
@@ -39,7 +39,6 @@ const DEBUG_GUIDES = {
39
39
  - Add a directional light:
40
40
  \`\`\`kotlin
41
41
  LightNode(
42
- engine = engine,
43
42
  type = LightManager.Type.DIRECTIONAL,
44
43
  apply = {
45
44
  intensity(100_000f)
@@ -60,7 +59,7 @@ const DEBUG_GUIDES = {
60
59
  - Try \`centerOrigin = Position(0f, 0f, 0f)\` on ModelNode.
61
60
  - Or move camera: \`cameraNode = rememberCameraNode(engine) { lookAt(Position(0f, 1f, 3f), Position(0f, 0f, 0f)) }\`
62
61
 
63
- 6. **Is the Scene composable actually visible?**
62
+ 6. **Is the SceneView composable actually visible?**
64
63
  - Check Modifier: \`Modifier.fillMaxSize()\` — not \`Modifier.size(0.dp)\` or hidden behind another composable.
65
64
 
66
65
  7. **Is the GLB file valid?**
@@ -79,14 +78,13 @@ fun DebugModelViewer() {
79
78
  val modelInstance = rememberModelInstance(modelLoader, "models/YOUR_FILE.glb")
80
79
  Log.d("SceneView", "Model loaded: \${modelInstance != null}")
81
80
 
82
- Scene(
81
+ SceneView(
83
82
  modifier = Modifier.fillMaxSize(),
84
83
  engine = engine,
85
84
  modelLoader = modelLoader
86
85
  ) {
87
86
  // Light is essential!
88
87
  LightNode(
89
- engine = engine,
90
88
  type = LightManager.Type.DIRECTIONAL,
91
89
  apply = { intensity(100_000f) }
92
90
  )
@@ -243,7 +241,7 @@ fun DebugModelViewer() {
243
241
 
244
242
  1. **Enable FPS overlay:**
245
243
  \`\`\`kotlin
246
- Scene(
244
+ SceneView(
247
245
  engine = engine,
248
246
  // Check frame time in onFrame callback
249
247
  onFrame = { frameTimeNanos ->
@@ -267,7 +265,7 @@ fun DebugModelViewer() {
267
265
  | Too many draw calls | Merge meshes in 3D editor (1 material = 1 draw call) |
268
266
  | Per-frame allocations | Reuse objects in \`onFrame\`, avoid creating Position/Rotation each frame |
269
267
  | Multiple engines | Use single \`rememberEngine()\`, never create multiple |
270
- | Post-processing enabled | Disable if not needed: \`Scene(postProcessing = false)\` |
268
+ | Post-processing enabled | Disable if not needed: \`SceneView(postProcessing = false)\` |
271
269
  | Shadow-casting lights | Each shadow light = extra depth pass. Limit to 1-2. |
272
270
 
273
271
  #### High Memory (>500MB)
@@ -294,7 +292,7 @@ fun DebugModelViewer() {
294
292
  title: "Build / Gradle Errors",
295
293
  guide: `## Debugging: Build Errors
296
294
 
297
- ### "Cannot resolve io.github.sceneview:sceneview:3.5.1"
295
+ ### "Cannot resolve io.github.sceneview:sceneview:3.6.0"
298
296
 
299
297
  1. Check repositories in \`settings.gradle.kts\`:
300
298
  \`\`\`kotlin
@@ -337,7 +335,7 @@ SceneView bundles Filament. If you also depend on Filament directly:
337
335
  \`\`\`kotlin
338
336
  // Remove direct Filament dependency — SceneView includes it
339
337
  // implementation("com.google.android.filament:filament-android:1.x.x") // REMOVE
340
- implementation("io.github.sceneview:sceneview:3.5.1") // This includes Filament
338
+ implementation("io.github.sceneview:sceneview:3.6.0") // This includes Filament
341
339
  \`\`\`
342
340
 
343
341
  ### "Cannot find Filament material"
@@ -363,7 +361,7 @@ rm -rf .gradle
363
361
 
364
362
  1. **Camera permission not granted** — most common cause.
365
363
  - Check logcat for permission denial.
366
- - Request permission before showing ARScene.
364
+ - Request permission before showing ARSceneView.
367
365
 
368
366
  2. **ARCore not initialized** — takes 1-2 seconds.
369
367
  - Show a loading overlay until first frame.
@@ -384,7 +382,7 @@ rm -rf .gradle
384
382
  - Check logcat for "Environment not found" messages.
385
383
  - Test without environment first.
386
384
 
387
- 4. **Scene composable has zero size** — \`Modifier.fillMaxSize()\` missing.
385
+ 4. **SceneView composable has zero size** — \`Modifier.fillMaxSize()\` missing.
388
386
 
389
387
  5. **OpenGL ES version** — Filament requires OpenGL ES 3.0+.
390
388
  - Check: \`GLES30.glGetString(GLES30.GL_VERSION)\`
@@ -393,16 +391,16 @@ rm -rf .gradle
393
391
  ### Diagnostic Code
394
392
 
395
393
  \`\`\`kotlin
396
- Scene(
394
+ SceneView(
397
395
  modifier = Modifier
398
396
  .fillMaxSize()
399
- .background(Color.Red), // Should see red if Scene has zero size
397
+ .background(Color.Red), // Should see red if SceneView has zero size
400
398
  engine = engine,
401
- onFrame = { Log.d("SV", "Frame rendered") } // If not logged, Scene isn't rendering
399
+ onFrame = { Log.d("SV", "Frame rendered") } // If not logged, SceneView isn't rendering
402
400
  ) {
403
401
  // Minimal visible content
404
402
  CubeNode(engine = engine, size = 1.0f)
405
- LightNode(engine = engine, type = LightManager.Type.DIRECTIONAL, apply = { intensity(100_000f) })
403
+ LightNode(type = LightManager.Type.DIRECTIONAL, apply = { intensity(100_000f) })
406
404
  }
407
405
  \`\`\``,
408
406
  },
@@ -425,15 +423,15 @@ Scene(
425
423
 
426
424
  ### Flat / No Shadows
427
425
 
428
- - Shadows disabled by default in \`Scene\` (enabled in \`ARScene\`).
429
- - Enable: \`Scene(view = rememberView(engine).also { it.setShadowingEnabled(true) })\`
426
+ - Shadows disabled by default in \`SceneView\` (enabled in \`ARSceneView\`).
427
+ - Enable: \`SceneView(view = rememberView(engine).also { it.setShadowingEnabled(true) })\`
430
428
  - Light must have \`castShadows(true)\` in its \`apply\` block.
431
429
 
432
430
  ### Environment / IBL Not Working
433
431
 
434
432
  \`\`\`kotlin
435
433
  val environmentLoader = rememberEnvironmentLoader(engine)
436
- Scene(
434
+ SceneView(
437
435
  environment = rememberEnvironment(environmentLoader) {
438
436
  environmentLoader.createHDREnvironment("environments/sky_2k.hdr")
439
437
  ?: createEnvironment(environmentLoader)
@@ -474,9 +472,9 @@ Scene(
474
472
 
475
473
  ### Camera Orbit Not Working
476
474
 
477
- - Default Scene has orbit camera. If overridden:
475
+ - Default SceneView has orbit camera. If overridden:
478
476
  \`\`\`kotlin
479
- Scene(
477
+ SceneView(
480
478
  cameraManipulator = rememberCameraManipulator() // Enables orbit
481
479
  )
482
480
  \`\`\`
@@ -604,7 +602,7 @@ Scene(
604
602
 
605
603
  2. **Animator not being updated** — animations require frame-by-frame updates.
606
604
  \`\`\`kotlin
607
- Scene(
605
+ SceneView(
608
606
  onFrame = { frameTimeNanos ->
609
607
  modelInstance?.animator?.let { animator ->
610
608
  if (animator.animationCount > 0) {
@@ -31,7 +31,7 @@ fun CustomMaterialScreen() {
31
31
  val modelLoader = rememberModelLoader(engine)
32
32
  val modelInstance = rememberModelInstance(modelLoader, "models/chair.glb")
33
33
 
34
- Scene(engine = engine) {
34
+ SceneView(engine = engine) {
35
35
  modelInstance?.let { instance ->
36
36
  ModelNode(
37
37
  modelInstance = instance,
@@ -62,7 +62,7 @@ fun TexturedModelScreen() {
62
62
  val materialLoader = rememberMaterialLoader(engine)
63
63
  val modelInstance = rememberModelInstance(modelLoader, "models/object.glb")
64
64
 
65
- Scene(engine = engine) {
65
+ SceneView(engine = engine) {
66
66
  modelInstance?.let { instance ->
67
67
  ModelNode(
68
68
  modelInstance = instance,
@@ -123,7 +123,7 @@ SceneView Android loads a default neutral IBL automatically. For custom environm
123
123
  val engine = rememberEngine()
124
124
  val environmentLoader = rememberEnvironmentLoader(engine)
125
125
 
126
- Scene(
126
+ SceneView(
127
127
  engine = engine,
128
128
  environment = environmentLoader.createHDREnvironment("environments/studio_2k.hdr")!!
129
129
  ) {
@@ -156,7 +156,7 @@ fun TappableModelScreen() {
156
156
  val modelInstance = rememberModelInstance(modelLoader, "models/button.glb")
157
157
  var tapped by remember { mutableStateOf(false) }
158
158
 
159
- Scene(engine = engine) {
159
+ SceneView(engine = engine) {
160
160
  modelInstance?.let { instance ->
161
161
  ModelNode(
162
162
  modelInstance = instance,
@@ -188,7 +188,7 @@ fun ARTapToPlaceScreen() {
188
188
  val modelLoader = rememberModelLoader(engine)
189
189
  val modelInstance = rememberModelInstance(modelLoader, "models/chair.glb")
190
190
 
191
- ARScene(
191
+ ARSceneView(
192
192
  engine = engine,
193
193
  sessionConfiguration = { session, config ->
194
194
  config.planeFindingMode = Config.PlaneFindingMode.HORIZONTAL_AND_VERTICAL
@@ -419,7 +419,7 @@ Browser → WebGL2 → Filament.js (WASM) → GPU
419
419
  ### Using sceneview.js (npm or local)
420
420
  \`\`\`html
421
421
  <!-- Option 1: npm CDN -->
422
- <script src="https://unpkg.com/sceneview.js@1.2.0"></script>
422
+ <script src="https://cdn.jsdelivr.net/npm/sceneview-web@3.6.0/sceneview.js"></script>
423
423
 
424
424
  <!-- Option 2: local hosting (recommended for production) -->
425
425
  <!-- Copy js/filament/ directory to your server for faster WASM loading -->
@@ -4,7 +4,7 @@
4
4
  * Generates a complete Scene{} or ARScene{} composable from a text description.
5
5
  * Maps common objects/concepts to SceneView node types and builds compilable code.
6
6
  *
7
- * All generated code targets SceneView v3.5.0 API and is verified against llms.txt.
7
+ * All generated code targets SceneView v3.6.0 API and is verified against llms.txt.
8
8
  */
9
9
  const OBJECT_MAPPINGS = [
10
10
  // Furniture
@@ -245,7 +245,7 @@ export function generateScene(description) {
245
245
  }
246
246
  // Build the code
247
247
  const isAR = parsed.isAR;
248
- dependencies.push(isAR ? "io.github.sceneview:arsceneview:3.5.1" : "io.github.sceneview:sceneview:3.5.1");
248
+ dependencies.push(isAR ? "io.github.sceneview:arsceneview:3.6.0" : "io.github.sceneview:sceneview:3.6.0");
249
249
  // Build model instance declarations
250
250
  const modelElements = elements.filter((e) => e.type === "model");
251
251
  const uniqueModels = new Map();
@@ -300,7 +300,7 @@ export function generateScene(description) {
300
300
  if (isAR) {
301
301
  lines.push(" var anchor by remember { mutableStateOf<Anchor?>(null) }");
302
302
  lines.push("");
303
- lines.push(" ARScene(");
303
+ lines.push(" ARSceneView(");
304
304
  lines.push(" modifier = Modifier.fillMaxSize(),");
305
305
  lines.push(" engine = engine,");
306
306
  if (hasModel)
@@ -320,7 +320,7 @@ export function generateScene(description) {
320
320
  lines.push(" AnchorNode(anchor = a) {");
321
321
  }
322
322
  else {
323
- lines.push(" Scene(");
323
+ lines.push(" SceneView(");
324
324
  lines.push(" modifier = Modifier.fillMaxSize(),");
325
325
  lines.push(" engine = engine,");
326
326
  if (hasModel)
@@ -483,7 +483,7 @@ export function formatGeneratedScene(result) {
483
483
  const parts = [];
484
484
  parts.push(`## Generated Scene\n`);
485
485
  parts.push(`**Description:** "${result.description}"`);
486
- parts.push(`**Mode:** ${result.isAR ? "AR (ARScene)" : "3D (Scene)"}`);
486
+ parts.push(`**Mode:** ${result.isAR ? "AR (ARSceneView)" : "3D (SceneView)"}`);
487
487
  parts.push(`**Elements:** ${result.elements.length} nodes\n`);
488
488
  parts.push(`### Dependency\n`);
489
489
  parts.push("```kotlin");
package/dist/guides.js CHANGED
@@ -6,16 +6,16 @@
6
6
  // ─── Platform Roadmap ─────────────────────────────────────────────────────────
7
7
  export const PLATFORM_ROADMAP = `# SceneView Multi-Platform Roadmap
8
8
 
9
- ## Current Status (v3.5.0)
9
+ ## Current Status (v3.6.0)
10
10
 
11
11
  | Platform | Status | Artifact | Renderer |
12
12
  |----------|--------|----------|----------|
13
- | **Android (Compose)** | Stable | \`io.github.sceneview:sceneview:3.5.1\` | Filament |
14
- | **Android (AR)** | Stable | \`io.github.sceneview:arsceneview:3.5.1\` | Filament + ARCore |
15
- | **iOS (SwiftUI)** | Alpha | SceneViewSwift SPM \`from: "3.5.0"\` | RealityKit + ARKit |
13
+ | **Android (Compose)** | Stable | \`io.github.sceneview:sceneview:3.6.0\` | Filament |
14
+ | **Android (AR)** | Stable | \`io.github.sceneview:arsceneview:3.6.0\` | Filament + ARCore |
15
+ | **iOS (SwiftUI)** | Alpha | SceneViewSwift SPM \`from: "3.6.0"\` | RealityKit + ARKit |
16
16
  | **macOS (SwiftUI)** | Alpha | SceneViewSwift SPM (in Package.swift) | RealityKit |
17
17
  | **visionOS (SwiftUI)** | Alpha | SceneViewSwift SPM (in Package.swift) | RealityKit |
18
- | **KMP Core** | Stable | \`io.github.sceneview:sceneview-core:3.5.0\` | N/A (shared logic) |
18
+ | **KMP Core** | Stable | \`io.github.sceneview:sceneview-core:3.6.0\` | N/A (shared logic) |
19
19
 
20
20
  ## Architecture: Native Renderers per Platform
21
21
 
@@ -31,7 +31,7 @@ KMP shares **logic**, not **rendering**. Each platform uses its native renderer.
31
31
 
32
32
  - **3D rendering** via Google Filament: PBR materials, HDR environments, glTF/GLB models, post-processing.
33
33
  - **AR** via ARCore: plane detection, hit testing, anchors, cloud anchors, augmented images, depth, light estimation, point cloud.
34
- - **Compose-native DSL**: all nodes are \`@Composable\` functions inside \`Scene { }\` or \`ARScene { }\`.
34
+ - **Compose-native DSL**: all nodes are \`@Composable\` functions inside \`SceneView { }\` or \`ARSceneView { }\`.
35
35
  - **26+ node types**: ModelNode, LightNode, AnchorNode, CameraNode, TextNode, PathNode, ViewNode, PlaneNode, SphereNode, CylinderNode, CubeNode, DynamicSkyNode, FogNode, ReflectionProbeNode, PhysicsNode, BillboardNode, LineNode, and more.
36
36
 
37
37
  ## Apple — Alpha (SceneViewSwift)
@@ -54,8 +54,7 @@ Shared Kotlin Multiplatform module providing:
54
54
 
55
55
  ## Upcoming
56
56
 
57
- - **v3.4.0**: SceneViewSwift stabilization, API parity with Android core nodes
58
- - **v3.5.0**: KMP core XCFramework consumption in SceneViewSwift
57
+ - **v3.6.0**: SceneViewSwift stabilization, API parity with Android core nodes, KMP core XCFramework consumption
59
58
  - **v4.0.0**: Android XR, visionOS spatial computing, cross-framework bridges (Flutter, React Native)
60
59
 
61
60
  ## How to Stay Updated
@@ -89,9 +88,9 @@ const PERFORMANCE_PRACTICES = `## Performance Best Practices
89
88
  const ARCHITECTURE_PRACTICES = `## Architecture Best Practices
90
89
 
91
90
  ### Compose Integration
92
- - **Treat Scene/ARScene like any Compose layout** — it participates in the Compose lifecycle. Don't fight it with imperative code.
93
- - **State hoisting** — hoist anchor state, model selection, and UI state to the parent composable. The Scene should be a pure renderer.
94
- - **ViewModel for business logic** — keep AR session state (anchors, detected images) in a ViewModel. Pass it down to the Scene composable.
91
+ - **Treat SceneView/ARSceneView like any Compose layout** — it participates in the Compose lifecycle. Don't fight it with imperative code.
92
+ - **State hoisting** — hoist anchor state, model selection, and UI state to the parent composable. The SceneView should be a pure renderer.
93
+ - **ViewModel for business logic** — keep AR session state (anchors, detected images) in a ViewModel. Pass it down to the SceneView composable.
95
94
  - **Side effects** — use \`LaunchedEffect\` and \`DisposableEffect\` for async operations, not raw coroutines in composables.
96
95
 
97
96
  ### Project Structure
@@ -105,10 +104,10 @@ app/
105
104
  kotlin/
106
105
  ui/
107
106
  scene/
108
- SceneScreen.kt # Compose screen with Scene { }
107
+ SceneScreen.kt # Compose screen with SceneView { }
109
108
  SceneViewModel.kt # State management
110
109
  ar/
111
- ARScreen.kt # Compose screen with ARScene { }
110
+ ARScreen.kt # Compose screen with ARSceneView { }
112
111
  ARViewModel.kt # Anchor and session state
113
112
  \`\`\`
114
113
 
@@ -264,7 +263,7 @@ export const TROUBLESHOOTING_GUIDE = `# SceneView Troubleshooting Guide
264
263
  - Reduce model polygon count (< 100K triangles)
265
264
  - Use KTX2 compressed textures (1024x1024 max)
266
265
  - Avoid per-frame allocations in \`onFrame\` callbacks
267
- - Disable post-processing if not needed: \`Scene(postProcessing = false)\`
266
+ - Disable post-processing if not needed: \`SceneView(postProcessing = false)\`
268
267
  - Profile with Android GPU Inspector
269
268
 
270
269
  ### High Memory Usage
@@ -339,7 +338,7 @@ export const AR_SETUP_GUIDE = `# SceneView AR — Complete Setup Guide (Android
339
338
  ## 1. SPM Dependency
340
339
 
341
340
  \`\`\`swift
342
- .package(url: "https://github.com/sceneview/sceneview", from: "3.5.0")
341
+ .package(url: "https://github.com/sceneview/sceneview", from: "3.6.0")
343
342
  \`\`\`
344
343
 
345
344
  ## 2. Info.plist — Camera Permission
@@ -424,7 +423,7 @@ ARSceneView(
424
423
  \`\`\`kotlin
425
424
  // build.gradle.kts (app module)
426
425
  dependencies {
427
- implementation("io.github.sceneview:arsceneview:3.5.1")
426
+ implementation("io.github.sceneview:arsceneview:3.6.0")
428
427
  // arsceneview includes sceneview transitively — no need to add both
429
428
  }
430
429
  \`\`\`
@@ -468,7 +467,7 @@ if (availability.isSupported) { /* show AR */ }
468
467
  ## 3. Session Configuration Options
469
468
 
470
469
  \`\`\`kotlin
471
- ARScene(
470
+ ARSceneView(
472
471
  engine = engine,
473
472
  modelLoader = modelLoader,
474
473
  sessionConfiguration = { session, config ->
@@ -520,7 +519,7 @@ ARScene(
520
519
  \`\`\`kotlin
521
520
  var anchor by remember { mutableStateOf<Anchor?>(null) }
522
521
 
523
- ARScene(
522
+ ARSceneView(
524
523
  engine = engine,
525
524
  modelLoader = modelLoader,
526
525
  planeRenderer = true,
@@ -547,7 +546,7 @@ ARScene(
547
546
 
548
547
  ### Surface Cursor (HitResultNode)
549
548
  \`\`\`kotlin
550
- ARScene(
549
+ ARSceneView(
551
550
  engine = engine,
552
551
  modelLoader = modelLoader,
553
552
  planeRenderer = true
@@ -564,7 +563,7 @@ ARScene(
564
563
  \`\`\`kotlin
565
564
  var images by remember { mutableStateOf<Map<String, AugmentedImage>>(emptyMap()) }
566
565
 
567
- ARScene(
566
+ ARSceneView(
568
567
  engine = engine,
569
568
  sessionConfiguration = { session, config ->
570
569
  config.addAugmentedImage(session, "poster", posterBitmap)
@@ -585,7 +584,7 @@ ARScene(
585
584
 
586
585
  ## 5. Permissions
587
586
 
588
- Camera permission must be requested at runtime (Android 6.0+). SceneView does **not** handle this — you must request it before showing ARScene:
587
+ Camera permission must be requested at runtime (Android 6.0+). SceneView does **not** handle this — you must request it before showing ARSceneView:
589
588
 
590
589
  \`\`\`kotlin
591
590
  val cameraPermission = rememberLauncherForActivityResult(
@@ -597,7 +596,7 @@ LaunchedEffect(Unit) {
597
596
  }
598
597
 
599
598
  if (showAR) {
600
- ARScene(engine = engine, modelLoader = modelLoader) { /* ... */ }
599
+ ARSceneView(engine = engine, modelLoader = modelLoader) { /* ... */ }
601
600
  }
602
601
  \`\`\`
603
602
  `;