UNPKG

skin3d

Version:

A fast, customizable Minecraft skin viewer powered by Three.js. Easily render and preview Minecraft skins in 3D for your projects.

361 lines (360 loc) 12.9 kB
import { type ModelType, type RemoteImage, type TextureSource } from "skinview-utils"; import { Color, type ColorRepresentation, PointLight, Group, PerspectiveCamera, Scene, Texture, WebGLRenderer, AmbientLight, type Mapping } from "three"; import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"; import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js"; import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js"; import { ShaderPass } from "three/examples/jsm/postprocessing/ShaderPass.js"; import { PlayerAnimation } from "./animation.js"; import { type BackEquipment, PlayerObject } from "./model.js"; import { NameTagObject } from "./nametag.js"; export interface LoadOptions { /** * Whether to make the object visible after the texture is loaded. * * @defaultValue `true` */ makeVisible?: boolean; } export interface SkinLoadOptions extends LoadOptions { /** * The model of the player (`"default"` for normal arms, and `"slim"` for slim arms). * * When set to `"auto-detect"`, the model will be inferred from the skin texture. * * @defaultValue `"auto-detect"` */ model?: ModelType | "auto-detect"; /** * Whether to display the ears drawn on the skin texture. * * - `true` - Display the ears drawn on the skin texture. * - `"load-only"` - Loads the ear texture, but do not make them visible. * You can make them visible later by setting `PlayerObject.ears.visible` to `true`. * - `false` - Do not load or show the ears. * * @defaultValue `false` */ ears?: boolean | "load-only"; } export interface CapeLoadOptions extends LoadOptions { /** * The equipment (`"cape"` or `"elytra"`) to show when the cape texture is loaded. * * If `makeVisible` is set to false, this option will have no effect. * * @defaultValue `"cape"` */ backEquipment?: BackEquipment; } export interface EarsLoadOptions extends LoadOptions { /** * The type of the provided ear texture. * * - `"standalone"` means the provided texture is a 14x7 image that only contains the ears. * - `"skin"` means the provided texture is a skin texture with ears, and we will use its ear part. * * @defaultValue `"standalone"` */ textureType?: "standalone" | "skin"; } export interface ViewOptions { /** * The canvas where the renderer draws its output. * * @defaultValue If unspecified, a new canvas element will be created. */ canvas?: HTMLCanvasElement; /** * The CSS width of the canvas. */ width?: number; /** * The CSS height of the canvas. */ height?: number; /** * The pixel ratio of the canvas. * * When set to `"match-device"`, the current device pixel ratio will be used, * and it will be automatically updated when the device pixel ratio changes. * * @defaultValue `"match-device"` */ pixelRatio?: number | "match-device"; /** * The skin texture of the player. * * @defaultValue If unspecified, the skin will be invisible. */ skin?: RemoteImage | TextureSource; /** * The model of the player (`"default"` for normal arms, and `"slim"` for slim arms). * * When set to `"auto-detect"`, the model will be inferred from the skin texture. * * If the `skin` option is not specified, this option will have no effect. * * @defaultValue `"auto-detect"` */ model?: ModelType | "auto-detect"; /** * The cape texture of the player. * * @defaultValue If unspecified, the cape will be invisible. */ cape?: RemoteImage | TextureSource; /** * The ear texture of the player. * * When set to `"current-skin"`, the ears drawn on the current skin texture (as is specified in the `skin` option) will be shown. * * To use an individual ear texture, you have to specify the `textureType` and the `source` option. * `source` is the texture to use, and `textureType` can be either `"standalone"` or `"skin"`: * - `"standalone"` means the provided texture is a 14x7 image that only contains the ears. * - `"skin"` means the provided texture is a skin texture with ears, and we will show its ear part. * * @defaultValue If unspecified, the ears will be invisible. */ ears?: "current-skin" | { textureType: "standalone" | "skin"; source: RemoteImage | TextureSource; }; /** * Whether to preserve the buffers until manually cleared or overwritten. * * @defaultValue `false` */ preserveDrawingBuffer?: boolean; /** * Whether to pause the rendering and animation loop. * * @defaultValue `false` */ renderPaused?: boolean; /** * The background of the scene. * * @defaultValue transparent */ background?: ColorRepresentation | Texture; /** * The panorama background to use. * * This option overrides the `background` option. */ panorama?: RemoteImage | TextureSource; /** * Camera vertical field of view, in degrees. * * The distance between the player and the camera will be automatically computed from `fov` and `zoom`. * * @defaultValue `50` * * @see {@link View.adjustCameraDistance} */ fov?: number; /** * Zoom ratio of the player. * * This value affects the distance between the object and the camera. * When set to `1.0`, the top edge of the player's head coincides with the edge of the canvas. * * The distance between the player and the camera will be automatically computed from `fov` and `zoom`. * * @defaultValue `0.9` * * @see {@link View.adjustCameraDistance} */ zoom?: number; /** * Whether to enable mouse control function. * * This function is implemented using {@link OrbitControls}. * By default, zooming and rotating are enabled, and panning is disabled. * * @defaultValue `true` */ enableControls?: boolean; /** * The animation to play on the player. * * @defaultValue If unspecified, no animation will be played. */ animation?: PlayerAnimation; /** * The name tag to display above the player. * * @defaultValue If unspecified, no name tag will be displayed. * @see {@link View.nameTag} */ nameTag?: NameTagObject | string; /** * Allow rotation around the X and Y axis (Vertical and Horizontal). * @defaultValue true */ enableRotation?: boolean; /** * Allow rotation around the X axis (vertical). * @defaultValue true */ allowRotateX?: boolean; /** * Allow rotation around the Y axis (horizontal). * @defaultValue true */ allowRotateY?: boolean; /** * Allow zooming. * @defaultValue true */ allowZoom?: boolean; } /** * The View renders the player on a canvas. */ export declare class View { /** The canvas where the renderer draws its output. */ readonly canvas: HTMLCanvasElement; readonly scene: Scene; readonly camera: PerspectiveCamera; readonly renderer: WebGLRenderer; /** Mouse control component (OrbitControls). */ readonly controls: OrbitControls; /** The player object (skin, cape, elytra, ears). */ readonly playerObject: PlayerObject; /** Group that wraps the player object for centering. */ readonly playerWrapper: Group; readonly globalLight: AmbientLight; readonly cameraLight: PointLight; readonly composer: EffectComposer; readonly renderPass: RenderPass; readonly fxaaPass: ShaderPass; readonly skinCanvas: HTMLCanvasElement; readonly capeCanvas: HTMLCanvasElement; readonly earsCanvas: HTMLCanvasElement; private skinTexture; private capeTexture; private earsTexture; private backgroundTexture; private _disposed; private _renderPaused; private _zoom; private isUserRotating; /** * Whether to rotate the player along the y axis. * * @defaultValue `false` */ autoRotate: boolean; /** * The angular velocity of the player, in rad/s. * * @defaultValue `1.0` * @see {@link autoRotate} */ autoRotateSpeed: number; private _animation; private clock; private animationID; private onContextLost; private onContextRestored; private _pixelRatio; private devicePixelRatioQuery; private onDevicePixelRatioChange; private _nameTag; constructor(options?: ViewOptions); /** Update the size and pixel ratio of the composer and FXAA pass. */ private updateComposerSize; /** Create or update the skin texture from the skin canvas. */ private recreateSkinTexture; /** Create or update the cape texture from the cape canvas. */ private recreateCapeTexture; /** Create or update the ears texture from the ears canvas. */ private recreateEarsTexture; /** * Load a skin texture. * @param source * - The skin image or canvas. * @param options - Loading options. */ loadSkin(empty: null): void; loadSkin<S extends TextureSource | RemoteImage>(source: S, options?: SkinLoadOptions): S extends TextureSource ? void : Promise<void>; /** Hide and dispose the current skin texture. */ resetSkin(): void; /** * Load a cape texture. * @param source - The cape image or canvas. * @param options - Loading options. */ loadCape(empty: null): void; loadCape<S extends TextureSource | RemoteImage>(source: S, options?: CapeLoadOptions): S extends TextureSource ? void : Promise<void>; /** Hide and dispose the current cape texture. */ resetCape(): void; /** * Load an ear texture. * @param source - The ear image or canvas. * @param options - Loading options. */ loadEars(empty: null): void; loadEars<S extends TextureSource | RemoteImage>(source: S, options?: EarsLoadOptions): S extends TextureSource ? void : Promise<void>; /** Hide and dispose the current ears texture. */ resetEars(): void; /** Load a panorama background. */ loadPanorama<S extends TextureSource | RemoteImage>(source: S): S extends TextureSource ? void : Promise<void>; /** * Load a background texture. * @param source - The background image or canvas. * @param mapping - Optional texture mapping. */ loadBackground<S extends TextureSource | RemoteImage>(source: S, mapping?: Mapping): S extends TextureSource ? void : Promise<void>; /** Animation and rendering loop. */ private draw; /** Render the scene to the canvas (does not advance animation). */ render(): void; /** Set the viewer size in pixels. */ setSize(width: number, height: number): void; /** Dispose all resources and event listeners. */ dispose(): void; get disposed(): boolean; /** Whether rendering and animations are paused. */ get renderPaused(): boolean; set renderPaused(value: boolean); get width(): number; set width(newWidth: number); get height(): number; set height(newHeight: number); get background(): null | Color | Texture; set background(value: null | ColorRepresentation | Texture); /** Adjust camera distance based on FOV and zoom. */ adjustCameraDistance(): void; /** Reset camera to default pose and distance. */ resetCameraPose(): void; get fov(): number; set fov(value: number); get zoom(): number; set zoom(value: number); get pixelRatio(): number | "match-device"; set pixelRatio(newValue: number | "match-device"); /** * The animation that is currently playing, or `null` if no animation is playing. * Setting this property to a different value will change the current animation. * The player's pose and the progress of the new animation will be reset before playing. * Setting this property to `null` will stop the current animation and reset the player's pose. */ get animation(): PlayerAnimation | null; set animation(animation: PlayerAnimation | null); /** * The name tag to display above the player, or `null` if there is none. * When setting this property to a `string` value, a {@link NameTagObject} * will be automatically created with default options. * * @example * view.nameTag = "Norch"; * view.nameTag = new NameTagObject("hello", { textStyle: "yellow" }); * view.nameTag = null; */ get nameTag(): NameTagObject | null; set nameTag(newVal: NameTagObject | string | null); /** Reset the model's rotation to default. */ resetModelRotation(): void; }