352 lines
12 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/lil-gui@0.19.2/dist/lil-gui.umd.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/lil-gui@0.19.2/dist/lil-gui.min.css" rel="stylesheet">
<script src="../dist/iife/spine-webcomponents.js"></script>
<title>Webcomponent GUI</title>
<style>
body, html {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
background-color: #3498db;
}
.container {
display: flex;
height: 100vh;
}
.left-column {
flex: 1;
overflow-y: auto;
margin: 20px;
background: url("assets/checker.png")
}
.right-column {
width: 300px;
overflow-y: auto;
display: flex; /* Enables Flexbox layout */
justify-content: center; /* Horizontally centers content */
}
#lil {
flex: 1;
}
</style>
</head>
<body>
<div class="container">
<div class="left-column">
<spine-skeleton
identifier="boi"
atlas="/assets/spineboy-pma.atlas"
skeleton="/assets/spineboy-pro.skel"
auto-calculate-bounds
debug
></spine-skeleton>
</div>
<div class="right-column">
<div id="lil"></div>
</div>
</div>
<script>
(async () => {
const boi = await spine.getSkeleton("boi").whenReady;
const animations = boi.skeleton.data.animations.map(({ name }) => name);
animations.push("none");
const skins = boi.skeleton.data.skins.map(({ name }) => name);
const gui = new lil.GUI({ container: document.getElementById('lil'), autoPlace: false, width: "100%" });
const refillAnimations = () => {
const animations = boi.skeleton.data.animations.map(({ name }) => name);
animations.push("none");
const animationController = getController("animation");
animationController.options(animations).setValue(animations[animations.length - 1]);
}
const refillSkins = () => {
const skins = boi.skeleton.data.skins.map(({ name }) => name);
const skinController = getController("skin");
skinController.options(skins).setValue(skins[0]);
}
const refillBounds = () => {
getController("boundsX").setValue(boi.bounds.x);
getController("boundsY").setValue(boi.bounds.y);
getController("boundsWidth").setValue(boi.bounds.width);
getController("boundsHeight").setValue(boi.bounds.height);
}
const myObject = {
drag: false,
debug: true,
clip: false,
animation: "none",
skin: "default",
padLeft: 0,
padRight: 0,
padBottom: 0,
padTop: 0,
customBounds: false,
autoCalculateBounds: true,
fit: "contain",
mode: "inside",
scaleX: 1,
scaleY: 1,
xAxis: boi.xAxis,
yAxis: boi.yAxis,
offsetX: boi.offsetX,
offsetY: boi.offsetY,
skeletonPath: boi.skeletonPath,
atlasPath: boi.atlasPath,
boundsX: boi.bounds.x,
boundsY: boi.bounds.y,
boundsWidth: boi.bounds.width,
boundsHeight: boi.bounds.height,
async reload() {
const { atlas: atlasPath, skeleton: skeletonPath } = gui.save().folders.Assets.controllers;
boi.atlasPath = atlasPath;
boi.skeletonPath = skeletonPath;
boi.start();
await boi.whenReady;
console.log(boi.bounds);
refillAnimations();
refillSkins();
refillBounds();
},
};
const assetFolder = gui.addFolder( 'Assets' );
assetFolder.add( myObject, 'skeletonPath' ).name( 'skeleton' );
assetFolder.add( myObject, 'atlasPath' ).name( 'atlas' );
assetFolder.add( myObject, 'reload' ).name( 'Reload Widget' );
gui
.add(myObject, 'animation', animations)
.name( 'animation' )
.onChange(value => {
if (value === "none") {
boi.removeAttribute("animation")
} else {
boi.setAttribute("animation", value)
}
refillBounds();
});
gui
.add(myObject, 'skin', skins)
.name( 'skin' )
.onChange(value => {
if (value === "none") {
boi.removeAttribute("skin")
} else {
boi.setAttribute("skin", value)
}
refillBounds();
});
gui
.add(myObject, 'fit', ["fill", "width", "height", "contain", "cover", "none", "scaleDown"])
.name( 'fit' )
.onChange(value => {
boi.setAttribute("fit", value)
if (value === "none") {
getController("scaleX").enable();
getController("scaleY").enable();
} else {
getController("scaleX").disable();
getController("scaleY").disable();
}
});
gui
.add(myObject, 'mode', ["inside", "origin"])
.name( 'mode' )
.onChange(value => {
boi.setAttribute("mode", value)
if (value === "origin") {
getController("fit").disable();
disableFolder("Bounds");
disableFolder("Padding");
getController("scaleX").enable();
getController("scaleY").enable();
} else {
getController("fit").enable();
enableFolder("Bounds");
enableFolder("Padding");
if (myObject.fit !== "none") {
getController("scaleX").disable();
getController("scaleY").disable();
}
}
});
gui
.add(myObject, 'scaleX').min(-20).max(20).step(0.01)
.name( 'scale-x' )
.onChange(value => {
boi.skeleton.scaleX = value;
})
.disable();
gui
.add(myObject, 'scaleY').min(-20).max(20).step(0.01)
.name( 'scale-y' )
.onChange(value => {
boi.skeleton.scaleY = value;
})
.disable();
gui
.add(myObject, 'drag')
.name( 'drag' )
.onChange(value => {
if (value) boi.setAttribute("drag", '')
else boi.removeAttribute("drag");
});
gui
.add(myObject, 'debug')
.name( 'debug' )
.onChange(value => {
if (value) boi.setAttribute("debug", '')
else boi.removeAttribute("debug");
});
gui
.add(myObject, 'clip')
.name( 'clip' )
.onChange(value => {
if (value) boi.setAttribute("clip", '')
else boi.removeAttribute("clip");
});
gui
.add(myObject, 'xAxis').min(-1).max(1).step(0.01)
.name( 'x-axis' )
.onChange(value => {
boi.setAttribute("x-axis", value)
});
gui
.add(myObject, 'yAxis').min(-1).max(1).step(0.01)
.name( 'y-axis' )
.onChange(value => {
boi.setAttribute("y-axis", value)
});
gui
.add(myObject, 'offsetX').min(-500).max(500).step(0.1)
.name( 'offset-x' )
.onChange(value => {
boi.setAttribute("offset-x", value)
});
gui
.add(myObject, 'offsetY').min(-500).max(500).step(0.1)
.name( 'offset-y' )
.onChange(value => {
boi.setAttribute("offset-y", value)
});
const paddingFolder = gui.addFolder( 'Padding' );
paddingFolder
.add(myObject, 'padLeft').min(0).max(1).step(0.01)
.name( 'pad-left' )
.onChange(value => {
boi.setAttribute("pad-left", value)
});
paddingFolder
.add(myObject, 'padTop').min(0).max(1).step(0.01)
.name( 'pad-top' )
.onChange(value => {
boi.setAttribute("pad-top", value)
});
paddingFolder
.add(myObject, 'padRight').min(0).max(1).step(0.01)
.name( 'pad-right' )
.onChange(value => {
boi.setAttribute("pad-right", value)
});
paddingFolder
.add(myObject, 'padBottom').min(0).max(1).step(0.01)
.name( 'pad-bottom' )
.onChange(value => {
boi.setAttribute("pad-bottom", value)
});
const boundsFolder = gui.addFolder( 'Bounds' );
boundsFolder
.add(myObject, 'autoCalculateBounds')
.name( 'auto-calculate-bounds' )
.onChange(value => {
boi.setAttribute("auto-calculate-bounds", value)
});
boundsFolder
.add(myObject, 'boundsX').min(-500).max(500).step(0.01)
.name( 'bounds-x' )
.onChange(value => {
boi.setAttribute("bounds-x", value)
});
boundsFolder
.add(myObject, 'boundsY').min(-500).max(500).step(0.01)
.name( 'bounds-y' )
.onChange(value => {
boi.setAttribute("bounds-y", value)
});
boundsFolder
.add(myObject, 'boundsWidth').min(0).max(500).step(0.01)
.name( 'bounds-width' )
.onChange(value => {
boi.setAttribute("bounds-width", value)
});
boundsFolder
.add(myObject, 'boundsHeight').min(0).max(500).step(0.01)
.name( 'bounds-height' )
.onChange(value => {
boi.setAttribute("bounds-height", value)
});
const controllers = gui.controllersRecursive();
const getController = (propertyName) => controllers.find(({ property }) => property === propertyName);
const folders = gui.foldersRecursive();
const getFolder = (folderName) => folders.find(({ _title }) => _title === folderName);
const disableFolder = (folderName) => getFolder(folderName).controllers.forEach(c => c.disable());
const enableFolder = (folderName) => getFolder(folderName).controllers.forEach(c => c.enable());
setInterval(() => {
if (myObject.fit === "none" || myObject.mode === "origin") return;
getController("scaleX").setValue(boi.skeleton.scaleX);
getController("scaleY").setValue(boi.skeleton.scaleY);
}, 100)
})();
</script>
</body>
</html>