-
+
- `;
+ `)
// Setup the scene renderer and OpenGL context
- this.canvas = findWithClass(parent, "spine-player-canvas")[0] as HTMLCanvasElement;
+ this.canvas = findWithClass(dom, "spine-player-canvas")[0] as HTMLCanvasElement;
var webglConfig = { alpha: config.alpha };
this.context = new spine.webgl.ManagedWebGLRenderingContext(this.canvas, webglConfig);
@@ -196,33 +278,23 @@
this.assetManager = new spine.webgl.AssetManager(this.context);
this.assetManager.loadText(config.jsonUrl);
this.assetManager.loadTextureAtlas(config.atlasUrl);
+ if (config.backgroundImage && config.backgroundImage.url)
+ this.assetManager.loadTexture(config.backgroundImage.url);
// Setup rendering loop
requestAnimationFrame(() => this.drawFrame());
// Setup the event listeners for UI elements
- let timeline = findWithClass(parent, "spine-player-timeline")[0];
- this.timelineSlider = new Slider(timeline);
- this.playButton = findWithId(parent, "spine-player-button-play-pause")[0];
- let speedButton = findWithId(parent, "spine-player-button-speed")[0];
- let animationButton = findWithId(parent, "spine-player-button-animation")[0];
- let skinButton = findWithId(parent, "spine-player-button-skin")[0];
- let settingsButton = findWithId(parent, "spine-player-button-settings")[0];
- let fullscreenButton = findWithId(parent, "spine-player-button-fullscreen")[0];
-
- let dropdown = findWithClass(parent, "spine-player-dropdown-content")[0];
-
- var justClicked = false;
- let dismissDropdown = function (event: any) {
- if (justClicked) {
- justClicked = false;
- return;
- }
- if (!isContained(dropdown, event.target)) {
- dropdown.classList.add("spine-player-hidden");
- window.onclick = null;
- }
- }
+ this.playerControls = findWithClass(dom, "spine-player-controls")[0];
+ let timeline = findWithClass(dom, "spine-player-timeline")[0];
+ this.timelineSlider = new Slider();
+ timeline.appendChild(this.timelineSlider.render());
+ this.playButton = findWithId(dom, "spine-player-button-play-pause")[0];
+ let speedButton = findWithId(dom, "spine-player-button-speed")[0];
+ let animationButton = findWithId(dom, "spine-player-button-animation")[0];
+ let skinButton = findWithId(dom, "spine-player-button-skin")[0];
+ let settingsButton = findWithId(dom, "spine-player-button-settings")[0];
+ let fullscreenButton = findWithId(dom, "spine-player-button-fullscreen")[0];
this.playButton.onclick = () => {
if (this.paused) this.play()
@@ -230,124 +302,19 @@
}
speedButton.onclick = () => {
- dropdown.classList.remove("spine-player-hidden");
- dropdown.innerHTML = /*html*/`
-
- `;
- let sliderParent = findWithClass(dropdown, "spine-player-speed-slider")[0];
- let slider = new Slider(sliderParent);
- slider.setValue(this.speed / 2);
- slider.change = (percentage) => {
- this.speed = percentage * 2;
- }
- justClicked = true;
- window.onclick = dismissDropdown;
+ this.showSpeedDialog();
}
animationButton.onclick = () => {
- if (!this.skeleton || this.skeleton.data.animations.length == 0) return;
- dropdown.classList.remove("spine-player-hidden");
- dropdown.innerHTML = /*html*/`
-
Animations
-
-
-
- `;
-
- let rows = findWithClass(dropdown, "spine-player-list")[0];
- this.skeleton.data.animations.forEach((animation) => {
- let row = document.createElement("div");
- row.classList.add("spine-player-list-item");
- if (animation.name == this.config.animation) row.classList.add("spine-player-list-item-selected");
- row.innerText = animation.name;
- rows.appendChild(row);
- row.onclick = () => {
- removeClass(rows.children, "spine-player-list-item-selected");
- row.classList.add("spine-player-list-item-selected");
- this.config.animation = animation.name;
- this.playTime = 0;
- this.animationState.setAnimation(0, this.config.animation, true);
- }
- });
-
- justClicked = true;
- window.onclick = dismissDropdown;
+ this.showAnimationsDialog();
}
skinButton.onclick = () => {
- if (!this.skeleton || this.skeleton.data.animations.length == 0) return;
- dropdown.classList.remove("spine-player-hidden");
- dropdown.innerHTML = /*html*/`
-
Skins
-
-
-
- `;
-
- let rows = findWithClass(dropdown, "spine-player-list")[0];
- this.skeleton.data.skins.forEach((skin) => {
- let row = document.createElement("div");
- row.classList.add("spine-player-list-item");
- if (skin.name == this.config.skin) row.classList.add("spine-player-list-item-selected");
- row.innerText = skin.name;
- rows.appendChild(row);
- row.onclick = () => {
- removeClass(rows.children, "spine-player-list-item-selected");
- row.classList.add("spine-player-list-item-selected");
- this.config.skin = skin.name;
- this.skeleton.setSkinByName(this.config.skin);
- this.skeleton.setSlotsToSetupPose();
- }
- });
-
- justClicked = true;
- window.onclick = dismissDropdown;
+ this.showSkinsDialog();
}
settingsButton.onclick = () => {
- if (!this.skeleton || this.skeleton.data.animations.length == 0) return;
- dropdown.classList.remove("spine-player-hidden");
- dropdown.innerHTML = /*html*/`
-
Debug
-
-
-
- `;
-
- let rows = findWithClass(dropdown, "spine-player-list")[0];
- let makeItem = (name: string) => {
- let row = document.createElement("div");
- row.classList.add("spine-player-list-item");
- if ((this.config.debug as any)[name] == true) row.classList.add("spine-player-list-item-selected");
- row.innerText = name
- rows.appendChild(row);
- row.onclick = () => {
- if ((this.config.debug as any)[name]) {
- (this.config.debug as any)[name] = false;
- row.classList.remove("spine-player-list-item-selected");
- } else {
- (this.config.debug as any)[name] = true;
- row.classList.add("spine-player-list-item-selected");
- }
- }
- };
-
- Object.keys(this.config.debug).forEach((name) => {
- makeItem(name);
- });
-
- justClicked = true;
- window.onclick = dismissDropdown;
+ this.showSettingsDialog();
}
fullscreenButton.onclick = () => {
@@ -358,7 +325,7 @@
else if (doc.webkitExitFullscreen) doc.webkitExitFullscreen()
else if (doc.msExitFullscreen) doc.msExitFullscreen();
} else {
- let player = findWithClass(parent, "spine-player")[0] as any;
+ let player = dom as any;
if (player.requestFullscreen) player.requestFullscreen();
else if (player.webkitRequestFullScreen) player.webkitRequestFullScreen();
else if (player.mozRequestFullScreen) player.mozRequestFullScreen();
@@ -370,6 +337,143 @@
window.onresize = () => {
this.drawFrame(false);
}
+
+ return dom;
+ }
+
+ showSpeedDialog () {
+ let popup = new Popup(this.playerControls, /*html*/`
+
+ `);
+ let sliderParent = findWithClass(popup.dom, "spine-player-speed-slider")[0];
+ let slider = new Slider();
+ sliderParent.appendChild(slider.render());
+ slider.setValue(this.speed / 2);
+ slider.change = (percentage) => {
+ this.speed = percentage * 2;
+ }
+ popup.show();
+ }
+
+ showAnimationsDialog () {
+ if (!this.skeleton || this.skeleton.data.animations.length == 0) return;
+
+ let popup = new Popup(this.playerControls, /*html*/`
+
+
+
+ `);
+
+ let rows = findWithClass(popup.dom, "spine-player-list")[0];
+ this.skeleton.data.animations.forEach((animation) => {
+ // skip animations not whitelisted if a whitelist is given
+ if (this.config.animations && this.config.animations.indexOf(animation.name) < 0) {
+ return;
+ }
+
+ let row = createElement(/*html*/`
+
+
+
+
+
+
+ `);
+ if (animation.name == this.config.animation) row.classList.add("selected");
+ findWithClass(row, "selectable-text")[0].innerText = animation.name;
+ rows.appendChild(row);
+ row.onclick = () => {
+ removeClass(rows.children, "selected");
+ row.classList.add("selected");
+ this.config.animation = animation.name;
+ this.playTime = 0;
+ this.animationState.setAnimation(0, this.config.animation, true);
+ }
+ });
+ popup.show();
+ }
+
+ showSkinsDialog () {
+ if (!this.skeleton || this.skeleton.data.animations.length == 0) return;
+
+ let popup = new Popup(this.playerControls, /*html*/`
+
+
+
+ `);
+
+ let rows = findWithClass(popup.dom, "spine-player-list")[0];
+ this.skeleton.data.skins.forEach((skin) => {
+ // skip animations not whitelisted if a whitelist is given
+ if (this.config.skins && this.config.skins.indexOf(skin.name) < 0) {
+ return;
+ }
+
+ let row = createElement(/*html*/`
+
+
+
+
+
+
+ `);
+ if (skin.name == this.config.skin) row.classList.add("selected");
+ findWithClass(row, "selectable-text")[0].innerText = skin.name;
+ rows.appendChild(row);
+ row.onclick = () => {
+ removeClass(rows.children, "selected");
+ row.classList.add("selected");
+ this.config.skin = skin.name;
+ this.skeleton.setSkinByName(this.config.skin);
+ this.skeleton.setSlotsToSetupPose();
+ }
+ });
+
+ popup.show();
+ }
+
+ showSettingsDialog () {
+ if (!this.skeleton || this.skeleton.data.animations.length == 0) return;
+
+ let popup = new Popup(this.playerControls, /*html*/`
+
+
+
+
+ `);
+
+ let rows = findWithClass(popup.dom, "spine-player-list")[0];
+ let makeItem = (label: string, name: string) => {
+ let row = createElement(/*html*/``);
+ let s = new Switch(label);
+ row.appendChild(s.render());
+ s.setEnabled((this.config.debug as any)[name]);
+ s.change = (value) => {
+ (this.config.debug as any)[name] = value;
+ }
+ rows.appendChild(row);
+ };
+
+ makeItem("Show bones", "bones");
+ makeItem("Show regions", "regions");
+ makeItem("Show meshes", "meshes");
+ makeItem("Show bounds", "bounds");
+ makeItem("Show paths", "paths");
+ makeItem("Show clipping", "clipping");
+ makeItem("Show points", "points");
+ makeItem("Show hulls", "hulls");
+
+ popup.show();
}
drawFrame (requestNextFrame = true) {
@@ -393,6 +497,7 @@
// Update and draw the skeleton
if (this.loaded) {
+ // Update animation and skeleton based on user selections
if (!this.paused && this.config.animation) {
this.time.update();
let delta = this.time.delta * this.speed;
@@ -417,15 +522,28 @@
this.sceneRenderer.camera.position.y = this.config.viewport.y + this.config.viewport.height / 2;
this.sceneRenderer.begin();
+
+ // Draw background image if given
+ if (this.config.backgroundImage && this.config.backgroundImage.url) {
+ let bgImage = this.assetManager.get(this.config.backgroundImage.url);
+ if (!this.config.backgroundImage.x) {
+ this.sceneRenderer.drawTexture(bgImage, this.config.viewport.x, this.config.viewport.y, this.config.viewport.width, this.config.viewport.height);
+ } else {
+ this.sceneRenderer.drawTexture(bgImage, this.config.backgroundImage.x, this.config.backgroundImage.y, this.config.backgroundImage.width, this.config.backgroundImage.height);
+ }
+ }
+
+ // Draw skeleton and debug output
this.sceneRenderer.drawSkeleton(this.skeleton, this.config.premultipliedAlpha);
this.sceneRenderer.skeletonDebugRenderer.drawBones = this.config.debug.bones;
this.sceneRenderer.skeletonDebugRenderer.drawBoundingBoxes = this.config.debug.bounds;
this.sceneRenderer.skeletonDebugRenderer.drawClipping = this.config.debug.clipping;
- this.sceneRenderer.skeletonDebugRenderer.drawMeshHull = this.config.debug.meshHull;
+ this.sceneRenderer.skeletonDebugRenderer.drawMeshHull = this.config.debug.hulls;
this.sceneRenderer.skeletonDebugRenderer.drawPaths = this.config.debug.paths;
this.sceneRenderer.skeletonDebugRenderer.drawRegionAttachments = this.config.debug.regions;
- this.sceneRenderer.skeletonDebugRenderer.drawMeshTriangles = this.config.debug.triangles;
+ this.sceneRenderer.skeletonDebugRenderer.drawMeshTriangles = this.config.debug.meshes;
this.sceneRenderer.drawSkeletonDebug(this.skeleton, this.config.premultipliedAlpha);
+
this.sceneRenderer.end();
this.sceneRenderer.camera.zoom = 0;
@@ -578,6 +696,12 @@
return found;
}
+ function createElement(html: string): HTMLElement {
+ let dom = document.createElement("div");
+ dom.innerHTML = html;
+ return dom.children[0] as HTMLElement;
+ }
+
function removeClass(elements: HTMLCollection, clazz: string) {
for (var i = 0; i < elements.length; i++) {
elements[i].classList.remove(clazz);