One extension. Three viewers. Built for Three.js / React / JS game & web devs.
Preview sprite sheets, Spine animations and GLTF/GLB models without leaving VS Code — then hit Copy as Component and paste working React code into your project.
| 🎞️ Sprite Sheet Player | Grid slicing, TexturePacker & Aseprite atlases, onion skinning, per-frame durations |
| 🦴 Spine 2D Player | .json/.skel + .atlas + texture, animation & skin dropdowns, mix slider, bone debug |
| 🧊 GLTF / GLB Viewer | Orbit + auto-frame, animation clip picker with scrub timeline, wireframe/normals/UV-checker modes, triangle & texture-memory overlay |
Add demo GIFs here before publishing. Marketplace listings without them get far fewer installs — record 5–10s clips of each viewer (Windows Game Bar, ScreenToGif, or the VS Code screen recorder) and drop them at the top of this file.
Why this instead of a plain previewer
- Copy as Component on every viewer — emits code that uses the actual filenames and clip names of the asset you are looking at. No other asset previewer does this.
- Auto-detection by content, not extension — a
.jsonwithskeleton+bonesopens the Spine player; a.jsonwithframes+metaopens the sprite player; a.jsonwith a matching.atlasnext to it is treated as Spine. - Hot reload — re-export from Aseprite, Blender or Spine and the open preview updates.
- One shared UI shell — the same toolbar and timeline across all three viewers, themed with VS Code's own CSS variables, so light/dark/high-contrast all work.
- Perf overlay on the 3D viewer — triangles, vertices, meshes, materials, textures and an estimated texture-memory figure, so you catch bloated assets before they hit your runtime.
- Onion skinning on the sprite player — ghost of the previous frame at low opacity.
Usage
| How | What happens |
|---|---|
Double-click a .gltf / .glb |
Opens in the Asset Studio 3D viewer (custom editor, priority: option — use Reopen Editor With… if another editor claims it) |
| Right-click any asset → Asset Studio: Open Asset (Auto-Detect) | Picks the right viewer from the file's contents |
| Command Palette → Asset Studio: Open … | Opens a specific viewer for the active file |
File pairs are resolved for you. Click player.png and a matching player.json atlas is
picked up automatically (and vice versa via meta.image). Click a Spine .json/.skel and the
sibling .atlas plus its texture page are resolved from the atlas header.
Copy as Component
- Sprite sheet → plain React using
background-positionstepping (uniform grids) or an explicit frame table (trimmed/packed atlases), or a@pixi/reactAnimatedSprite. - GLTF →
@react-three/fiber+dreiwithuseGLTF/useAnimationsand the detected clip pre-wired. If@react-three/fiberis not in your workspacepackage.json, you get plainthree.jsboilerplate instead. Override withassetStudio.codegen.reactThreeFiber.
The generated code is copied to your clipboard and opened in a new editor tab.
Settings
| Setting | Default | What it does |
|---|---|---|
assetStudio.sprite.defaultFps |
12 |
Playback FPS when the atlas has no per-frame durations |
assetStudio.sprite.assetBasePath |
/assets |
Public base path used in generated code (url(/assets/player-run.png)) |
assetStudio.codegen.reactThreeFiber |
auto |
auto | always | never — which flavour of 3D code to emit |
assetStudio.gltf.showGrid |
true |
Ground grid visible on load |
assetStudio.gltf.autoRotate |
false |
Auto-rotate the camera on load |
assetStudio.hotReload |
true |
Reload the preview when the asset changes on disk |
Building from source
npm run install:all # installs the extension host + webview-ui dependencies
npm run build # esbuild bundle + Vite webview build
npm run package # produces asset-studio-0.1.0.vsix
code --install-extension asset-studio-0.1.0.vsix
Other scripts: npm run watch (extension host), npm run typecheck, npm run icon
(regenerates media/icon.png), npm run samples (regenerates samples/).
Test assets
npm run samples writes into samples/:
bouncer.png+bouncer.json— an 8-frame Aseprite-format sprite sheet with abounceframe tag and 90 ms per-frame durationscube.gltfandcube.glb— the same animated cube with two clips (Spin,Hop), one with an embedded data-URI buffer, one as a binary.glb
Spine test data is not generated: Spine exports require the Spine Editor, so bring your own (see the licensing note below).
⚠️ Spine licensing
The Spine runtimes bundled here (@esotericsoftware/spine-player, which wraps
spine-webgl) are free to use under the
Spine Runtimes License. Exported Spine
data — the .json / .skel / .atlas files — requires the developer using them to own a
valid Spine Editor license for commercial use.
This extension only plays files you already have. It is not a free alternative to the Spine Editor and does not bundle any Spine editing capability.
Known limitations (v0.1)
- Draco-compressed models decode with the decoder bundled in the extension (no network needed); KTX2/Basis and Meshopt compression are not wired up yet.
- Spine assets are loaded without cache-busting because the Spine player infers JSON vs binary from the URL's extension. If a Spine hot reload ever shows stale data, close and reopen the panel.
- The GLTF custom editor is registered with
priority: option, so VS Code will not steal.gltf/.glbfrom another extension you already have installed — use Reopen Editor With… once and VS Code remembers the choice. - Very large models load inside the webview (not the extension host), so the editor stays
responsive, but a multi-hundred-MB
.glbwill still take a while to parse.
Roadmap
v0.2 is the "wow layer" from the spec: QR-code phone AR preview, live sync into a running dev server, a one-click sprite-sheet packer, CodeSandbox export, an actionable performance advisor, a PBR channel inspector, and an optional (BYO-key) Claude assist panel.
License
MIT — see LICENSE. Spine runtimes are licensed separately, as described above.