Merge remote-tracking branch 'upstream/master'
|
@ -1,6 +1,6 @@
|
||||||
name: CI
|
name: CI
|
||||||
|
|
||||||
on: [push]
|
on: [push, pull_request]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
|
@ -9,8 +9,6 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: npm build & test
|
- run: npm install
|
||||||
run: |
|
- run: npm run build
|
||||||
npm install
|
- run: npm test
|
||||||
npm run build
|
|
||||||
npm test
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
name: Deploy to GitHub Pages
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: npm install
|
||||||
|
- run: npm run build
|
||||||
|
- run: npm test
|
||||||
|
- name: Prepare files
|
||||||
|
run: |
|
||||||
|
cp -r examples public
|
||||||
|
cp -r bundles public/js
|
||||||
|
build_commit="${{ github.sha }}"
|
||||||
|
build_time=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||||
|
sed -Ez \
|
||||||
|
-e 's#\.\./bundles/skinview3d\.bundle\.js#js/skinview3d.bundle.js#g' \
|
||||||
|
-e 's#\{\{build_commit\}\}#'$build_commit'#g' \
|
||||||
|
-e 's#\{\{build_time\}\}#'$build_time'#g' \
|
||||||
|
-e 's#<!--%%deploy_only%%(.*)-->#\1#g' \
|
||||||
|
-i public/*.html
|
||||||
|
- uses: crazy-max/ghaction-github-pages@v2
|
||||||
|
with:
|
||||||
|
target_branch: gh-pages
|
||||||
|
build_dir: public
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@ -62,3 +62,4 @@ libs/
|
||||||
_ignore/
|
_ignore/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.rpt2_cache
|
.rpt2_cache
|
||||||
|
public/
|
||||||
|
|
24
README.md
|
@ -16,11 +16,12 @@ Three.js powered Minecraft skin viewer.
|
||||||
* Automatic model detection (Slim / Default)
|
* Automatic model detection (Slim / Default)
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
[Examples of using the viewer](https://bs-community.github.io/skinview3d/)
|
[Example of using skinview3d](https://bs-community.github.io/skinview3d/)
|
||||||
```html
|
```html
|
||||||
<div id="skin_container"></div>
|
<canvas id="skin_container"></canvas>
|
||||||
<script>
|
<script>
|
||||||
let skinViewer = new skinview3d.SkinViewer(document.getElementById("skin_container"), {
|
let skinViewer = new skinview3d.SkinViewer({
|
||||||
|
canvas: document.getElementById("skin_container"),
|
||||||
width: 300,
|
width: 300,
|
||||||
height: 400,
|
height: 400,
|
||||||
skin: "img/skin.png"
|
skin: "img/skin.png"
|
||||||
|
@ -65,5 +66,22 @@ Three.js powered Minecraft skin viewer.
|
||||||
</script>
|
</script>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Anti-aliasing
|
||||||
|
skinview3d supports FXAA (fast approximate anti-aliasing).
|
||||||
|
To enable it, you need to replace `SkinViewer` with `FXAASkinViewer`.
|
||||||
|
|
||||||
|
It's recommended to use an opaque background when FXAA is enabled,
|
||||||
|
as transparent background may look buggy.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
let skinViewer = new skinview3d.FXAASkinViewer({
|
||||||
|
// we do not use transparent background, so disable alpha to improve performance
|
||||||
|
alpha: false,
|
||||||
|
...
|
||||||
|
});
|
||||||
|
// set the background color
|
||||||
|
skinViewer.renderer.setClearColor(0x5a76f3);
|
||||||
|
```
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
`npm run build`
|
`npm run build`
|
||||||
|
|
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 689 B |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 278 KiB |
After Width: | Height: | Size: 109 KiB |
After Width: | Height: | Size: 589 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.4 KiB |
|
@ -3,73 +3,439 @@
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
||||||
<title>skinview3d</title>
|
<title>skinview3d</title>
|
||||||
<link href="https://fonts.googleapis.com/css?family=Archivo+Black" rel="stylesheet">
|
|
||||||
<style>
|
<style>
|
||||||
html,
|
|
||||||
body {
|
body {
|
||||||
|
font-family: "Helvetica Neue", "Helvetica", "Arial", "sans-serif";
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="number"] {
|
||||||
|
max-width: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"] {
|
||||||
|
box-sizing: border-box;
|
||||||
|
max-width: 250px;
|
||||||
|
width: calc(100% - 100px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.control {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control + .control {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-section {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-section>h1,
|
||||||
|
.control-section>h2 {
|
||||||
|
margin-left: -10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
table td,
|
||||||
|
table th {
|
||||||
|
border: 1px black dashed;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
thead th {
|
||||||
|
border-top: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody tr:last-child td,
|
||||||
|
tbody tr:last-child th {
|
||||||
|
border-bottom: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
table th:first-child,
|
||||||
|
table td:first-child {
|
||||||
|
border-left: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
table th:last-child,
|
||||||
|
table td:last-child {
|
||||||
|
border-right: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
table td input[type="checkbox"] {
|
||||||
|
vertical-align: middle;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
width: 100%;
|
||||||
background-color: #1e1e1e;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#skin_container {
|
footer {
|
||||||
text-align: center;
|
margin-top: 10px;
|
||||||
cursor: move;
|
padding-top: 10px;
|
||||||
|
border-top: 1px grey solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
#skin_container > canvas {
|
label {
|
||||||
background: white;
|
white-space: nowrap;
|
||||||
filter: drop-shadow(-5px 5px 7px rgba(0, 0, 0, 0.4));
|
|
||||||
outline: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#elytra, #animated {
|
.control-section ul {
|
||||||
display: block;
|
margin-top: 0;
|
||||||
margin: 1vh auto;
|
padding-left: 20px;
|
||||||
font-size: 2rem;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<button id="elytra">Enable/Disable Elytra</button>
|
|
||||||
<button id="animated">Enable/Disable Animated</button>
|
<canvas id="skin_container"></canvas>
|
||||||
<div id="skin_container"></div>
|
|
||||||
<script type="text/javascript" src="../bundles/skinview3d.bundle.js"></script>
|
<div class="controls">
|
||||||
|
|
||||||
|
<button id="reset_all" type="button" class="control">Reset All</button>
|
||||||
|
|
||||||
|
<div class="control-section">
|
||||||
|
<h1>Canvas Size</h1>
|
||||||
|
<label class="control">Width: <input id="canvas_width" type="number" value="300"></label>
|
||||||
|
<label class="control">Height: <input id="canvas_height" type="number" value="300"></label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-section">
|
||||||
|
<h1>Animation</h1>
|
||||||
|
<label class="control">Global Speed: <input id="global_animation_speed" type="number" value="1" step="0.1"></label>
|
||||||
|
<button id="animation_pause_resume" type="button" class="control">Pause / Resume</button>
|
||||||
|
<div>
|
||||||
|
<h2>Rotate</h2>
|
||||||
|
<label class="control"><input id="rotate_animation" type="checkbox"> Enable</label>
|
||||||
|
<label class="control">Speed: <input id="rotate_animation_speed" type="number" value="1" step="0.1"></label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h2>Walk / Run</h2>
|
||||||
|
<div class="control">
|
||||||
|
<label><input type="radio" id="primary_animation_none" name="primary_animation" value="" checked> None</label>
|
||||||
|
<label><input type="radio" id="primary_animation_walk" name="primary_animation" value="walk"> Walk</label>
|
||||||
|
<label><input type="radio" id="primary_animation_run" name="primary_animation" value="run"> Run</label>
|
||||||
|
</div>
|
||||||
|
<label class="control">Speed: <input id="primary_animation_speed" type="number" value="1" step="0.1"></label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-section">
|
||||||
|
<h1>Mouse Control</h1>
|
||||||
|
<div class="control">
|
||||||
|
<label><input type="checkbox" id="control_rotate" checked> Enable Rotate</label>
|
||||||
|
<label><input type="checkbox" id="control_zoom" checked> Enable Zoom</label>
|
||||||
|
<label><input type="checkbox" id="control_pan"> Enable Pan</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-section">
|
||||||
|
<h1>Skin Layers</h1>
|
||||||
|
<table id="layers_table">
|
||||||
|
<!-- table contents are generated using javascript -->
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-section">
|
||||||
|
<h1>Textures</h1>
|
||||||
|
<div>
|
||||||
|
<div class="control">
|
||||||
|
<label>Skin URL: <input id="skin_url" type="text" value="img/1_8_texturemap_redux.png" placeholder="none" list="default_skins"></label>
|
||||||
|
<datalist id="default_skins">
|
||||||
|
<option value="img/1_8_texturemap_redux.png">
|
||||||
|
<option value="img/hacksore.png">
|
||||||
|
<option value="img/haka.png">
|
||||||
|
<option value="img/hatsune_miku.png">
|
||||||
|
<option value="img/ironman_hd.png">
|
||||||
|
<option value="img/sethbling.png">
|
||||||
|
</datalist>
|
||||||
|
<input id="skin_url_upload" type="file" accept="image/*" style="display: none;">
|
||||||
|
<button type="button" class="control"
|
||||||
|
onclick="document.getElementById('skin_url_upload').click();">Browse...</button>
|
||||||
|
</div>
|
||||||
|
<label class="control">Model:
|
||||||
|
<select id="skin_model" value="auto-detect">
|
||||||
|
<option value="auto-detect">Auto detect</option>
|
||||||
|
<option value="default">Default</option>
|
||||||
|
<option value="slim">Slim</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="control">
|
||||||
|
<label>Cape URL: <input id="cape_url" type="text" value="" placeholder="none" list="default_capes"></label>
|
||||||
|
<datalist id="default_capes">
|
||||||
|
<option value="">
|
||||||
|
<option value="img/mojang_cape.png">
|
||||||
|
<option value="img/legacy_cape.png">
|
||||||
|
<option value="img/hd_cape.png">
|
||||||
|
</datalist>
|
||||||
|
<input id="cape_url_upload" type="file" accept="image/*" style="display: none;">
|
||||||
|
<button type="button" class="control"
|
||||||
|
onclick="document.getElementById('cape_url_upload').click();">Browse...</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-section">
|
||||||
|
<h1>Other examples</h1>
|
||||||
|
<ul>
|
||||||
|
<li><a href="offscreen-render.html">offscreen-render</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<div>
|
||||||
|
GitHub: <a href="https://github.com/bs-community/skinview3d">bs-community/skinview3d</a>
|
||||||
|
</div>
|
||||||
|
<!--%%deploy_only%%
|
||||||
|
<div>
|
||||||
|
Built from
|
||||||
|
commit <a href="https://github.com/bs-community/skinview3d/commit/{{build_commit}}">{{build_commit}}</a>
|
||||||
|
at <time datetime="{{build_time}}">{{build_time}}</time>
|
||||||
|
</div>
|
||||||
|
-->
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="../bundles/skinview3d.bundle.js"></script>
|
||||||
<script>
|
<script>
|
||||||
var animated = false;
|
const skinParts = {
|
||||||
|
head: "head",
|
||||||
|
body: "body",
|
||||||
|
rightArm: "right arm",
|
||||||
|
leftArm: "left arm",
|
||||||
|
rightLeg: "right leg",
|
||||||
|
leftLeg: "left leg"
|
||||||
|
};
|
||||||
|
const skinLayers = {
|
||||||
|
innerLayer: "inner",
|
||||||
|
outerLayer: "outer"
|
||||||
|
};
|
||||||
|
const availableAnimations = {
|
||||||
|
walk: skinview3d.WalkingAnimation,
|
||||||
|
run: skinview3d.RunningAnimation
|
||||||
|
};
|
||||||
|
|
||||||
document.getElementById("elytra").addEventListener('click', function() {
|
let skinViewer;
|
||||||
skinViewer.playerObject.cape.visible = !skinViewer.playerObject.cape.visible;
|
let oribitControl;
|
||||||
skinViewer.playerObject.elytra.visible = !skinViewer.playerObject.elytra.visible
|
let rotateAnimation;
|
||||||
});
|
let primaryAnimation;
|
||||||
|
|
||||||
document.getElementById("animated").addEventListener('click', function() {
|
function reloadSkin() {
|
||||||
if(animated) {
|
const input = document.getElementById("skin_url");
|
||||||
skinViewer.loadCustomCape("./cape.png");
|
const url = input.value;
|
||||||
animated = false;
|
if (url === "") {
|
||||||
|
skinViewer.loadSkin(null);
|
||||||
|
input.setCustomValidity("");
|
||||||
} else {
|
} else {
|
||||||
skinViewer.loadCustomCape("./animated.png");
|
skinViewer.loadSkin(url, document.getElementById("skin_model").value)
|
||||||
animated = true;
|
.then(() => input.setCustomValidity(""))
|
||||||
|
.catch(e => {
|
||||||
|
input.setCustomValidity("Image can't be loaded.");
|
||||||
|
console.error(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function reloadCape() {
|
||||||
|
const input = document.getElementById("cape_url");
|
||||||
|
const url = input.value;
|
||||||
|
if (url === "") {
|
||||||
|
skinViewer.loadCape(null);
|
||||||
|
input.setCustomValidity("");
|
||||||
|
} else {
|
||||||
|
skinViewer.loadCape(url)
|
||||||
|
.then(() => input.setCustomValidity(""))
|
||||||
|
.catch(e => {
|
||||||
|
input.setCustomValidity("Image can't be loaded.");
|
||||||
|
console.error(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initializeLayersTable() {
|
||||||
|
const table = document.getElementById("layers_table");
|
||||||
|
const thead = document.createElement("thead");
|
||||||
|
table.appendChild(thead);
|
||||||
|
const rowHead = document.createElement("tr");
|
||||||
|
rowHead.appendChild(document.createElement("th"));
|
||||||
|
thead.appendChild(rowHead);
|
||||||
|
for (const [part, partName] of Object.entries(skinParts)) {
|
||||||
|
const cellHead = document.createElement("th");
|
||||||
|
cellHead.innerText = partName;
|
||||||
|
rowHead.appendChild(cellHead);
|
||||||
|
}
|
||||||
|
const tbody = document.createElement("tbody");
|
||||||
|
table.appendChild(tbody);
|
||||||
|
for (const [layer, layerName] of Object.entries(skinLayers)) {
|
||||||
|
const row = document.createElement("tr");
|
||||||
|
tbody.appendChild(row);
|
||||||
|
const cellLayer = document.createElement("th");
|
||||||
|
cellLayer.innerText = layerName;
|
||||||
|
row.appendChild(cellLayer);
|
||||||
|
for (const part of Object.keys(skinParts)) {
|
||||||
|
const cell = document.createElement("td");
|
||||||
|
row.appendChild(cell);
|
||||||
|
const checkbox = document.createElement("input");
|
||||||
|
checkbox.type = "checkbox";
|
||||||
|
checkbox.dataset.layer = layer;
|
||||||
|
checkbox.dataset.part = part;
|
||||||
|
checkbox.checked = true;
|
||||||
|
cell.appendChild(checkbox);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initializeControls() {
|
||||||
|
document.getElementById("canvas_width").addEventListener("change", e => skinViewer.width = e.target.value);
|
||||||
|
document.getElementById("canvas_height").addEventListener("change", e => skinViewer.height = e.target.value);
|
||||||
|
document.getElementById("global_animation_speed").addEventListener("change", e => skinViewer.animations.speed = e.target.value);
|
||||||
|
document.getElementById("animation_pause_resume").addEventListener("click", () => skinViewer.animations.paused = !skinViewer.animations.paused);
|
||||||
|
document.getElementById("rotate_animation").addEventListener("change", e => {
|
||||||
|
if (e.target.checked && rotateAnimation === null) {
|
||||||
|
rotateAnimation = skinViewer.animations.add(skinview3d.RotatingAnimation);
|
||||||
|
rotateAnimation.speed = document.getElementById("rotate_animation_speed").value;
|
||||||
|
} else if (!e.target.checked && rotateAnimation !== null) {
|
||||||
|
rotateAnimation.resetAndRemove();
|
||||||
|
rotateAnimation = null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
document.getElementById("rotate_animation_speed").addEventListener("change", e => {
|
||||||
let skinViewer = new skinview3d.SkinViewer(document.getElementById("skin_container"), {
|
if (rotateAnimation !== null) {
|
||||||
width: 1400,
|
rotateAnimation.speed = e.target.value;
|
||||||
height: 800,
|
}
|
||||||
skin: "https://crafatar.com/skins/ba4161c03a42496c8ae07d13372f3371",
|
|
||||||
cape: "./cape.png",
|
|
||||||
ears: "./ears.png"
|
|
||||||
});
|
});
|
||||||
|
for (const el of document.querySelectorAll('input[type="radio"][name="primary_animation"]')) {
|
||||||
|
el.addEventListener("change", e => {
|
||||||
|
if (primaryAnimation !== null) {
|
||||||
|
primaryAnimation.resetAndRemove();
|
||||||
|
primaryAnimation = null;
|
||||||
|
}
|
||||||
|
if (e.target.value !== "") {
|
||||||
|
primaryAnimation = skinViewer.animations.add(availableAnimations[e.target.value]);
|
||||||
|
primaryAnimation.speed = document.getElementById("primary_animation_speed").value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
document.getElementById("primary_animation_speed").addEventListener("change", e => {
|
||||||
|
if (primaryAnimation !== null) {
|
||||||
|
primaryAnimation.speed = e.target.value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
document.getElementById("control_rotate").addEventListener("change", e => oribitControl.enableRotate = e.target.checked);
|
||||||
|
document.getElementById("control_zoom").addEventListener("change", e => oribitControl.enableZoom = e.target.checked);
|
||||||
|
document.getElementById("control_pan").addEventListener("change", e => oribitControl.enablePan = e.target.checked);
|
||||||
|
for (const part of Object.keys(skinParts)) {
|
||||||
|
for (const layer of Object.keys(skinLayers)) {
|
||||||
|
document.querySelector(`#layers_table input[type="checkbox"][data-part="${part}"][data-layer="${layer}"]`)
|
||||||
|
.addEventListener("change", e => skinViewer.playerObject.skin[part][layer].visible = e.target.checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const skinReader = new FileReader();
|
||||||
|
skinReader.addEventListener("load", e => {
|
||||||
|
document.getElementById("skin_url").value = skinReader.result;
|
||||||
|
reloadSkin();
|
||||||
|
});
|
||||||
|
document.getElementById("skin_url_upload").addEventListener("change", e => {
|
||||||
|
const file = e.target.files[0];
|
||||||
|
if (file !== undefined) {
|
||||||
|
skinReader.readAsDataURL(file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const capeReader = new FileReader();
|
||||||
|
capeReader.addEventListener("load", e => {
|
||||||
|
document.getElementById("cape_url").value = capeReader.result;
|
||||||
|
reloadCape();
|
||||||
|
});
|
||||||
|
document.getElementById("cape_url_upload").addEventListener("change", e => {
|
||||||
|
const file = e.target.files[0];
|
||||||
|
if (file !== undefined) {
|
||||||
|
capeReader.readAsDataURL(file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
document.getElementById("skin_url").addEventListener("change", () => reloadSkin());
|
||||||
|
document.getElementById("skin_model").addEventListener("change", () => reloadSkin());
|
||||||
|
document.getElementById("cape_url").addEventListener("change", () => reloadCape());
|
||||||
|
document.getElementById("reset_all").addEventListener("click", () => {
|
||||||
|
skinViewer.dispose();
|
||||||
|
initializeViewer();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let control = new skinview3d.createOrbitControls(skinViewer);
|
function initializeViewer() {
|
||||||
control.enableZoom = false;
|
skinViewer = new skinview3d.FXAASkinViewer({
|
||||||
control.enablePan = false;
|
canvas: document.getElementById("skin_container"),
|
||||||
skinViewer.playerObject.rotation.y = 180 * Math.PI / 180;
|
alpha: false
|
||||||
|
});
|
||||||
|
skinViewer.renderer.setClearColor(0x5a76f3);
|
||||||
|
oribitControl = skinview3d.createOrbitControls(skinViewer);
|
||||||
|
rotateAnimation = null;
|
||||||
|
primaryAnimation = null;
|
||||||
|
|
||||||
|
skinViewer.width = document.getElementById("canvas_width").value;
|
||||||
|
skinViewer.height = document.getElementById("canvas_height").value;
|
||||||
|
skinViewer.animations.speed = document.getElementById("global_animation_speed").value;
|
||||||
|
if (document.getElementById("rotate_animation").checked) {
|
||||||
|
rotateAnimation = skinViewer.animations.add(skinview3d.RotatingAnimation);
|
||||||
|
rotateAnimation.speed = document.getElementById("rotate_animation_speed").value;
|
||||||
|
}
|
||||||
|
const primaryAnimationName = document.querySelector('input[type="radio"][name="primary_animation"]:checked').value;
|
||||||
|
if (primaryAnimationName !== "") {
|
||||||
|
primaryAnimation = skinViewer.animations.add(availableAnimations[primaryAnimationName]);
|
||||||
|
primaryAnimation.speed = document.getElementById("primary_animation_speed").value;
|
||||||
|
}
|
||||||
|
oribitControl.enableRotate = document.getElementById("control_rotate").checked;
|
||||||
|
oribitControl.enableZoom = document.getElementById("control_zoom").checked;
|
||||||
|
oribitControl.enablePan = document.getElementById("control_pan").checked;
|
||||||
|
for (const part of Object.keys(skinParts)) {
|
||||||
|
for (const layer of Object.keys(skinLayers)) {
|
||||||
|
skinViewer.playerObject.skin[part][layer].visible =
|
||||||
|
document.querySelector(`#layers_table input[type="checkbox"][data-part="${part}"][data-layer="${layer}"]`).checked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reloadSkin();
|
||||||
|
reloadCape();
|
||||||
|
}
|
||||||
|
|
||||||
|
initializeLayersTable();
|
||||||
|
initializeControls();
|
||||||
|
initializeViewer();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
<script type="module" src="https://unpkg.com/stats.js@0.17.0/src/Stats.js" integrity="sha384-W71K+d2HbqXqQWSj3Vj4RDsIVvIV7lR8O6RArKAiqB39ntwLci0W08qOn4Z1n8sM" crossorigin="anonymous" async></script>
|
||||||
|
<script type="module" async>
|
||||||
|
import Stats from "https://unpkg.com/stats.js@0.17.0/src/Stats.js";
|
||||||
|
const stats = new Stats();
|
||||||
|
stats.dom.style.left = "";
|
||||||
|
stats.dom.style.right = "0";
|
||||||
|
document.body.appendChild(stats.dom);
|
||||||
|
function loop() {
|
||||||
|
stats.update();
|
||||||
|
requestAnimationFrame(loop)
|
||||||
|
}
|
||||||
|
requestAnimationFrame(loop);
|
||||||
|
</script>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
||||||
|
<title>skinview3d / offscreen-render</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="rendered_imgs"></div>
|
||||||
|
<script src="../bundles/skinview3d.bundle.js"></script>
|
||||||
|
<script>
|
||||||
|
const textures = [
|
||||||
|
{
|
||||||
|
skin: "img/1_8_texturemap_redux.png",
|
||||||
|
cape: null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skin: "img/hacksore.png",
|
||||||
|
cape: "img/legacy_cape.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skin: "img/haka.png",
|
||||||
|
cape: null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skin: "img/hatsune_miku.png",
|
||||||
|
cape: "img/mojang_cape.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skin: "img/ironman_hd.png",
|
||||||
|
cape: "img/hd_cape.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skin: "img/sethbling.png",
|
||||||
|
cape: null
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
(async function () {
|
||||||
|
const skinViewer = new skinview3d.FXAASkinViewer({
|
||||||
|
width: 200,
|
||||||
|
height: 300,
|
||||||
|
alpha: false,
|
||||||
|
renderPaused: true
|
||||||
|
});
|
||||||
|
skinViewer.renderer.setClearColor(0x5a76f3);
|
||||||
|
skinViewer.camera.rotation.x = -0.620;
|
||||||
|
skinViewer.camera.rotation.y = 0.534;
|
||||||
|
skinViewer.camera.rotation.z = 0.348;
|
||||||
|
skinViewer.camera.position.x = 30.5;
|
||||||
|
skinViewer.camera.position.y = 18.0;
|
||||||
|
skinViewer.camera.position.z = 42.0;
|
||||||
|
|
||||||
|
for (const { skin, cape } of textures) {
|
||||||
|
await Promise.all([skinViewer.loadSkin(skin), skinViewer.loadCape(cape)]);
|
||||||
|
skinViewer.render();
|
||||||
|
const image = skinViewer.canvas.toDataURL();
|
||||||
|
|
||||||
|
const imgElement = document.createElement("img");
|
||||||
|
imgElement.src = image;
|
||||||
|
imgElement.width = skinViewer.width;
|
||||||
|
imgElement.height = skinViewer.height;
|
||||||
|
document.getElementById("rendered_imgs").appendChild(imgElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
skinViewer.dispose();
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -1,31 +1,31 @@
|
||||||
{
|
{
|
||||||
"name": "skinview3d",
|
"name": "skinview3d",
|
||||||
"version": "2.0.0-alpha.5",
|
"version": "2.0.0-alpha.8",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": {
|
"@babel/code-frame": {
|
||||||
"version": "7.8.3",
|
"version": "7.10.4",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
|
||||||
"integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==",
|
"integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/highlight": "^7.8.3"
|
"@babel/highlight": "^7.10.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/helper-validator-identifier": {
|
"@babel/helper-validator-identifier": {
|
||||||
"version": "7.9.5",
|
"version": "7.10.4",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
|
||||||
"integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==",
|
"integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@babel/highlight": {
|
"@babel/highlight": {
|
||||||
"version": "7.9.0",
|
"version": "7.10.4",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
|
||||||
"integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==",
|
"integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/helper-validator-identifier": "^7.9.0",
|
"@babel/helper-validator-identifier": "^7.10.4",
|
||||||
"chalk": "^2.0.0",
|
"chalk": "^2.0.0",
|
||||||
"js-tokens": "^4.0.0"
|
"js-tokens": "^4.0.0"
|
||||||
}
|
}
|
||||||
|
@ -40,15 +40,20 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@rollup/plugin-node-resolve": {
|
"@rollup/plugin-node-resolve": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "8.4.0",
|
"version": "8.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-8.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-8.4.0.tgz",
|
||||||
"integrity": "sha512-LFqKdRLn0ShtQyf6SBYO69bGE1upV6wUhBX0vFOUnLAyzx5cwp8svA0eHUnu8+YU57XOkrMtfG63QOpQx25pHQ==",
|
"integrity": "sha512-LFqKdRLn0ShtQyf6SBYO69bGE1upV6wUhBX0vFOUnLAyzx5cwp8svA0eHUnu8+YU57XOkrMtfG63QOpQx25pHQ==",
|
||||||
|
=======
|
||||||
|
"version": "9.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-9.0.0.tgz",
|
||||||
|
"integrity": "sha512-gPz+utFHLRrd41WMP13Jq5mqqzHL3OXrfj3/MkSyB6UBIcuNt9j60GCbarzMzdf1VHFpOxfQh/ez7wyadLMqkg==",
|
||||||
|
>>>>>>> upstream/master
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@rollup/pluginutils": "^3.1.0",
|
"@rollup/pluginutils": "^3.1.0",
|
||||||
"@types/resolve": "1.17.1",
|
"@types/resolve": "1.17.1",
|
||||||
"builtin-modules": "^3.1.0",
|
"builtin-modules": "^3.1.0",
|
||||||
"deep-freeze": "^0.0.1",
|
|
||||||
"deepmerge": "^4.2.2",
|
"deepmerge": "^4.2.2",
|
||||||
"is-module": "^1.0.0",
|
"is-module": "^1.0.0",
|
||||||
"resolve": "^1.17.0"
|
"resolve": "^1.17.0"
|
||||||
|
@ -117,9 +122,15 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "14.0.22",
|
"version": "14.0.22",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.22.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.22.tgz",
|
||||||
"integrity": "sha512-emeGcJvdiZ4Z3ohbmw93E/64jRzUHAItSHt8nF7M4TGgQTiWqFVGB8KNpLGFmUHmHLvjvBgFwVlqNcq+VuGv9g==",
|
"integrity": "sha512-emeGcJvdiZ4Z3ohbmw93E/64jRzUHAItSHt8nF7M4TGgQTiWqFVGB8KNpLGFmUHmHLvjvBgFwVlqNcq+VuGv9g==",
|
||||||
|
=======
|
||||||
|
"version": "14.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.0.tgz",
|
||||||
|
"integrity": "sha512-mikldZQitV94akrc4sCcSjtJfsTKt4p+e/s0AGscVA6XArQ9kFclP+ZiYUMnq987rc6QlYxXv/EivqlfSLxpKA==",
|
||||||
|
>>>>>>> upstream/master
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/resolve": {
|
"@types/resolve": {
|
||||||
|
@ -132,12 +143,21 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/eslint-plugin": {
|
"@typescript-eslint/eslint-plugin": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "3.6.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.6.0.tgz",
|
||||||
"integrity": "sha512-ubHlHVt1lsPQB/CZdEov9XuOFhNG9YRC//kuiS1cMQI6Bs1SsqKrEmZnpgRwthGR09/kEDtr9MywlqXyyYd8GA==",
|
"integrity": "sha512-ubHlHVt1lsPQB/CZdEov9XuOFhNG9YRC//kuiS1cMQI6Bs1SsqKrEmZnpgRwthGR09/kEDtr9MywlqXyyYd8GA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/experimental-utils": "3.6.0",
|
"@typescript-eslint/experimental-utils": "3.6.0",
|
||||||
|
=======
|
||||||
|
"version": "3.9.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.9.1.tgz",
|
||||||
|
"integrity": "sha512-XIr+Mfv7i4paEdBf0JFdIl9/tVxyj+rlilWIfZ97Be0lZ7hPvUbS5iHt9Glc8kRI53dsr0PcAEudbf8rO2wGgg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@typescript-eslint/experimental-utils": "3.9.1",
|
||||||
|
>>>>>>> upstream/master
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
"functional-red-black-tree": "^1.0.1",
|
"functional-red-black-tree": "^1.0.1",
|
||||||
"regexpp": "^3.0.0",
|
"regexpp": "^3.0.0",
|
||||||
|
@ -146,6 +166,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/experimental-utils": {
|
"@typescript-eslint/experimental-utils": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "3.6.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.6.0.tgz",
|
||||||
"integrity": "sha512-4Vdf2hvYMUnTdkCNZu+yYlFtL2v+N2R7JOynIOkFbPjf9o9wQvRwRkzUdWlFd2YiiUwJLbuuLnl5civNg5ykOQ==",
|
"integrity": "sha512-4Vdf2hvYMUnTdkCNZu+yYlFtL2v+N2R7JOynIOkFbPjf9o9wQvRwRkzUdWlFd2YiiUwJLbuuLnl5civNg5ykOQ==",
|
||||||
|
@ -154,11 +175,22 @@
|
||||||
"@types/json-schema": "^7.0.3",
|
"@types/json-schema": "^7.0.3",
|
||||||
"@typescript-eslint/types": "3.6.0",
|
"@typescript-eslint/types": "3.6.0",
|
||||||
"@typescript-eslint/typescript-estree": "3.6.0",
|
"@typescript-eslint/typescript-estree": "3.6.0",
|
||||||
|
=======
|
||||||
|
"version": "3.9.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.9.1.tgz",
|
||||||
|
"integrity": "sha512-lkiZ8iBBaYoyEKhCkkw4SAeatXyBq9Ece5bZXdLe1LWBUwTszGbmbiqmQbwWA8cSYDnjWXp9eDbXpf9Sn0hLAg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/json-schema": "^7.0.3",
|
||||||
|
"@typescript-eslint/types": "3.9.1",
|
||||||
|
"@typescript-eslint/typescript-estree": "3.9.1",
|
||||||
|
>>>>>>> upstream/master
|
||||||
"eslint-scope": "^5.0.0",
|
"eslint-scope": "^5.0.0",
|
||||||
"eslint-utils": "^2.0.0"
|
"eslint-utils": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/parser": {
|
"@typescript-eslint/parser": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "3.6.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.6.0.tgz",
|
||||||
"integrity": "sha512-taghDxuLhbDAD1U5Fk8vF+MnR0yiFE9Z3v2/bYScFb0N1I9SK8eKHkdJl1DAD48OGFDMFTeOTX0z7g0W6SYUXw==",
|
"integrity": "sha512-taghDxuLhbDAD1U5Fk8vF+MnR0yiFE9Z3v2/bYScFb0N1I9SK8eKHkdJl1DAD48OGFDMFTeOTX0z7g0W6SYUXw==",
|
||||||
|
@ -168,10 +200,22 @@
|
||||||
"@typescript-eslint/experimental-utils": "3.6.0",
|
"@typescript-eslint/experimental-utils": "3.6.0",
|
||||||
"@typescript-eslint/types": "3.6.0",
|
"@typescript-eslint/types": "3.6.0",
|
||||||
"@typescript-eslint/typescript-estree": "3.6.0",
|
"@typescript-eslint/typescript-estree": "3.6.0",
|
||||||
|
=======
|
||||||
|
"version": "3.9.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.9.1.tgz",
|
||||||
|
"integrity": "sha512-y5QvPFUn4Vl4qM40lI+pNWhTcOWtpZAJ8pOEQ21fTTW4xTJkRplMjMRje7LYTXqVKKX9GJhcyweMz2+W1J5bMg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/eslint-visitor-keys": "^1.0.0",
|
||||||
|
"@typescript-eslint/experimental-utils": "3.9.1",
|
||||||
|
"@typescript-eslint/types": "3.9.1",
|
||||||
|
"@typescript-eslint/typescript-estree": "3.9.1",
|
||||||
|
>>>>>>> upstream/master
|
||||||
"eslint-visitor-keys": "^1.1.0"
|
"eslint-visitor-keys": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/types": {
|
"@typescript-eslint/types": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "3.6.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.6.0.tgz",
|
||||||
"integrity": "sha512-JwVj74ohUSt0ZPG+LZ7hb95fW8DFOqBuR6gE7qzq55KDI3BepqsCtHfBIoa0+Xi1AI7fq5nCu2VQL8z4eYftqg==",
|
"integrity": "sha512-JwVj74ohUSt0ZPG+LZ7hb95fW8DFOqBuR6gE7qzq55KDI3BepqsCtHfBIoa0+Xi1AI7fq5nCu2VQL8z4eYftqg==",
|
||||||
|
@ -185,6 +229,21 @@
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/types": "3.6.0",
|
"@typescript-eslint/types": "3.6.0",
|
||||||
"@typescript-eslint/visitor-keys": "3.6.0",
|
"@typescript-eslint/visitor-keys": "3.6.0",
|
||||||
|
=======
|
||||||
|
"version": "3.9.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.9.1.tgz",
|
||||||
|
"integrity": "sha512-15JcTlNQE1BsYy5NBhctnEhEoctjXOjOK+Q+rk8ugC+WXU9rAcS2BYhoh6X4rOaXJEpIYDl+p7ix+A5U0BqPTw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@typescript-eslint/typescript-estree": {
|
||||||
|
"version": "3.9.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.9.1.tgz",
|
||||||
|
"integrity": "sha512-IqM0gfGxOmIKPhiHW/iyAEXwSVqMmR2wJ9uXHNdFpqVvPaQ3dWg302vW127sBpAiqM9SfHhyS40NKLsoMpN2KA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@typescript-eslint/types": "3.9.1",
|
||||||
|
"@typescript-eslint/visitor-keys": "3.9.1",
|
||||||
|
>>>>>>> upstream/master
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
"glob": "^7.1.6",
|
"glob": "^7.1.6",
|
||||||
"is-glob": "^4.0.1",
|
"is-glob": "^4.0.1",
|
||||||
|
@ -194,21 +253,50 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/visitor-keys": {
|
"@typescript-eslint/visitor-keys": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "3.6.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.6.0.tgz",
|
||||||
"integrity": "sha512-p1izllL2Ubwunite0ITjubuMQRBGgjdVYwyG7lXPX8GbrA6qF0uwSRz9MnXZaHMxID4948gX0Ez8v9tUDi/KfQ==",
|
"integrity": "sha512-p1izllL2Ubwunite0ITjubuMQRBGgjdVYwyG7lXPX8GbrA6qF0uwSRz9MnXZaHMxID4948gX0Ez8v9tUDi/KfQ==",
|
||||||
|
=======
|
||||||
|
"version": "3.9.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.9.1.tgz",
|
||||||
|
"integrity": "sha512-zxdtUjeoSh+prCpogswMwVUJfEFmCOjdzK9rpNjNBfm6EyPt99x3RrJoBOGZO23FCt0WPKUCOL5mb/9D5LjdwQ==",
|
||||||
|
>>>>>>> upstream/master
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"eslint-visitor-keys": "^1.1.0"
|
"eslint-visitor-keys": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@yushijinhun/three-minifier-rollup": {
|
<<<<<<< HEAD
|
||||||
"version": "0.1.7",
|
=======
|
||||||
"resolved": "https://registry.npmjs.org/@yushijinhun/three-minifier-rollup/-/three-minifier-rollup-0.1.7.tgz",
|
"@yushijinhun/three-minifier-common": {
|
||||||
"integrity": "sha512-GzlFkEzUqyI8X23guT7Y8R3KaCzCXdUNpWfSPiq7m/f3xUNhhclFJORWqurZdnSEnxWCiCMgNm/9GsLMd/N2Qw==",
|
"version": "0.2.0-alpha.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@yushijinhun/three-minifier-common/-/three-minifier-common-0.2.0-alpha.2.tgz",
|
||||||
|
"integrity": "sha512-Y2NlRcyvEQmY5FlELV/Az7UElddTqKwZxA77OB0of5sj610pa2pM+IlwC20qgEXMaqfdULaENjYGi5EHPK0RSQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@rollup/plugin-node-resolve": "^8.0.0",
|
"acorn": "^8.0.1",
|
||||||
|
"acorn-walk": "^8.0.0",
|
||||||
|
"glsl-tokenizer": "^2.1.5"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"acorn": {
|
||||||
|
"version": "8.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.0.1.tgz",
|
||||||
|
"integrity": "sha512-dmKn4pqZ29iQl2Pvze1zTrps2luvls2PBY//neO2WJ0s10B3AxJXshN+Ph7B4GrhfGhHXrl4dnUwyNNXQcnWGQ==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
>>>>>>> upstream/master
|
||||||
|
"@yushijinhun/three-minifier-rollup": {
|
||||||
|
"version": "0.2.0-alpha.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@yushijinhun/three-minifier-rollup/-/three-minifier-rollup-0.2.0-alpha.2.tgz",
|
||||||
|
"integrity": "sha512-jB9efJwsX9M4QGx4/rA760H9G44tnGq6gIG/ZlP8PWKIBdw48JmRlk20LP1mCT0SH6CKGZcdE0DwR3At+ssGXg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@rollup/plugin-node-resolve": "^9.0.0",
|
||||||
|
"@yushijinhun/three-minifier-common": "^0.2.0-alpha.2",
|
||||||
"magic-string": "^0.25.7"
|
"magic-string": "^0.25.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -233,9 +321,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"acorn": {
|
"acorn": {
|
||||||
"version": "7.3.1",
|
"version": "7.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz",
|
||||||
"integrity": "sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA==",
|
"integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"acorn-jsx": {
|
"acorn-jsx": {
|
||||||
|
@ -244,19 +332,31 @@
|
||||||
"integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==",
|
"integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"acorn-walk": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-oZRad/3SMOI/pxbbmqyurIx7jHw1wZDcR9G44L8pUVFEomX/0dH89SrM1KaDXuv1NpzAXz6Op/Xu/Qd5XXzdEA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"agent-base": {
|
"agent-base": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.1.tgz",
|
||||||
"integrity": "sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw==",
|
"integrity": "sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"debug": "4"
|
"debug": "4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ajv": {
|
"ajv": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "6.12.3",
|
"version": "6.12.3",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz",
|
||||||
"integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==",
|
"integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==",
|
||||||
|
=======
|
||||||
|
"version": "6.12.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz",
|
||||||
|
"integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==",
|
||||||
|
>>>>>>> upstream/master
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"fast-deep-equal": "^3.1.1",
|
"fast-deep-equal": "^3.1.1",
|
||||||
|
@ -643,12 +743,6 @@
|
||||||
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
|
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"deep-freeze": {
|
|
||||||
"version": "0.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/deep-freeze/-/deep-freeze-0.0.1.tgz",
|
|
||||||
"integrity": "sha1-OgsABd4YZygZ39OM0x+RF5yJPoQ=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"deep-is": {
|
"deep-is": {
|
||||||
"version": "0.1.3",
|
"version": "0.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
|
||||||
|
@ -776,9 +870,15 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"eslint": {
|
"eslint": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "7.4.0",
|
"version": "7.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.4.0.tgz",
|
||||||
"integrity": "sha512-gU+lxhlPHu45H3JkEGgYhWhkR9wLHHEXC9FbWFnTlEkbKyZKWgWRLgf61E8zWmBuI6g5xKBph9ltg3NtZMVF8g==",
|
"integrity": "sha512-gU+lxhlPHu45H3JkEGgYhWhkR9wLHHEXC9FbWFnTlEkbKyZKWgWRLgf61E8zWmBuI6g5xKBph9ltg3NtZMVF8g==",
|
||||||
|
=======
|
||||||
|
"version": "7.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.7.0.tgz",
|
||||||
|
"integrity": "sha512-1KUxLzos0ZVsyL81PnRN335nDtQ8/vZUD6uMtWbF+5zDtjKcsklIi78XoE0MVL93QvWTu+E5y44VyyCsOMBrIg==",
|
||||||
|
>>>>>>> upstream/master
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/code-frame": "^7.0.0",
|
"@babel/code-frame": "^7.0.0",
|
||||||
|
@ -789,9 +889,9 @@
|
||||||
"doctrine": "^3.0.0",
|
"doctrine": "^3.0.0",
|
||||||
"enquirer": "^2.3.5",
|
"enquirer": "^2.3.5",
|
||||||
"eslint-scope": "^5.1.0",
|
"eslint-scope": "^5.1.0",
|
||||||
"eslint-utils": "^2.0.0",
|
"eslint-utils": "^2.1.0",
|
||||||
"eslint-visitor-keys": "^1.2.0",
|
"eslint-visitor-keys": "^1.3.0",
|
||||||
"espree": "^7.1.0",
|
"espree": "^7.2.0",
|
||||||
"esquery": "^1.2.0",
|
"esquery": "^1.2.0",
|
||||||
"esutils": "^2.0.2",
|
"esutils": "^2.0.2",
|
||||||
"file-entry-cache": "^5.0.1",
|
"file-entry-cache": "^5.0.1",
|
||||||
|
@ -805,7 +905,7 @@
|
||||||
"js-yaml": "^3.13.1",
|
"js-yaml": "^3.13.1",
|
||||||
"json-stable-stringify-without-jsonify": "^1.0.1",
|
"json-stable-stringify-without-jsonify": "^1.0.1",
|
||||||
"levn": "^0.4.1",
|
"levn": "^0.4.1",
|
||||||
"lodash": "^4.17.14",
|
"lodash": "^4.17.19",
|
||||||
"minimatch": "^3.0.4",
|
"minimatch": "^3.0.4",
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
"optionator": "^0.9.1",
|
"optionator": "^0.9.1",
|
||||||
|
@ -923,14 +1023,14 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"espree": {
|
"espree": {
|
||||||
"version": "7.1.0",
|
"version": "7.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/espree/-/espree-7.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/espree/-/espree-7.2.0.tgz",
|
||||||
"integrity": "sha512-dcorZSyfmm4WTuTnE5Y7MEN1DyoPYy1ZR783QW1FJoenn7RailyWFsq/UL6ZAAA7uXurN9FIpYyUs3OfiIW+Qw==",
|
"integrity": "sha512-H+cQ3+3JYRMEIOl87e7QdHX70ocly5iW4+dttuR8iYSPr/hXKFb+7dBsZ7+u1adC4VrnPlTkv0+OwuPnDop19g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"acorn": "^7.2.0",
|
"acorn": "^7.3.1",
|
||||||
"acorn-jsx": "^5.2.0",
|
"acorn-jsx": "^5.2.0",
|
||||||
"eslint-visitor-keys": "^1.2.0"
|
"eslint-visitor-keys": "^1.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"esprima": {
|
"esprima": {
|
||||||
|
@ -949,9 +1049,9 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"estraverse": {
|
"estraverse": {
|
||||||
"version": "5.1.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
|
||||||
"integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==",
|
"integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1124,6 +1224,15 @@
|
||||||
"type-fest": "^0.8.1"
|
"type-fest": "^0.8.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"glsl-tokenizer": {
|
||||||
|
"version": "2.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/glsl-tokenizer/-/glsl-tokenizer-2.1.5.tgz",
|
||||||
|
"integrity": "sha512-XSZEJ/i4dmz3Pmbnpsy3cKh7cotvFlBiZnDOwnj/05EwNp2XrhQ4XKJxT7/pDt4kp4YcpRSKz8eTV7S+mwV6MA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"through2": "^0.6.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"graceful-fs": {
|
"graceful-fs": {
|
||||||
"version": "4.1.11",
|
"version": "4.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
|
||||||
|
@ -1351,11 +1460,12 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"jest-worker": {
|
"jest-worker": {
|
||||||
"version": "26.0.0",
|
"version": "26.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.3.0.tgz",
|
||||||
"integrity": "sha512-pPaYa2+JnwmiZjK9x7p9BoZht+47ecFCDFA/CJxspHzeDvQcfVBLWzCiWyo+EGrSiQMWZtCFo9iSvMZnAAo8vw==",
|
"integrity": "sha512-Vmpn2F6IASefL+DVBhPzI2J9/GJUsqzomdeN+P+dK8/jKxbh8R3BtFnx3FIta7wYlPU62cpJMJQo4kuOowcMnw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
"@types/node": "*",
|
||||||
"merge-stream": "^2.0.0",
|
"merge-stream": "^2.0.0",
|
||||||
"supports-color": "^7.0.0"
|
"supports-color": "^7.0.0"
|
||||||
}
|
}
|
||||||
|
@ -1416,9 +1526,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"koa": {
|
"koa": {
|
||||||
"version": "2.12.1",
|
"version": "2.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/koa/-/koa-2.12.1.tgz",
|
"resolved": "https://registry.npmjs.org/koa/-/koa-2.13.0.tgz",
|
||||||
"integrity": "sha512-NuYVKjnBxeEe19VljPO9yNcaKKVrMagcax3jjzZtOlxRY2nThWKQqgnI3Pr1OG7mFtvySoDRixoUWZIt6R9C3A==",
|
"integrity": "sha512-i/XJVOfPw7npbMv67+bOeXr3gPqOAw6uh5wFyNs3QvJ47tUx3M3V9rIE0//WytY42MKz4l/MXKyGkQ2LQTfLUQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"accepts": "^1.3.5",
|
"accepts": "^1.3.5",
|
||||||
|
@ -1591,26 +1701,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"koa-send": {
|
"koa-send": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/koa-send/-/koa-send-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/koa-send/-/koa-send-5.0.1.tgz",
|
||||||
"integrity": "sha512-90ZotV7t0p3uN9sRwW2D484rAaKIsD8tAVtypw/aBU+ryfV+fR2xrcAwhI8Wl6WRkojLUs/cB9SBSCuIb+IanQ==",
|
"integrity": "sha512-tmcyQ/wXXuxpDxyNXv5yNNkdAMdFRqwtegBXUaowiQzUKqJehttS0x2j0eOZDQAyloAth5w6wwBImnFzkUz3pQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"debug": "^3.1.0",
|
"debug": "^4.1.1",
|
||||||
"http-errors": "^1.6.3",
|
"http-errors": "^1.7.3",
|
||||||
"mz": "^2.7.0",
|
|
||||||
"resolve-path": "^1.4.0"
|
"resolve-path": "^1.4.0"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"debug": {
|
|
||||||
"version": "3.2.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
|
|
||||||
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"ms": "^2.1.1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"koa-static": {
|
"koa-static": {
|
||||||
|
@ -1691,9 +1789,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lodash": {
|
"lodash": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "4.17.19",
|
"version": "4.17.19",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
|
||||||
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
|
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
|
||||||
|
=======
|
||||||
|
"version": "4.17.20",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||||
|
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
|
||||||
|
>>>>>>> upstream/master
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"lodash.assignwith": {
|
"lodash.assignwith": {
|
||||||
|
@ -2269,6 +2373,15 @@
|
||||||
"integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==",
|
"integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"randombytes": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"safe-buffer": "^5.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"raw-body": {
|
"raw-body": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz",
|
||||||
|
@ -2380,24 +2493,30 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rollup": {
|
"rollup": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "2.21.0",
|
"version": "2.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.21.0.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.21.0.tgz",
|
||||||
"integrity": "sha512-BEGgy+wSzux7Ycq58pRiWEOBZaXRXTuvzl1gsm7gqmsAHxkWf9nyA5V2LN9fGSHhhDQd0/C13iRzSh4bbIpWZQ==",
|
"integrity": "sha512-BEGgy+wSzux7Ycq58pRiWEOBZaXRXTuvzl1gsm7gqmsAHxkWf9nyA5V2LN9fGSHhhDQd0/C13iRzSh4bbIpWZQ==",
|
||||||
|
=======
|
||||||
|
"version": "2.26.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.26.3.tgz",
|
||||||
|
"integrity": "sha512-Mlt39/kL2rA9egcbQbaZV1SNVplGqYYhDDMcGgHPPE0tvM3R4GrB+IEdYy2QtTrdzMQx57ZcqDFf/KWWm8F+uw==",
|
||||||
|
>>>>>>> upstream/master
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"fsevents": "~2.1.2"
|
"fsevents": "~2.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rollup-plugin-terser": {
|
"rollup-plugin-terser": {
|
||||||
"version": "6.1.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-6.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.0.tgz",
|
||||||
"integrity": "sha512-4fB3M9nuoWxrwm39habpd4hvrbrde2W2GG4zEGPQg1YITNkM3Tqur5jSuXlWNzbv/2aMLJ+dZJaySc3GCD8oDw==",
|
"integrity": "sha512-p/N3lLiFusCjYTLfVkoaiRTOGr5AESEaljMPH12MhOtoMkmTBhIAfuadrcWy4am1U0vU4WTxO9fi0K09O4CboQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/code-frame": "^7.8.3",
|
"@babel/code-frame": "^7.10.4",
|
||||||
"jest-worker": "^26.0.0",
|
"jest-worker": "^26.2.1",
|
||||||
"serialize-javascript": "^3.0.0",
|
"serialize-javascript": "^4.0.0",
|
||||||
"terser": "^4.7.0"
|
"terser": "^5.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
|
@ -2419,10 +2538,13 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"serialize-javascript": {
|
"serialize-javascript": {
|
||||||
"version": "3.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
|
||||||
"integrity": "sha512-skZcHYw2vEX4bw90nAr2iTTsz6x2SrHEnfxgKYmZlvJYBEZrvbKtobJWlQ20zczKb3bsHHXXTYt48zBA7ni9cw==",
|
"integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"randombytes": "^2.1.0"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"serve-index-75lb": {
|
"serve-index-75lb": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
|
@ -2508,9 +2630,15 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"skinview-utils": {
|
"skinview-utils": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "0.5.6",
|
"version": "0.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/skinview-utils/-/skinview-utils-0.5.6.tgz",
|
"resolved": "https://registry.npmjs.org/skinview-utils/-/skinview-utils-0.5.6.tgz",
|
||||||
"integrity": "sha512-TkpkCkLHNmeltUrtmkMexS/6izDE6LD9VKrvEnKvAqByKcymiwfhFydzTCe1vsarnZK1VPtDbAvBh9/n6UkDLg=="
|
"integrity": "sha512-TkpkCkLHNmeltUrtmkMexS/6izDE6LD9VKrvEnKvAqByKcymiwfhFydzTCe1vsarnZK1VPtDbAvBh9/n6UkDLg=="
|
||||||
|
=======
|
||||||
|
"version": "0.5.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/skinview-utils/-/skinview-utils-0.5.7.tgz",
|
||||||
|
"integrity": "sha512-XhOuCzvGoHuYOymfuZ8IJklVgqkYfusuyQSZMWiE/kluh89ZtBjS3cwoHIff1+Z5mAXHoa+Vkr0wN3JHJvF2ag=="
|
||||||
|
>>>>>>> upstream/master
|
||||||
},
|
},
|
||||||
"slice-ansi": {
|
"slice-ansi": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
|
@ -2764,9 +2892,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"terser": {
|
"terser": {
|
||||||
"version": "4.7.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/terser/-/terser-4.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/terser/-/terser-5.1.0.tgz",
|
||||||
"integrity": "sha512-Lfb0RiZcjRDXCC3OSHJpEkxJ9Qeqs6mp2v4jf2MHfy8vGERmVDuvjXdd/EnP5Deme5F2yBRBymKmKHCBg2echw==",
|
"integrity": "sha512-pwC1Jbzahz1ZPU87NQ8B3g5pKbhyJSiHih4gLH6WZiPU8mmS1IlGbB0A2Nuvkj/LCNsgIKctg6GkYwWCeTvXZQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"commander": "^2.20.0",
|
"commander": "^2.20.0",
|
||||||
|
@ -2781,9 +2909,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"thenify": {
|
"thenify": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
|
||||||
"integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=",
|
"integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"any-promise": "^1.0.0"
|
"any-promise": "^1.0.0"
|
||||||
|
@ -2799,9 +2927,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"three": {
|
"three": {
|
||||||
"version": "0.117.1",
|
"version": "0.120.0",
|
||||||
"resolved": "https://registry.npmjs.org/three/-/three-0.117.1.tgz",
|
"resolved": "https://registry.npmjs.org/three/-/three-0.120.0.tgz",
|
||||||
"integrity": "sha512-t4zeJhlNzUIj9+ub0l6nICVimSuRTZJOqvk3Rmlu+YGdTOJ49Wna8p7aumpkXJakJfITiybfpYE1XN1o1Z34UQ=="
|
"integrity": "sha512-Swffpi3EAHWkmqC1MagKEzR5XgwkDiyeWI3M7vkGbBc0xhq2LcQmJj5DqBruLkrgcZQ+fM/+fSQBU1tDvggO4A=="
|
||||||
},
|
},
|
||||||
"through": {
|
"through": {
|
||||||
"version": "2.3.8",
|
"version": "2.3.8",
|
||||||
|
@ -2809,6 +2937,42 @@
|
||||||
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
|
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"through2": {
|
||||||
|
"version": "0.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
|
||||||
|
"integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"readable-stream": ">=1.0.33-1 <1.1.0-0",
|
||||||
|
"xtend": ">=4.0.0 <4.1.0-0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"isarray": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||||
|
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "1.0.34",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
|
||||||
|
"integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"core-util-is": "~1.0.0",
|
||||||
|
"inherits": "~2.0.1",
|
||||||
|
"isarray": "0.0.1",
|
||||||
|
"string_decoder": "~0.10.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"string_decoder": {
|
||||||
|
"version": "0.10.31",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||||
|
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"toidentifier": {
|
"toidentifier": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
|
||||||
|
@ -2862,9 +3026,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"typescript": {
|
"typescript": {
|
||||||
"version": "3.9.6",
|
"version": "3.9.7",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.6.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz",
|
||||||
"integrity": "sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw==",
|
"integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"typical": {
|
"typical": {
|
||||||
|
@ -2976,6 +3140,12 @@
|
||||||
"mkdirp": "^0.5.1"
|
"mkdirp": "^0.5.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"xtend": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"ylru": {
|
"ylru": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/ylru/-/ylru-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/ylru/-/ylru-1.2.1.tgz",
|
||||||
|
|
28
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "skinview3d",
|
"name": "skinview3d",
|
||||||
"version": "2.0.0-alpha.5",
|
"version": "2.0.0-alpha.8",
|
||||||
"description": "Three.js powered Minecraft skin viewer",
|
"description": "Three.js powered Minecraft skin viewer",
|
||||||
"main": "libs/skinview3d.js",
|
"main": "libs/skinview3d.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
@ -11,10 +11,10 @@
|
||||||
"build": "npm run build:modules && npm run build:bundles",
|
"build": "npm run build:modules && npm run build:bundles",
|
||||||
"test:lint": "eslint --ext .ts src",
|
"test:lint": "eslint --ext .ts src",
|
||||||
"test": "npm run test:lint",
|
"test": "npm run test:lint",
|
||||||
"dev:watch:modules": "tsc -w --declaration --sourceMap --outDir libs -p .",
|
"dev:watch:modules": "tsc -w --preserveWatchOutput --declaration --sourceMap --outDir libs -p .",
|
||||||
"dev:watch:bundles": "rollup -w -c",
|
"dev:watch:bundles": "rollup -w --no-watch.clearScreen -c",
|
||||||
"dev:serve": "ws",
|
"dev:serve": "ws",
|
||||||
"dev": "npm-run-all --parallel dev:watch:modules dev:watch:bundles dev:serve",
|
"dev": "npm-run-all --parallel dev:watch:bundles dev:serve",
|
||||||
"prepublishOnly": "npm run clean && npm run build"
|
"prepublishOnly": "npm run clean && npm run build"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -38,21 +38,21 @@
|
||||||
"bundles"
|
"bundles"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"skinview-utils": "^0.5.6",
|
"skinview-utils": "^0.5.7",
|
||||||
"three": "^0.117.1"
|
"three": "^0.120.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rollup/plugin-node-resolve": "^8.4.0",
|
"@rollup/plugin-node-resolve": "^9.0.0",
|
||||||
"@rollup/plugin-typescript": "^5.0.2",
|
"@rollup/plugin-typescript": "^5.0.2",
|
||||||
"@typescript-eslint/eslint-plugin": "^3.6.0",
|
"@typescript-eslint/eslint-plugin": "^3.9.1",
|
||||||
"@typescript-eslint/parser": "^3.6.0",
|
"@typescript-eslint/parser": "^3.9.1",
|
||||||
"@yushijinhun/three-minifier-rollup": "^0.1.7",
|
"@yushijinhun/three-minifier-rollup": "^0.2.0-alpha.2",
|
||||||
"eslint": "^7.4.0",
|
"eslint": "^7.7.0",
|
||||||
"local-web-server": "^4.2.1",
|
"local-web-server": "^4.2.1",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"rollup": "^2.21.0",
|
"rollup": "^2.26.3",
|
||||||
"rollup-plugin-terser": "^6.1.0",
|
"rollup-plugin-terser": "^7.0.0",
|
||||||
"typescript": "^3.9.6"
|
"typescript": "^3.9.7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,7 +162,7 @@ export const WalkingAnimation: Animation = (player, time) => {
|
||||||
export const RunningAnimation: Animation = (player, time) => {
|
export const RunningAnimation: Animation = (player, time) => {
|
||||||
const skin = player.skin;
|
const skin = player.skin;
|
||||||
|
|
||||||
time *= 15;
|
time = time * 15 + Math.PI * 0.5;
|
||||||
|
|
||||||
// Leg swing with larger amplitude
|
// Leg swing with larger amplitude
|
||||||
skin.leftLeg.rotation.x = Math.cos(time + Math.PI) * 1.3;
|
skin.leftLeg.rotation.x = Math.cos(time + Math.PI) * 1.3;
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
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 { FXAAShader } from "three/examples/jsm/shaders/FXAAShader.js";
|
||||||
|
import { SkinViewer, SkinViewerOptions } from "./viewer.js";
|
||||||
|
|
||||||
|
export class FXAASkinViewer extends SkinViewer {
|
||||||
|
|
||||||
|
readonly composer: EffectComposer;
|
||||||
|
readonly renderPass: RenderPass;
|
||||||
|
readonly fxaaPass: ShaderPass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note: FXAA doesn't work well with transparent backgrounds.
|
||||||
|
* It's recommended to use an opaque background and set `options.alpha` to false.
|
||||||
|
*/
|
||||||
|
constructor(options: SkinViewerOptions = {}) {
|
||||||
|
super(options);
|
||||||
|
this.composer = new EffectComposer(this.renderer);
|
||||||
|
this.renderPass = new RenderPass(this.scene, this.camera);
|
||||||
|
this.fxaaPass = new ShaderPass(FXAAShader);
|
||||||
|
this.composer.addPass(this.renderPass);
|
||||||
|
this.composer.addPass(this.fxaaPass);
|
||||||
|
this.updateComposerSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
setSize(width: number, height: number): void {
|
||||||
|
super.setSize(width, height);
|
||||||
|
if (this.composer !== undefined) {
|
||||||
|
this.updateComposerSize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateComposerSize(): void {
|
||||||
|
this.composer.setSize(this.width, this.height);
|
||||||
|
const pixelRatio = this.renderer.getPixelRatio();
|
||||||
|
this.composer.setPixelRatio(pixelRatio);
|
||||||
|
this.fxaaPass.material.uniforms["resolution"].value.x = 1 / (this.width * pixelRatio);
|
||||||
|
this.fxaaPass.material.uniforms["resolution"].value.y = 1 / (this.height * pixelRatio);
|
||||||
|
}
|
||||||
|
|
||||||
|
render(): void {
|
||||||
|
this.composer.render();
|
||||||
|
}
|
||||||
|
}
|
82
src/model.ts
|
@ -72,23 +72,29 @@ export class SkinObject extends Group {
|
||||||
constructor(texture: Texture) {
|
constructor(texture: Texture) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
const layer1 = {
|
const layer1Material = new MeshBasicMaterial({
|
||||||
map: texture,
|
map: texture,
|
||||||
side: FrontSide
|
side: FrontSide
|
||||||
};
|
});
|
||||||
const layer2 = {
|
const layer2Material = new MeshBasicMaterial({
|
||||||
map: texture,
|
map: texture,
|
||||||
side: DoubleSide,
|
side: DoubleSide,
|
||||||
transparent: true,
|
transparent: true,
|
||||||
opacity: 1,
|
alphaTest: 1e-5
|
||||||
alphaTest: 0.5
|
});
|
||||||
}
|
|
||||||
|
|
||||||
const layer1Material = new MeshBasicMaterial(layer1);
|
const layer1MaterialBiased = layer1Material.clone();
|
||||||
const layer2Material = new MeshBasicMaterial(layer2);
|
layer1MaterialBiased.polygonOffset = true;
|
||||||
|
layer1MaterialBiased.polygonOffsetFactor = 1.0;
|
||||||
|
layer1MaterialBiased.polygonOffsetUnits = 1.0;
|
||||||
|
|
||||||
|
const layer2MaterialBiased = layer2Material.clone();
|
||||||
|
layer2MaterialBiased.polygonOffset = true;
|
||||||
|
layer2MaterialBiased.polygonOffsetFactor = 1.0;
|
||||||
|
layer2MaterialBiased.polygonOffsetUnits = 1.0;
|
||||||
|
|
||||||
// Head
|
// Head
|
||||||
const headBox = new BoxGeometry(8, 8, 8, 0, 0, 0);
|
const headBox = new BoxGeometry(8, 8, 8);
|
||||||
setVertices(headBox,
|
setVertices(headBox,
|
||||||
toSkinVertices(8, 0, 16, 8),
|
toSkinVertices(8, 0, 16, 8),
|
||||||
toSkinVertices(16, 0, 24, 8),
|
toSkinVertices(16, 0, 24, 8),
|
||||||
|
@ -99,7 +105,7 @@ export class SkinObject extends Group {
|
||||||
);
|
);
|
||||||
const headMesh = new Mesh(headBox, layer1Material);
|
const headMesh = new Mesh(headBox, layer1Material);
|
||||||
|
|
||||||
const head2Box = new BoxGeometry(9, 9, 9, 0, 0, 0);
|
const head2Box = new BoxGeometry(9, 9, 9);
|
||||||
setVertices(head2Box,
|
setVertices(head2Box,
|
||||||
toSkinVertices(40, 0, 48, 8),
|
toSkinVertices(40, 0, 48, 8),
|
||||||
toSkinVertices(48, 0, 56, 8),
|
toSkinVertices(48, 0, 56, 8),
|
||||||
|
@ -117,7 +123,7 @@ export class SkinObject extends Group {
|
||||||
this.add(this.head);
|
this.add(this.head);
|
||||||
|
|
||||||
// Body
|
// Body
|
||||||
const bodyBox = new BoxGeometry(8, 12, 4, 0, 0, 0);
|
const bodyBox = new BoxGeometry(8, 12, 4);
|
||||||
setVertices(bodyBox,
|
setVertices(bodyBox,
|
||||||
toSkinVertices(20, 16, 28, 20),
|
toSkinVertices(20, 16, 28, 20),
|
||||||
toSkinVertices(28, 16, 36, 20),
|
toSkinVertices(28, 16, 36, 20),
|
||||||
|
@ -126,15 +132,9 @@ export class SkinObject extends Group {
|
||||||
toSkinVertices(28, 20, 32, 32),
|
toSkinVertices(28, 20, 32, 32),
|
||||||
toSkinVertices(32, 20, 40, 32)
|
toSkinVertices(32, 20, 40, 32)
|
||||||
);
|
);
|
||||||
const bodyMesh = new Mesh(bodyBox, new MeshBasicMaterial({
|
const bodyMesh = new Mesh(bodyBox, layer1Material);
|
||||||
...layer1,
|
|
||||||
// this pulls bodyMesh towards the camera
|
|
||||||
// so body is given priority over others in z-fighting
|
|
||||||
polygonOffset: true,
|
|
||||||
polygonOffsetUnits: -1
|
|
||||||
}));
|
|
||||||
|
|
||||||
const body2Box = new BoxGeometry(9, 13.5, 4.5, 0, 0, 0);
|
const body2Box = new BoxGeometry(9, 13.5, 4.5);
|
||||||
setVertices(body2Box,
|
setVertices(body2Box,
|
||||||
toSkinVertices(20, 32, 28, 36),
|
toSkinVertices(20, 32, 28, 36),
|
||||||
toSkinVertices(28, 32, 36, 36),
|
toSkinVertices(28, 32, 36, 36),
|
||||||
|
@ -143,12 +143,7 @@ export class SkinObject extends Group {
|
||||||
toSkinVertices(28, 36, 32, 48),
|
toSkinVertices(28, 36, 32, 48),
|
||||||
toSkinVertices(32, 36, 40, 48)
|
toSkinVertices(32, 36, 40, 48)
|
||||||
);
|
);
|
||||||
const body2Mesh = new Mesh(body2Box, new MeshBasicMaterial({
|
const body2Mesh = new Mesh(body2Box, layer2Material);
|
||||||
...layer2,
|
|
||||||
// same as above
|
|
||||||
polygonOffset: true,
|
|
||||||
polygonOffsetUnits: -1
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.body = new BodyPart(bodyMesh, body2Mesh);
|
this.body = new BodyPart(bodyMesh, body2Mesh);
|
||||||
this.body.name = "body";
|
this.body.name = "body";
|
||||||
|
@ -157,7 +152,7 @@ export class SkinObject extends Group {
|
||||||
this.add(this.body);
|
this.add(this.body);
|
||||||
|
|
||||||
// Right Arm
|
// Right Arm
|
||||||
const rightArmBox = new BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related
|
const rightArmBox = new BoxGeometry();
|
||||||
const rightArmMesh = new Mesh(rightArmBox, layer1Material);
|
const rightArmMesh = new Mesh(rightArmBox, layer1Material);
|
||||||
this.modelListeners.push(() => {
|
this.modelListeners.push(() => {
|
||||||
rightArmMesh.scale.x = this.slim ? 3 : 4;
|
rightArmMesh.scale.x = this.slim ? 3 : 4;
|
||||||
|
@ -186,8 +181,8 @@ export class SkinObject extends Group {
|
||||||
rightArmBox.elementsNeedUpdate = true;
|
rightArmBox.elementsNeedUpdate = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
const rightArm2Box = new BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related
|
const rightArm2Box = new BoxGeometry();
|
||||||
const rightArm2Mesh = new Mesh(rightArm2Box, layer2Material);
|
const rightArm2Mesh = new Mesh(rightArm2Box, layer2MaterialBiased);
|
||||||
rightArm2Mesh.renderOrder = 1;
|
rightArm2Mesh.renderOrder = 1;
|
||||||
this.modelListeners.push(() => {
|
this.modelListeners.push(() => {
|
||||||
rightArm2Mesh.scale.x = this.slim ? 3.375 : 4.5;
|
rightArm2Mesh.scale.x = this.slim ? 3.375 : 4.5;
|
||||||
|
@ -230,7 +225,7 @@ export class SkinObject extends Group {
|
||||||
this.add(this.rightArm);
|
this.add(this.rightArm);
|
||||||
|
|
||||||
// Left Arm
|
// Left Arm
|
||||||
const leftArmBox = new BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related
|
const leftArmBox = new BoxGeometry();
|
||||||
const leftArmMesh = new Mesh(leftArmBox, layer1Material);
|
const leftArmMesh = new Mesh(leftArmBox, layer1Material);
|
||||||
this.modelListeners.push(() => {
|
this.modelListeners.push(() => {
|
||||||
leftArmMesh.scale.x = this.slim ? 3 : 4;
|
leftArmMesh.scale.x = this.slim ? 3 : 4;
|
||||||
|
@ -259,8 +254,8 @@ export class SkinObject extends Group {
|
||||||
leftArmBox.elementsNeedUpdate = true;
|
leftArmBox.elementsNeedUpdate = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
const leftArm2Box = new BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related
|
const leftArm2Box = new BoxGeometry();
|
||||||
const leftArm2Mesh = new Mesh(leftArm2Box, layer2Material);
|
const leftArm2Mesh = new Mesh(leftArm2Box, layer2MaterialBiased);
|
||||||
leftArm2Mesh.renderOrder = 1;
|
leftArm2Mesh.renderOrder = 1;
|
||||||
this.modelListeners.push(() => {
|
this.modelListeners.push(() => {
|
||||||
leftArm2Mesh.scale.x = this.slim ? 3.375 : 4.5;
|
leftArm2Mesh.scale.x = this.slim ? 3.375 : 4.5;
|
||||||
|
@ -303,7 +298,7 @@ export class SkinObject extends Group {
|
||||||
this.add(this.leftArm);
|
this.add(this.leftArm);
|
||||||
|
|
||||||
// Right Leg
|
// Right Leg
|
||||||
const rightLegBox = new BoxGeometry(4, 12, 4, 0, 0, 0);
|
const rightLegBox = new BoxGeometry(4, 12, 4);
|
||||||
setVertices(rightLegBox,
|
setVertices(rightLegBox,
|
||||||
toSkinVertices(4, 16, 8, 20),
|
toSkinVertices(4, 16, 8, 20),
|
||||||
toSkinVertices(8, 16, 12, 20),
|
toSkinVertices(8, 16, 12, 20),
|
||||||
|
@ -312,9 +307,9 @@ export class SkinObject extends Group {
|
||||||
toSkinVertices(8, 20, 12, 32),
|
toSkinVertices(8, 20, 12, 32),
|
||||||
toSkinVertices(12, 20, 16, 32)
|
toSkinVertices(12, 20, 16, 32)
|
||||||
);
|
);
|
||||||
const rightLegMesh = new Mesh(rightLegBox, layer1Material);
|
const rightLegMesh = new Mesh(rightLegBox, layer1MaterialBiased);
|
||||||
|
|
||||||
const rightLeg2Box = new BoxGeometry(4.5, 13.5, 4.5, 0, 0, 0);
|
const rightLeg2Box = new BoxGeometry(4.5, 13.5, 4.5);
|
||||||
setVertices(rightLeg2Box,
|
setVertices(rightLeg2Box,
|
||||||
toSkinVertices(4, 32, 8, 36),
|
toSkinVertices(4, 32, 8, 36),
|
||||||
toSkinVertices(8, 32, 12, 36),
|
toSkinVertices(8, 32, 12, 36),
|
||||||
|
@ -323,7 +318,7 @@ export class SkinObject extends Group {
|
||||||
toSkinVertices(8, 36, 12, 48),
|
toSkinVertices(8, 36, 12, 48),
|
||||||
toSkinVertices(12, 36, 16, 48)
|
toSkinVertices(12, 36, 16, 48)
|
||||||
);
|
);
|
||||||
const rightLeg2Mesh = new Mesh(rightLeg2Box, layer2Material);
|
const rightLeg2Mesh = new Mesh(rightLeg2Box, layer2MaterialBiased);
|
||||||
rightLeg2Mesh.renderOrder = 1;
|
rightLeg2Mesh.renderOrder = 1;
|
||||||
|
|
||||||
const rightLegPivot = new Group();
|
const rightLegPivot = new Group();
|
||||||
|
@ -338,7 +333,7 @@ export class SkinObject extends Group {
|
||||||
this.add(this.rightLeg);
|
this.add(this.rightLeg);
|
||||||
|
|
||||||
// Left Leg
|
// Left Leg
|
||||||
const leftLegBox = new BoxGeometry(4, 12, 4, 0, 0, 0);
|
const leftLegBox = new BoxGeometry(4, 12, 4);
|
||||||
setVertices(leftLegBox,
|
setVertices(leftLegBox,
|
||||||
toSkinVertices(20, 48, 24, 52),
|
toSkinVertices(20, 48, 24, 52),
|
||||||
toSkinVertices(24, 48, 28, 52),
|
toSkinVertices(24, 48, 28, 52),
|
||||||
|
@ -347,9 +342,9 @@ export class SkinObject extends Group {
|
||||||
toSkinVertices(24, 52, 28, 64),
|
toSkinVertices(24, 52, 28, 64),
|
||||||
toSkinVertices(28, 52, 32, 64)
|
toSkinVertices(28, 52, 32, 64)
|
||||||
);
|
);
|
||||||
const leftLegMesh = new Mesh(leftLegBox, layer1Material);
|
const leftLegMesh = new Mesh(leftLegBox, layer1MaterialBiased);
|
||||||
|
|
||||||
const leftLeg2Box = new BoxGeometry(4.5, 13.5, 4.5, 0, 0, 0);
|
const leftLeg2Box = new BoxGeometry(4.5, 13.5, 4.5);
|
||||||
setVertices(leftLeg2Box,
|
setVertices(leftLeg2Box,
|
||||||
toSkinVertices(4, 48, 8, 52),
|
toSkinVertices(4, 48, 8, 52),
|
||||||
toSkinVertices(8, 48, 12, 52),
|
toSkinVertices(8, 48, 12, 52),
|
||||||
|
@ -358,7 +353,7 @@ export class SkinObject extends Group {
|
||||||
toSkinVertices(8, 52, 12, 64),
|
toSkinVertices(8, 52, 12, 64),
|
||||||
toSkinVertices(12, 52, 16, 64)
|
toSkinVertices(12, 52, 16, 64)
|
||||||
);
|
);
|
||||||
const leftLeg2Mesh = new Mesh(leftLeg2Box, layer2Material);
|
const leftLeg2Mesh = new Mesh(leftLeg2Box, layer2MaterialBiased);
|
||||||
leftLeg2Mesh.renderOrder = 1;
|
leftLeg2Mesh.renderOrder = 1;
|
||||||
|
|
||||||
const leftLegPivot = new Group();
|
const leftLegPivot = new Group();
|
||||||
|
@ -404,11 +399,16 @@ export class CapeObject extends Group {
|
||||||
constructor(texture: Texture) {
|
constructor(texture: Texture) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
const capeMaterial = new MeshBasicMaterial({ map: texture, transparent: true, opacity: 1, side: DoubleSide, alphaTest: 0.5 });
|
const capeMaterial = new MeshBasicMaterial({
|
||||||
|
map: texture,
|
||||||
|
side: DoubleSide,
|
||||||
|
transparent: true,
|
||||||
|
alphaTest: 1e-5
|
||||||
|
});
|
||||||
|
|
||||||
// back = outside
|
// back = outside
|
||||||
// front = inside
|
// front = inside
|
||||||
const capeBox = new BoxGeometry(10, 16, 1, 0, 0, 0);
|
const capeBox = new BoxGeometry(10, 16, 1);
|
||||||
setVertices(capeBox,
|
setVertices(capeBox,
|
||||||
toCapeVertices(1, 0, 11, 1),
|
toCapeVertices(1, 0, 11, 1),
|
||||||
toCapeVertices(11, 0, 21, 1),
|
toCapeVertices(11, 0, 21, 1),
|
||||||
|
|
|
@ -2,3 +2,4 @@ export * from "./model.js";
|
||||||
export * from "./viewer.js";
|
export * from "./viewer.js";
|
||||||
export * from "./orbit_controls.js";
|
export * from "./orbit_controls.js";
|
||||||
export * from "./animation.js";
|
export * from "./animation.js";
|
||||||
|
export * from "./fxaa.js";
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { PlayerObject } from "./model.js";
|
||||||
|
|
||||||
export type LoadOptions = {
|
export type LoadOptions = {
|
||||||
/**
|
/**
|
||||||
* Whether to make the object visible after the texture is loaded. (default: true)
|
* Whether to make the object visible after the texture is loaded. Default is true.
|
||||||
*/
|
*/
|
||||||
makeVisible?: boolean;
|
makeVisible?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,29 @@ export type SkinViewerOptions = {
|
||||||
skin?: RemoteImage | TextureSource;
|
skin?: RemoteImage | TextureSource;
|
||||||
cape?: RemoteImage | TextureSource;
|
cape?: RemoteImage | TextureSource;
|
||||||
ears?: RemoteImage | TextureSource;
|
ears?: RemoteImage | TextureSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the canvas contains an alpha buffer. Default is true.
|
||||||
|
* This option can be turned off if you use an opaque background.
|
||||||
|
*/
|
||||||
|
alpha?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render target.
|
||||||
|
* A new canvas is created if this parameter is unspecified.
|
||||||
|
*/
|
||||||
|
canvas?: HTMLCanvasElement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to preserve the buffers until manually cleared or overwritten. Default is false.
|
||||||
|
*/
|
||||||
|
preserveDrawingBuffer?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The initial value of `SkinViewer.renderPaused`. Default is false.
|
||||||
|
* If this option is true, rendering and animation loops will not start.
|
||||||
|
*/
|
||||||
|
renderPaused?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
function toMakeVisible(options?: LoadOptions): boolean {
|
function toMakeVisible(options?: LoadOptions): boolean {
|
||||||
|
@ -26,16 +49,16 @@ function toMakeVisible(options?: LoadOptions): boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
class SkinViewer {
|
class SkinViewer {
|
||||||
readonly domElement: Node;
|
readonly canvas: HTMLCanvasElement;
|
||||||
readonly scene: Scene;
|
readonly scene: Scene;
|
||||||
readonly camera: PerspectiveCamera;
|
readonly camera: PerspectiveCamera;
|
||||||
readonly renderer: WebGLRenderer;
|
readonly renderer: WebGLRenderer;
|
||||||
readonly playerObject: PlayerObject;
|
readonly playerObject: PlayerObject;
|
||||||
readonly animations: RootAnimation = new RootAnimation();
|
readonly animations: RootAnimation = new RootAnimation();
|
||||||
|
|
||||||
protected readonly skinCanvas: HTMLCanvasElement;
|
readonly skinCanvas: HTMLCanvasElement;
|
||||||
protected readonly capeCanvas: HTMLCanvasElement;
|
readonly capeCanvas: HTMLCanvasElement;
|
||||||
protected readonly earCanvas: HTMLCanvasElement;
|
readonly earCanvas: HTMLCanvasElement;
|
||||||
private readonly skinTexture: Texture;
|
private readonly skinTexture: Texture;
|
||||||
private readonly capeTexture: Texture;
|
private readonly capeTexture: Texture;
|
||||||
private readonly earTexture: Texture;
|
private readonly earTexture: Texture;
|
||||||
|
@ -50,8 +73,8 @@ class SkinViewer {
|
||||||
private _disposed: boolean = false;
|
private _disposed: boolean = false;
|
||||||
private _renderPaused: boolean = false;
|
private _renderPaused: boolean = false;
|
||||||
|
|
||||||
constructor(domElement: Node, options: SkinViewerOptions = {}) {
|
constructor(options: SkinViewerOptions = {}) {
|
||||||
this.domElement = domElement;
|
this.canvas = options.canvas === undefined ? document.createElement("canvas") : options.canvas;
|
||||||
|
|
||||||
// texture
|
// texture
|
||||||
this.skinCanvas = document.createElement("canvas");
|
this.skinCanvas = document.createElement("canvas");
|
||||||
|
@ -85,8 +108,13 @@ class SkinViewer {
|
||||||
this.camera.position.y = -12;
|
this.camera.position.y = -12;
|
||||||
this.camera.position.z = 60;
|
this.camera.position.z = 60;
|
||||||
|
|
||||||
this.renderer = new WebGLRenderer({ alpha: true, logarithmicDepthBuffer: true });
|
this.renderer = new WebGLRenderer({
|
||||||
this.domElement.appendChild(this.renderer.domElement);
|
canvas: this.canvas,
|
||||||
|
alpha: options.alpha !== false, // default: true
|
||||||
|
preserveDrawingBuffer: options.preserveDrawingBuffer === true // default: false
|
||||||
|
|
||||||
|
});
|
||||||
|
this.renderer.setPixelRatio(window.devicePixelRatio);
|
||||||
|
|
||||||
this.playerObject = new PlayerObject(this.skinTexture, this.capeTexture, this.earTexture);
|
this.playerObject = new PlayerObject(this.skinTexture, this.capeTexture, this.earTexture);
|
||||||
this.playerObject.name = "player";
|
this.playerObject.name = "player";
|
||||||
|
@ -95,8 +123,6 @@ class SkinViewer {
|
||||||
this.playerObject.ears.visible = false;
|
this.playerObject.ears.visible = false;
|
||||||
this.scene.add(this.playerObject);
|
this.scene.add(this.playerObject);
|
||||||
|
|
||||||
window.requestAnimationFrame(() => this.draw());
|
|
||||||
|
|
||||||
if (options.skin !== undefined) {
|
if (options.skin !== undefined) {
|
||||||
this.loadSkin(options.skin);
|
this.loadSkin(options.skin);
|
||||||
}
|
}
|
||||||
|
@ -112,6 +138,12 @@ class SkinViewer {
|
||||||
if (options.height !== undefined) {
|
if (options.height !== undefined) {
|
||||||
this.height = options.height;
|
this.height = options.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.renderPaused === true) {
|
||||||
|
this._renderPaused = true;
|
||||||
|
} else {
|
||||||
|
window.requestAnimationFrame(() => this.draw());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected skinLoaded(model: ModelType, options?: LoadOptions): void {
|
protected skinLoaded(model: ModelType, options?: LoadOptions): void {
|
||||||
|
@ -153,12 +185,16 @@ class SkinViewer {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.animations.runAnimationLoop(this.playerObject);
|
this.animations.runAnimationLoop(this.playerObject);
|
||||||
this.doRender();
|
this.render();
|
||||||
this.animatedCape();
|
this.animatedCape();
|
||||||
window.requestAnimationFrame(() => this.draw());
|
window.requestAnimationFrame(() => this.draw());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected doRender(): void {
|
/**
|
||||||
|
* Renders the scene to the canvas.
|
||||||
|
* This method does not change the animation progress.
|
||||||
|
*/
|
||||||
|
render(): void {
|
||||||
this.renderer.render(this.scene, this.camera);
|
this.renderer.render(this.scene, this.camera);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,7 +206,6 @@ class SkinViewer {
|
||||||
|
|
||||||
dispose(): void {
|
dispose(): void {
|
||||||
this._disposed = true;
|
this._disposed = true;
|
||||||
this.domElement.removeChild(this.renderer.domElement);
|
|
||||||
this.renderer.dispose();
|
this.renderer.dispose();
|
||||||
this.skinTexture.dispose();
|
this.skinTexture.dispose();
|
||||||
this.capeTexture.dispose();
|
this.capeTexture.dispose();
|
||||||
|
@ -180,6 +215,11 @@ class SkinViewer {
|
||||||
return this._disposed;
|
return this._disposed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether rendering and animations are paused.
|
||||||
|
* Setting this property to true will stop both rendering and animation loops.
|
||||||
|
* Setting it back to false will resume them.
|
||||||
|
*/
|
||||||
get renderPaused(): boolean {
|
get renderPaused(): boolean {
|
||||||
return this._renderPaused;
|
return this._renderPaused;
|
||||||
}
|
}
|
||||||
|
|