Add PlayerObject.backEquipment property
This commit is contained in:
parent
61572b6824
commit
61aa9753af
|
@ -12,6 +12,7 @@ Three.js powered Minecraft skin viewer.
|
|||
* 1.8 Skins
|
||||
* HD Skins
|
||||
* Capes
|
||||
* Elytras
|
||||
* Slim Arms
|
||||
* Automatic model detection (Slim / Default)
|
||||
|
||||
|
@ -37,7 +38,10 @@ Three.js powered Minecraft skin viewer.
|
|||
// Load a cape
|
||||
skinViewer.loadCape("img/cape.png");
|
||||
|
||||
// Unload(hide) the cape
|
||||
// Load a elytra (from a cape texture)
|
||||
skinViewer.loadCape("img/cape.png", { backEquipment: "elytra" });
|
||||
|
||||
// Unload(hide) the cape / elytra
|
||||
skinViewer.loadCape(null);
|
||||
|
||||
// Control objects with your mouse!
|
||||
|
|
|
@ -182,6 +182,13 @@
|
|||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div>
|
||||
<h2>Back Equipment</h2>
|
||||
<div class="control">
|
||||
<label><input type="radio" id="back_equipment_cape" name="back_equipment" value="cape" checked> Cape</label>
|
||||
<label><input type="radio" id="back_equipment_elytra" name="back_equipment" value="elytra"> Elytra</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-section">
|
||||
|
@ -284,7 +291,8 @@
|
|||
skinViewer.loadCape(null);
|
||||
input.setCustomValidity("");
|
||||
} else {
|
||||
skinViewer.loadCape(url)
|
||||
const selectedBackEquipment = document.querySelector('input[type="radio"][name="back_equipment"]:checked');
|
||||
skinViewer.loadCape(url, { backEquipment: selectedBackEquipment.value })
|
||||
.then(() => input.setCustomValidity(""))
|
||||
.catch(e => {
|
||||
input.setCustomValidity("Image can't be loaded.");
|
||||
|
@ -363,6 +371,18 @@
|
|||
document.getElementById("skin_url").addEventListener("change", () => reloadSkin());
|
||||
document.getElementById("skin_model").addEventListener("change", () => reloadSkin());
|
||||
document.getElementById("cape_url").addEventListener("change", () => reloadCape());
|
||||
|
||||
for (const el of document.querySelectorAll('input[type="radio"][name="back_equipment"]')) {
|
||||
el.addEventListener("change", e => {
|
||||
if (skinViewer.playerObject.backEquipment === null) {
|
||||
// cape texture hasn't been loaded yet
|
||||
// this option will be processed on texture loading
|
||||
} else {
|
||||
skinViewer.playerObject.backEquipment = e.target.value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.getElementById("reset_all").addEventListener("click", () => {
|
||||
skinViewer.dispose();
|
||||
orbitControl.dispose();
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<div id="rendered_imgs"></div>
|
||||
<script src="../bundles/skinview3d.bundle.js"></script>
|
||||
<script>
|
||||
const textures = [
|
||||
const configurations = [
|
||||
{
|
||||
skin: "img/1_8_texturemap_redux.png",
|
||||
cape: null
|
||||
|
@ -23,11 +23,12 @@
|
|||
},
|
||||
{
|
||||
skin: "img/haka.png",
|
||||
cape: null
|
||||
cape: "img/mojang_cape.png"
|
||||
},
|
||||
{
|
||||
skin: "img/hatsune_miku.png",
|
||||
cape: "img/mojang_cape.png"
|
||||
cape: "img/mojang_cape.png",
|
||||
backEquipment: "elytra"
|
||||
},
|
||||
{
|
||||
skin: "img/ironman_hd.png",
|
||||
|
@ -54,8 +55,11 @@
|
|||
skinViewer.camera.position.y = 22.0;
|
||||
skinViewer.camera.position.z = 42.0;
|
||||
|
||||
for (const { skin, cape } of textures) {
|
||||
await Promise.all([skinViewer.loadSkin(skin), skinViewer.loadCape(cape)]);
|
||||
for (const config of configurations) {
|
||||
await Promise.all([
|
||||
skinViewer.loadSkin(config.skin),
|
||||
skinViewer.loadCape(config.cape, { backEquipment: config.backEquipment })
|
||||
]);
|
||||
skinViewer.render();
|
||||
const image = skinViewer.canvas.toDataURL();
|
||||
|
||||
|
|
17
src/model.ts
17
src/model.ts
|
@ -343,6 +343,8 @@ export class ElytraObject extends Group {
|
|||
}
|
||||
}
|
||||
|
||||
export type BackEquipment = "cape" | "elytra";
|
||||
|
||||
export class PlayerObject extends Group {
|
||||
|
||||
readonly skin: SkinObject;
|
||||
|
@ -369,4 +371,19 @@ export class PlayerObject extends Group {
|
|||
this.elytra.visible = false;
|
||||
this.add(this.elytra);
|
||||
}
|
||||
|
||||
get backEquipment(): BackEquipment | null {
|
||||
if (this.cape.visible) {
|
||||
return "cape";
|
||||
} else if (this.elytra.visible) {
|
||||
return "elytra";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
set backEquipment(value: BackEquipment | null) {
|
||||
this.cape.visible = value === "cape";
|
||||
this.elytra.visible = value === "elytra";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { applyMixins, CapeContainer, ModelType, SkinContainer, RemoteImage, TextureSource } from "skinview-utils";
|
||||
import { NearestFilter, PerspectiveCamera, Scene, Texture, Vector2, WebGLRenderer } from "three";
|
||||
import { RootAnimation } from "./animation.js";
|
||||
import { PlayerObject } from "./model.js";
|
||||
import { BackEquipment, PlayerObject } from "./model.js";
|
||||
|
||||
export interface LoadOptions {
|
||||
/**
|
||||
|
@ -10,6 +10,14 @@ export interface LoadOptions {
|
|||
makeVisible?: boolean;
|
||||
}
|
||||
|
||||
export interface CapeLoadOptions extends LoadOptions {
|
||||
/**
|
||||
* The equipment (cape or elytra) to show, defaults to "cape".
|
||||
* If makeVisible is set to false, this option will have no effect.
|
||||
*/
|
||||
backEquipment?: BackEquipment;
|
||||
}
|
||||
|
||||
export interface SkinViewerOptions {
|
||||
width?: number;
|
||||
height?: number;
|
||||
|
@ -40,13 +48,6 @@ export interface SkinViewerOptions {
|
|||
renderPaused?: boolean;
|
||||
}
|
||||
|
||||
function toMakeVisible(options?: LoadOptions): boolean {
|
||||
if (options && options.makeVisible === false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
class SkinViewer {
|
||||
readonly canvas: HTMLCanvasElement;
|
||||
readonly scene: Scene;
|
||||
|
@ -118,18 +119,18 @@ class SkinViewer {
|
|||
}
|
||||
}
|
||||
|
||||
protected skinLoaded(model: ModelType, options?: LoadOptions): void {
|
||||
protected skinLoaded(model: ModelType, options: LoadOptions = {}): void {
|
||||
this.skinTexture.needsUpdate = true;
|
||||
this.playerObject.skin.modelType = model;
|
||||
if (toMakeVisible(options)) {
|
||||
if (options.makeVisible !== false) {
|
||||
this.playerObject.skin.visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected capeLoaded(options?: LoadOptions): void {
|
||||
protected capeLoaded(options: CapeLoadOptions = {}): void {
|
||||
this.capeTexture.needsUpdate = true;
|
||||
if (toMakeVisible(options)) {
|
||||
this.playerObject.cape.visible = true;
|
||||
if (options.makeVisible !== false) {
|
||||
this.playerObject.backEquipment = options.backEquipment === undefined ? "cape" : options.backEquipment;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,7 +139,7 @@ class SkinViewer {
|
|||
}
|
||||
|
||||
protected resetCape(): void {
|
||||
this.playerObject.cape.visible = false;
|
||||
this.playerObject.backEquipment = null;
|
||||
}
|
||||
|
||||
private draw(): void {
|
||||
|
@ -208,6 +209,6 @@ class SkinViewer {
|
|||
this.setSize(this.width, newHeight);
|
||||
}
|
||||
}
|
||||
interface SkinViewer extends SkinContainer<LoadOptions>, CapeContainer<LoadOptions> { }
|
||||
interface SkinViewer extends SkinContainer<LoadOptions>, CapeContainer<CapeLoadOptions> { }
|
||||
applyMixins(SkinViewer, [SkinContainer, CapeContainer]);
|
||||
export { SkinViewer };
|
||||
|
|
Loading…
Reference in New Issue