-
Notifications
You must be signed in to change notification settings - Fork 0
Getting Started
Install from npm:
npm install skinview3d-etfskinview3d
(GitHub | npm)
and three
(GitHub | npm)
are peer dependencies; install the versions your viewer already
uses.
The extension attaches to a live skinview3d viewer through
attachETFSkinFeatures():
import { SkinViewer } from "skinview3d";
import { attachETFSkinFeatures } from "skinview3d-etf";
const viewer = new SkinViewer({ canvas, width: 400, height: 400 });
await viewer.loadSkin(skinUrl);
const controller = attachETFSkinFeatures(viewer, {
features: { transparency: true, emissive: true, nose: true },
blink: { periodMs: [4000, 10000], closedMs: 200 },
onWarning: (message) => console.warn(message),
});Every feature defaults to enabled; Options documents
the option groups (features, blink, enchanted, villagerNose) and
the exported defaults. The controller never rebuilds the scene graph and
never seizes the viewer's animation slot: it adds artifacts under
the existing meshes and cleans all of them up on detach().
Skin changes are never detected automatically: call
controller.refresh() after every viewer.loadSkin() call. The
host recreates the skin textures and resets its canvas, so the
controller re-decodes the current skin and re-applies everything.
Call controller.rebind() after the player object is replaced or
the model is re-parented (another extension may move parts into its
own groups), and after you replace viewer.animation yourself - a
replaced slot object disconnects the ticker hook.
Blinking (in the "auto" state) and the scrolling enchanted
pattern need a clock. By default the controller manages one: it hooks the viewer's
animation slot through addAnimation() while an animation is
assigned, and installs a private FunctionAnimation while the slot
is empty. Assigning viewer.animation resets the player's pose once
(the host does that on every slot change) and drops a private
ticker - call controller.rebind() afterwards.
For custom render loops, pass manageTicker: false and call
controller.update(dt) yourself with the elapsed seconds; negative
and non-finite deltas are ignored.
controller.detach() restores everything the extension touched -
canvas pixels, material swaps, textures, overlays and ticker hooks -
and is idempotent. Call attachETFSkinFeatures() again to
re-attach; a fresh controller starts from the documented defaults.
decodeSkin() is a standalone, three-free module that operates on
plain pixel buffers (ImageData-compatible; 64x64, plus legacy
64x32 skins, which are converted to the 1.8 layout first):
import { decodeSkin } from "skinview3d-etf";
const result = decodeSkin(imageData);
// result.skin, result.emissive?.mask, result.blink?.frames, ...The decoder is also published as the standalone etf-skin-decoder
(GitHub | npm)
package; skinview3d-etf depends on it and
re-exports its API for the rest of the v0.0.x line. New code should
import it from etf-skin-decoder directly.
Interop: any canvas works through getImageData() - including one
painted by the host's utility layer skinview-utils
(GitHub | npm):
import { loadSkinToCanvas } from "skinview-utils";
const canvas = document.createElement("canvas");
loadSkinToCanvas(canvas, image); // converts legacy skins too
const context = canvas.getContext("2d");
const result = decodeSkin(
context.getImageData(0, 0, canvas.width, canvas.height),
);The live viewer takes the same route: SkinViewer.loadSkin() paints
its skin canvas through loadSkinToCanvas() before the extension
reads it, so a skin with zero transparent pixels first loses the
regions the host's opaque-background fix clears (see
FAQ §7).
Any other size decodes as supported: false with a warning and no
features; a malformed buffer throws a TypeError. A skin without
the ETF marker decodes as hasMarker: false - use the demo's
preview tab to inspect what a skin actually carries.
The repository ships a Vite demo (pnpm dev in a checkout) with
several sample skins, a PNG upload, live control tables for every
option and a decoder preview tab. A live build is deployed at
https://stevehsudrawing.github.io/skinview3d-etf/; the demo is not
part of the npm package.