[ts][player] Fixed text selection on speed slider modification in FF, added snapping to speed slider, added hiding timeline if mouse doesn't move for 1 second except when popup is active or mouse is over controls, decided against popup centered over button, removed Show prefix from debug popup, added hiding buttons if there is only one skin/animation, fixed control bone not moving when paused.

This commit is contained in:
badlogic 2018-11-14 14:29:27 +01:00
parent 8b49ad91cb
commit 94eec340c4
7 changed files with 12094 additions and 11964 deletions

View File

@ -444,7 +444,7 @@ void test (SkeletonData* skeletonData, Atlas* atlas) {
Skeleton skeleton(skeletonData); Skeleton skeleton(skeletonData);
AnimationStateData animationStateData(skeletonData); AnimationStateData animationStateData(skeletonData);
AnimationState animationState(&animationStateData); AnimationState animationState(&animationStateData);
animationState.setAnimation(0, "drive", true); animationState.setAnimation(0, "idle", true);
float d = 3; float d = 3;
for (int i = 0; i < 1; i++) { for (int i = 0; i < 1; i++) {
@ -459,6 +459,7 @@ int main () {
DebugExtension dbgExtension(SpineExtension::getInstance()); DebugExtension dbgExtension(SpineExtension::getInstance());
SpineExtension::setInstance(&dbgExtension); SpineExtension::setInstance(&dbgExtension);
testcase(test, "data/yellow_god.json", "data/yellow_god.skel", "data/yellow_god.atlas", 0.6f);
testcase(spineboy, "data/spineboy-pro.json", "data/spineboy-pro.skel", "data/spineboy.atlas", 0.6f); testcase(spineboy, "data/spineboy-pro.json", "data/spineboy-pro.skel", "data/spineboy.atlas", 0.6f);
testcase(stretchymanStrechyIk, "data/stretchyman-stretchy-ik.json", "data/stretchyman-stretchy-ik.skel", "data/stretchyman.atlas", 0.6f); testcase(stretchymanStrechyIk, "data/stretchyman-stretchy-ik.json", "data/stretchyman-stretchy-ik.skel", "data/stretchyman.atlas", 0.6f);
testcase(spineboy, "data/spineboy-ess.json", "data/spineboy-ess.skel", "data/spineboy.atlas", 0.6f); testcase(spineboy, "data/spineboy-ess.json", "data/spineboy-ess.skel", "data/spineboy.atlas", 0.6f);

View File

@ -16,11 +16,11 @@ declare module spine {
setup = 0, setup = 0,
first = 1, first = 1,
replace = 2, replace = 2,
add = 3 add = 3,
} }
enum MixDirection { enum MixDirection {
in = 0, in = 0,
out = 1 out = 1,
} }
enum TimelineType { enum TimelineType {
rotate = 0, rotate = 0,
@ -37,7 +37,7 @@ declare module spine {
pathConstraintPosition = 11, pathConstraintPosition = 11,
pathConstraintSpacing = 12, pathConstraintSpacing = 12,
pathConstraintMix = 13, pathConstraintMix = 13,
twoColor = 14 twoColor = 14,
} }
abstract class CurveTimeline implements Timeline { abstract class CurveTimeline implements Timeline {
static LINEAR: number; static LINEAR: number;
@ -341,7 +341,7 @@ declare module spine {
end = 2, end = 2,
dispose = 3, dispose = 3,
complete = 4, complete = 4,
event = 5 event = 5,
} }
interface AnimationStateListener2 { interface AnimationStateListener2 {
start(entry: TrackEntry): void; start(entry: TrackEntry): void;
@ -380,8 +380,8 @@ declare module spine {
private toLoad; private toLoad;
private loaded; private loaded;
constructor(textureLoader: (image: HTMLImageElement) => any, pathPrefix?: string); constructor(textureLoader: (image: HTMLImageElement) => any, pathPrefix?: string);
private static downloadText; private static downloadText(url, success, error);
private static downloadBinary; private static downloadBinary(url, success, error);
loadText(path: string, success?: (path: string, text: string) => void, error?: (path: string, error: string) => void): void; loadText(path: string, success?: (path: string, text: string) => void, error?: (path: string, error: string) => void): void;
loadTexture(path: string, success?: (path: string, image: HTMLImageElement) => void, error?: (path: string, error: string) => void): void; loadTexture(path: string, success?: (path: string, image: HTMLImageElement) => void, error?: (path: string, error: string) => void): void;
loadTextureData(path: string, data: string, success?: (path: string, image: HTMLImageElement) => void, error?: (path: string, error: string) => void): void; loadTextureData(path: string, data: string, success?: (path: string, image: HTMLImageElement) => void, error?: (path: string, error: string) => void): void;
@ -414,7 +414,7 @@ declare module spine {
Normal = 0, Normal = 0,
Additive = 1, Additive = 1,
Multiply = 2, Multiply = 2,
Screen = 3 Screen = 3,
} }
} }
declare module spine { declare module spine {
@ -483,7 +483,7 @@ declare module spine {
OnlyTranslation = 1, OnlyTranslation = 1,
NoRotationOrReflection = 2, NoRotationOrReflection = 2,
NoScale = 3, NoScale = 3,
NoScaleOrReflection = 4 NoScaleOrReflection = 4,
} }
} }
declare module spine { declare module spine {
@ -593,17 +593,17 @@ declare module spine {
} }
enum PositionMode { enum PositionMode {
Fixed = 0, Fixed = 0,
Percent = 1 Percent = 1,
} }
enum SpacingMode { enum SpacingMode {
Length = 0, Length = 0,
Fixed = 1, Fixed = 1,
Percent = 2 Percent = 2,
} }
enum RotateMode { enum RotateMode {
Tangent = 0, Tangent = 0,
Chain = 1, Chain = 1,
ChainScale = 2 ChainScale = 2,
} }
} }
declare module spine { declare module spine {
@ -614,12 +614,12 @@ declare module spine {
private rawAssets; private rawAssets;
private errors; private errors;
constructor(pathPrefix?: string); constructor(pathPrefix?: string);
private queueAsset; private queueAsset(clientId, textureLoader, path);
loadText(clientId: string, path: string): void; loadText(clientId: string, path: string): void;
loadJson(clientId: string, path: string): void; loadJson(clientId: string, path: string): void;
loadTexture(clientId: string, textureLoader: (image: HTMLImageElement) => any, path: string): void; loadTexture(clientId: string, textureLoader: (image: HTMLImageElement) => any, path: string): void;
get(clientId: string, path: string): any; get(clientId: string, path: string): any;
private updateClientAssets; private updateClientAssets(clientAssets);
isLoadingComplete(clientId: string): boolean; isLoadingComplete(clientId: string): boolean;
dispose(): void; dispose(): void;
hasErrors(): boolean; hasErrors(): boolean;
@ -823,12 +823,12 @@ declare module spine {
MipMapNearestNearest = 9984, MipMapNearestNearest = 9984,
MipMapLinearNearest = 9985, MipMapLinearNearest = 9985,
MipMapNearestLinear = 9986, MipMapNearestLinear = 9986,
MipMapLinearLinear = 9987 MipMapLinearLinear = 9987,
} }
enum TextureWrap { enum TextureWrap {
MirroredRepeat = 33648, MirroredRepeat = 33648,
ClampToEdge = 33071, ClampToEdge = 33071,
Repeat = 10497 Repeat = 10497,
} }
class TextureRegion { class TextureRegion {
renderObject: any; renderObject: any;
@ -855,7 +855,7 @@ declare module spine {
pages: TextureAtlasPage[]; pages: TextureAtlasPage[];
regions: TextureAtlasRegion[]; regions: TextureAtlasRegion[];
constructor(atlasText: string, textureLoader: (path: string) => any); constructor(atlasText: string, textureLoader: (path: string) => any);
private load; private load(atlasText, textureLoader);
findRegion(name: string): TextureAtlasRegion; findRegion(name: string): TextureAtlasRegion;
dispose(): void; dispose(): void;
} }
@ -931,9 +931,9 @@ declare module spine {
private polygonIndicesPool; private polygonIndicesPool;
triangulate(verticesArray: ArrayLike<number>): Array<number>; triangulate(verticesArray: ArrayLike<number>): Array<number>;
decompose(verticesArray: Array<number>, triangles: Array<number>): Array<Array<number>>; decompose(verticesArray: Array<number>, triangles: Array<number>): Array<Array<number>>;
private static isConcave; private static isConcave(index, vertexCount, vertices, indices);
private static positiveArea; private static positiveArea(p1x, p1y, p2x, p2y, p3x, p3y);
private static winding; private static winding(p1x, p1y, p2x, p2y, p3x, p3y);
} }
} }
declare module spine { declare module spine {
@ -1105,7 +1105,7 @@ declare module spine {
Mesh = 2, Mesh = 2,
LinkedMesh = 3, LinkedMesh = 3,
Path = 4, Path = 4,
Point = 5 Point = 5,
} }
} }
declare module spine { declare module spine {
@ -1299,7 +1299,7 @@ declare module spine.webgl {
touchesPool: Pool<Touch>; touchesPool: Pool<Touch>;
private listeners; private listeners;
constructor(element: HTMLElement); constructor(element: HTMLElement);
private setupCallbacks; private setupCallbacks(element);
addListener(listener: InputListener): void; addListener(listener: InputListener): void;
removeListener(listener: InputListener): void; removeListener(listener: InputListener): void;
} }
@ -1408,7 +1408,7 @@ declare module spine.webgl {
drawWithOffset(shader: Shader, primitiveType: number, offset: number, count: number): void; drawWithOffset(shader: Shader, primitiveType: number, offset: number, count: number): void;
bind(shader: Shader): void; bind(shader: Shader): void;
unbind(shader: Shader): void; unbind(shader: Shader): void;
private update; private update();
restore(): void; restore(): void;
dispose(): void; dispose(): void;
} }
@ -1434,7 +1434,7 @@ declare module spine.webgl {
constructor(); constructor();
} }
enum VertexAttributeType { enum VertexAttributeType {
Float = 0 Float = 0,
} }
} }
declare module spine.webgl { declare module spine.webgl {
@ -1453,7 +1453,7 @@ declare module spine.webgl {
begin(shader: Shader): void; begin(shader: Shader): void;
setBlendMode(srcBlend: number, dstBlend: number): void; setBlendMode(srcBlend: number, dstBlend: number): void;
draw(texture: GLTexture, vertices: ArrayLike<number>, indices: Array<number>): void; draw(texture: GLTexture, vertices: ArrayLike<number>, indices: Array<number>): void;
private flush; private flush();
end(): void; end(): void;
getDrawCalls(): number; getDrawCalls(): number;
dispose(): void; dispose(): void;
@ -1493,13 +1493,13 @@ declare module spine.webgl {
curve(x1: number, y1: number, cx1: number, cy1: number, cx2: number, cy2: number, x2: number, y2: number, segments: number, color?: Color): void; curve(x1: number, y1: number, cx1: number, cy1: number, cx2: number, cy2: number, x2: number, y2: number, segments: number, color?: Color): void;
end(): void; end(): void;
resize(resizeMode: ResizeMode): void; resize(resizeMode: ResizeMode): void;
private enableRenderer; private enableRenderer(renderer);
dispose(): void; dispose(): void;
} }
enum ResizeMode { enum ResizeMode {
Stretch = 0, Stretch = 0,
Expand = 1, Expand = 1,
Fit = 2 Fit = 2,
} }
} }
declare module spine.webgl { declare module spine.webgl {
@ -1527,9 +1527,9 @@ declare module spine.webgl {
getVertexShaderSource(): string; getVertexShaderSource(): string;
getFragmentSource(): string; getFragmentSource(): string;
constructor(context: ManagedWebGLRenderingContext | WebGLRenderingContext, vertexShader: string, fragmentShader: string); constructor(context: ManagedWebGLRenderingContext | WebGLRenderingContext, vertexShader: string, fragmentShader: string);
private compile; private compile();
private compileShader; private compileShader(type, source);
private compileProgram; private compileProgram(vs, fs);
restore(): void; restore(): void;
bind(): void; bind(): void;
unbind(): void; unbind(): void;
@ -1576,16 +1576,16 @@ declare module spine.webgl {
polygon(polygonVertices: ArrayLike<number>, offset: number, count: number, color?: Color): void; polygon(polygonVertices: ArrayLike<number>, offset: number, count: number, color?: Color): void;
circle(filled: boolean, x: number, y: number, radius: number, color?: Color, segments?: number): void; circle(filled: boolean, x: number, y: number, radius: number, color?: Color, segments?: number): void;
curve(x1: number, y1: number, cx1: number, cy1: number, cx2: number, cy2: number, x2: number, y2: number, segments: number, color?: Color): void; curve(x1: number, y1: number, cx1: number, cy1: number, cx2: number, cy2: number, x2: number, y2: number, segments: number, color?: Color): void;
private vertex; private vertex(x, y, color);
end(): void; end(): void;
private flush; private flush();
private check; private check(shapeType, numVertices);
dispose(): void; dispose(): void;
} }
enum ShapeType { enum ShapeType {
Point = 0, Point = 0,
Line = 1, Line = 1,
Filled = 4 Filled = 4,
} }
} }
declare module spine.webgl { declare module spine.webgl {
@ -1718,8 +1718,8 @@ declare module spine {
width: number; width: number;
height: number; height: number;
}; };
success: (widget: SpineWidget) => void; success: (widget: SpinePlayer) => void;
error: (widget: SpineWidget, msg: string) => void; error: (widget: SpinePlayer, msg: string) => void;
} }
class SpinePlayer { class SpinePlayer {
private config; private config;
@ -1733,6 +1733,8 @@ declare module spine {
private canvas; private canvas;
private timelineSlider; private timelineSlider;
private playButton; private playButton;
private skinButton;
private animationButton;
private context; private context;
private loadingScreen; private loadingScreen;
private assetManager; private assetManager;
@ -1756,8 +1758,8 @@ declare module spine {
scale(sourceWidth: number, sourceHeight: number, targetWidth: number, targetHeight: number): Vector2; scale(sourceWidth: number, sourceHeight: number, targetWidth: number, targetHeight: number): Vector2;
loadSkeleton(): void; loadSkeleton(): void;
setupInput(): void; setupInput(): void;
private play; private play();
private pause; private pause();
} }
} }
declare module spine { declare module spine {
@ -1781,10 +1783,10 @@ declare module spine {
private loaded; private loaded;
private bounds; private bounds;
constructor(element: HTMLElement | string, config: SpineWidgetConfig); constructor(element: HTMLElement | string, config: SpineWidgetConfig);
private validateConfig; private validateConfig(config);
private load; private load();
private render; private render();
private resize; private resize();
pause(): void; pause(): void;
play(): void; play(): void;
isPlaying(): boolean; isPlaying(): boolean;
@ -1792,7 +1794,7 @@ declare module spine {
static loadWidgets(): void; static loadWidgets(): void;
static loadWidget(widget: HTMLElement): void; static loadWidget(widget: HTMLElement): void;
static pageLoaded: boolean; static pageLoaded: boolean;
private static ready; private static ready();
static setupDOMListener(): void; static setupDOMListener(): void;
} }
class SpineWidgetConfig { class SpineWidgetConfig {

View File

@ -1,10 +1,7 @@
var __extends = (this && this.__extends) || (function () { var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) { var extendStatics = Object.setPrototypeOf ||
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
}
return function (d, b) { return function (d, b) {
extendStatics(d, b); extendStatics(d, b);
function __() { this.constructor = d; } function __() { this.constructor = d; }
@ -9456,7 +9453,11 @@ var spine;
return Switch; return Switch;
}()); }());
var Slider = (function () { var Slider = (function () {
function Slider() { function Slider(snaps, snapPercentage) {
if (snaps === void 0) { snaps = 0; }
if (snapPercentage === void 0) { snapPercentage = 0.1; }
this.snaps = snaps;
this.snapPercentage = snapPercentage;
} }
Slider.prototype.render = function () { Slider.prototype.render = function () {
var _this = this; var _this = this;
@ -9472,7 +9473,7 @@ var spine;
up: function (x, y) { up: function (x, y) {
dragging = false; dragging = false;
var percentage = x / _this.slider.clientWidth; var percentage = x / _this.slider.clientWidth;
percentage = Math.max(0, Math.min(percentage, 1)); percentage = percentage = Math.max(0, Math.min(percentage, 1));
_this.setValue(x / _this.slider.clientWidth); _this.setValue(x / _this.slider.clientWidth);
if (_this.change) if (_this.change)
_this.change(percentage); _this.change(percentage);
@ -9481,7 +9482,7 @@ var spine;
if (dragging) { if (dragging) {
var percentage = x / _this.slider.clientWidth; var percentage = x / _this.slider.clientWidth;
percentage = Math.max(0, Math.min(percentage, 1)); percentage = Math.max(0, Math.min(percentage, 1));
_this.setValue(x / _this.slider.clientWidth); percentage = _this.setValue(x / _this.slider.clientWidth);
if (_this.change) if (_this.change)
_this.change(percentage); _this.change(percentage);
} }
@ -9489,7 +9490,7 @@ var spine;
dragged: function (x, y) { dragged: function (x, y) {
var percentage = x / _this.slider.clientWidth; var percentage = x / _this.slider.clientWidth;
percentage = Math.max(0, Math.min(percentage, 1)); percentage = Math.max(0, Math.min(percentage, 1));
_this.setValue(x / _this.slider.clientWidth); percentage = _this.setValue(x / _this.slider.clientWidth);
if (_this.change) if (_this.change)
_this.change(percentage); _this.change(percentage);
} }
@ -9498,7 +9499,18 @@ var spine;
}; };
Slider.prototype.setValue = function (percentage) { Slider.prototype.setValue = function (percentage) {
percentage = Math.max(0, Math.min(1, percentage)); percentage = Math.max(0, Math.min(1, percentage));
if (this.snaps > 0) {
var modulo = percentage % (1 / this.snaps);
if (modulo < (1 / this.snaps) * this.snapPercentage) {
percentage = percentage - modulo;
}
else if (modulo > (1 / this.snaps) - (1 / this.snaps) * this.snapPercentage) {
percentage = percentage - modulo + (1 / this.snaps);
}
percentage = Math.max(0, Math.min(1, percentage));
}
this.value.style.width = "" + (percentage * 100) + "%"; this.value.style.width = "" + (percentage * 100) + "%";
return percentage;
}; };
return Slider; return Slider;
}()); }());
@ -9573,11 +9585,12 @@ var spine;
var errorDom = findWithClass(this.dom, "spine-player-error")[0]; var errorDom = findWithClass(this.dom, "spine-player-error")[0];
errorDom.classList.remove("spine-player-hidden"); errorDom.classList.remove("spine-player-hidden");
errorDom.innerHTML = "<p style=\"text-align: center; align-self: center;\">" + error + "</p>"; errorDom.innerHTML = "<p style=\"text-align: center; align-self: center;\">" + error + "</p>";
this.config.error(this, error);
}; };
SpinePlayer.prototype.render = function () { SpinePlayer.prototype.render = function () {
var _this = this; var _this = this;
var config = this.config; var config = this.config;
var dom = this.dom = createElement("\n\t\t\t\t<div class=\"spine-player\">\n\t\t\t\t\t<canvas class=\"spine-player-canvas\"></canvas>\n\t\t\t\t\t<div class=\"spine-player-error spine-player-hidden\"></div>\n\t\t\t\t\t<div class=\"spine-player-controls spine-player-popup-parent\">\n\t\t\t\t\t\t<div class=\"spine-player-timeline\">\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"spine-player-buttons\">\n\t\t\t\t\t\t\t<button id=\"spine-player-button-play-pause\" class=\"spine-player-button spine-player-button-icon-pause\"></button>\n\t\t\t\t\t\t\t<div class=\"spine-player-button-spacer\"></div>\n\t\t\t\t\t\t\t<button id=\"spine-player-button-speed\" class=\"spine-player-button spine-player-button-icon-speed\"></button>\n\t\t\t\t\t\t\t<button id=\"spine-player-button-animation\" class=\"spine-player-button spine-player-button-icon-animations\"></button>\n\t\t\t\t\t\t\t<button id=\"spine-player-button-skin\" class=\"spine-player-button spine-player-button-icon-skins\"></button>\n\t\t\t\t\t\t\t<button id=\"spine-player-button-settings\" class=\"spine-player-button spine-player-button-icon-settings\"></button>\n\t\t\t\t\t\t\t<button id=\"spine-player-button-fullscreen\" class=\"spine-player-button spine-player-button-icon-fullscreen\"></button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t"); var dom = this.dom = createElement("\n\t\t\t\t<div class=\"spine-player\">\n\t\t\t\t\t<canvas class=\"spine-player-canvas\"></canvas>\n\t\t\t\t\t<div class=\"spine-player-error spine-player-hidden\"></div>\n\t\t\t\t\t<div class=\"spine-player-controls spine-player-popup-parent hidden\">\n\t\t\t\t\t\t<div class=\"spine-player-timeline\">\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"spine-player-buttons\">\n\t\t\t\t\t\t\t<button id=\"spine-player-button-play-pause\" class=\"spine-player-button spine-player-button-icon-pause\"></button>\n\t\t\t\t\t\t\t<div class=\"spine-player-button-spacer\"></div>\n\t\t\t\t\t\t\t<button id=\"spine-player-button-speed\" class=\"spine-player-button spine-player-button-icon-speed\"></button>\n\t\t\t\t\t\t\t<button id=\"spine-player-button-animation\" class=\"spine-player-button spine-player-button-icon-animations\"></button>\n\t\t\t\t\t\t\t<button id=\"spine-player-button-skin\" class=\"spine-player-button spine-player-button-icon-skins\"></button>\n\t\t\t\t\t\t\t<button id=\"spine-player-button-settings\" class=\"spine-player-button spine-player-button-icon-settings\"></button>\n\t\t\t\t\t\t\t<button id=\"spine-player-button-fullscreen\" class=\"spine-player-button spine-player-button-icon-fullscreen\"></button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t");
try { try {
this.config = this.validateConfig(config); this.config = this.validateConfig(config);
} }
@ -9608,8 +9621,8 @@ var spine;
timeline.appendChild(this.timelineSlider.render()); timeline.appendChild(this.timelineSlider.render());
this.playButton = findWithId(dom, "spine-player-button-play-pause")[0]; this.playButton = findWithId(dom, "spine-player-button-play-pause")[0];
var speedButton = findWithId(dom, "spine-player-button-speed")[0]; var speedButton = findWithId(dom, "spine-player-button-speed")[0];
var animationButton = findWithId(dom, "spine-player-button-animation")[0]; this.animationButton = findWithId(dom, "spine-player-button-animation")[0];
var skinButton = findWithId(dom, "spine-player-button-skin")[0]; this.skinButton = findWithId(dom, "spine-player-button-skin")[0];
var settingsButton = findWithId(dom, "spine-player-button-settings")[0]; var settingsButton = findWithId(dom, "spine-player-button-settings")[0];
var fullscreenButton = findWithId(dom, "spine-player-button-fullscreen")[0]; var fullscreenButton = findWithId(dom, "spine-player-button-fullscreen")[0];
this.playButton.onclick = function () { this.playButton.onclick = function () {
@ -9621,10 +9634,10 @@ var spine;
speedButton.onclick = function () { speedButton.onclick = function () {
_this.showSpeedDialog(); _this.showSpeedDialog();
}; };
animationButton.onclick = function () { this.animationButton.onclick = function () {
_this.showAnimationsDialog(); _this.showAnimationsDialog();
}; };
skinButton.onclick = function () { this.skinButton.onclick = function () {
_this.showSkinsDialog(); _this.showSkinsDialog();
}; };
settingsButton.onclick = function () { settingsButton.onclick = function () {
@ -9657,15 +9670,13 @@ var spine;
window.onresize = function () { window.onresize = function () {
_this.drawFrame(false); _this.drawFrame(false);
}; };
if (!config.showControls)
findWithClass(dom, "spine-player-controls ")[0].classList.add("spine-player-hidden");
return dom; return dom;
}; };
SpinePlayer.prototype.showSpeedDialog = function () { SpinePlayer.prototype.showSpeedDialog = function () {
var _this = this; var _this = this;
var popup = new Popup(this.playerControls, "\n\t\t\t\t<div class=\"spine-player-row\" style=\"user-select: none; align-items: center; padding: 8px;\">\n\t\t\t\t\t<div style=\"margin-right: 16px;\">Speed</div>\n\t\t\t\t\t<div class=\"spine-player-column\">\n\t\t\t\t\t\t<div class=\"spine-player-speed-slider\" style=\"margin-bottom: 4px;\"></div>\n\t\t\t\t\t\t<div class=\"spine-player-row\" style=\"justify-content: space-between;\">\n\t\t\t\t\t\t\t<div>0.1x</div>\n\t\t\t\t\t\t\t<div>1x</div>\n\t\t\t\t\t\t\t<div>2x</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t"); var popup = new Popup(this.playerControls, "\n\t\t\t\t<div class=\"spine-player-row\" style=\"user-select: none; align-items: center; padding: 8px;\">\n\t\t\t\t\t<div style=\"margin-right: 16px;\">Speed</div>\n\t\t\t\t\t<div class=\"spine-player-column\">\n\t\t\t\t\t\t<div class=\"spine-player-speed-slider\" style=\"margin-bottom: 4px;\"></div>\n\t\t\t\t\t\t<div class=\"spine-player-row\" style=\"justify-content: space-between;\">\n\t\t\t\t\t\t\t<div>0.1x</div>\n\t\t\t\t\t\t\t<div>1x</div>\n\t\t\t\t\t\t\t<div>2x</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t");
var sliderParent = findWithClass(popup.dom, "spine-player-speed-slider")[0]; var sliderParent = findWithClass(popup.dom, "spine-player-speed-slider")[0];
var slider = new Slider(); var slider = new Slider(2);
sliderParent.appendChild(slider.render()); sliderParent.appendChild(slider.render());
slider.setValue(this.speed / 2); slider.setValue(this.speed / 2);
slider.change = function (percentage) { slider.change = function (percentage) {
@ -9739,14 +9750,14 @@ var spine;
}; };
rows.appendChild(row); rows.appendChild(row);
}; };
makeItem("Show bones", "bones"); makeItem("Bones", "bones");
makeItem("Show regions", "regions"); makeItem("Regions", "regions");
makeItem("Show meshes", "meshes"); makeItem("Meshes", "meshes");
makeItem("Show bounds", "bounds"); makeItem("Bounds", "bounds");
makeItem("Show paths", "paths"); makeItem("Paths", "paths");
makeItem("Show clipping", "clipping"); makeItem("Clipping", "clipping");
makeItem("Show points", "points"); makeItem("Points", "points");
makeItem("Show hulls", "hulls"); makeItem("Hulls", "hulls");
popup.show(); popup.show();
}; };
SpinePlayer.prototype.drawFrame = function (requestNextFrame) { SpinePlayer.prototype.drawFrame = function (requestNextFrame) {
@ -9776,8 +9787,8 @@ var spine;
this.timelineSlider.setValue(this.playTime / animationDuration); this.timelineSlider.setValue(this.playTime / animationDuration);
this.animationState.update(delta); this.animationState.update(delta);
this.animationState.apply(this.skeleton); this.animationState.apply(this.skeleton);
this.skeleton.updateWorldTransform();
} }
this.skeleton.updateWorldTransform();
var viewportSize = this.scale(this.config.viewport.width, this.config.viewport.height, this.canvas.width, this.canvas.height); var viewportSize = this.scale(this.config.viewport.width, this.config.viewport.height, this.canvas.width, this.canvas.height);
this.sceneRenderer.camera.zoom = this.config.viewport.width / viewportSize.x; this.sceneRenderer.camera.zoom = this.config.viewport.width / viewportSize.x;
this.sceneRenderer.camera.position.x = this.config.viewport.x + this.config.viewport.width / 2; this.sceneRenderer.camera.position.x = this.config.viewport.x + this.config.viewport.width / 2;
@ -9895,11 +9906,6 @@ var spine;
this.config.viewport.width = size.x * 1.2; this.config.viewport.width = size.x * 1.2;
this.config.viewport.height = size.y * 1.2; this.config.viewport.height = size.y * 1.2;
} }
if (!this.config.animation) {
if (skeletonData.animations.length > 0) {
this.config.animation = skeletonData.animations[0].name;
}
}
if (this.config.animations && this.config.animations.length > 0) { if (this.config.animations && this.config.animations.length > 0) {
this.config.animations.forEach(function (animation) { this.config.animations.forEach(function (animation) {
if (!_this.skeleton.data.findAnimation(animation)) { if (!_this.skeleton.data.findAnimation(animation)) {
@ -9907,6 +9913,14 @@ var spine;
return; return;
} }
}); });
if (!this.config.animation) {
this.config.animation = this.config.animations[0];
}
}
if (!this.config.animation) {
if (skeletonData.animations.length > 0) {
this.config.animation = skeletonData.animations[0].name;
}
} }
if (this.config.animation) { if (this.config.animation) {
if (!skeletonData.findAnimation(this.config.animation)) { if (!skeletonData.findAnimation(this.config.animation)) {
@ -9925,9 +9939,15 @@ var spine;
}; };
} }
this.setupInput(); this.setupInput();
if (skeletonData.skins.length == 1)
this.skinButton.classList.add("spine-player-hidden");
if (skeletonData.animations.length == 1)
this.animationButton.classList.add("spine-player-hidden");
this.config.success(this);
this.loaded = true; this.loaded = true;
}; };
SpinePlayer.prototype.setupInput = function () { SpinePlayer.prototype.setupInput = function () {
var _this = this;
var controlBones = this.config.controlBones; var controlBones = this.config.controlBones;
var selectedBones = this.selectedBones = new Array(this.config.controlBones.length); var selectedBones = this.selectedBones = new Array(this.config.controlBones.length);
var canvas = this.canvas; var canvas = this.canvas;
@ -9949,9 +9969,11 @@ var spine;
target = bone; target = bone;
} }
} }
handleHover();
}, },
up: function (x, y) { up: function (x, y) {
target = null; target = null;
handleHover();
}, },
dragged: function (x, y) { dragged: function (x, y) {
if (target != null) { if (target != null) {
@ -9966,6 +9988,7 @@ var spine;
target.y = coords.y - skeleton.y; target.y = coords.y - skeleton.y;
} }
} }
handleHover();
}, },
moved: function (x, y) { moved: function (x, y) {
for (var i = 0; i < controlBones.length; i++) { for (var i = 0; i < controlBones.length; i++) {
@ -9980,8 +10003,40 @@ var spine;
selectedBones[i] = null; selectedBones[i] = null;
} }
} }
handleHover();
} }
}); });
var mouseOverChildren = false;
canvas.onmouseover = function (ev) {
mouseOverChildren = false;
};
canvas.onmouseout = function (ev) {
if (ev.relatedTarget == null) {
mouseOverChildren = false;
}
else {
mouseOverChildren = isContained(_this.dom, ev.relatedTarget);
}
};
var cancelId = 0;
var handleHover = function () {
if (!_this.config.showControls)
return;
clearTimeout(cancelId);
_this.playerControls.classList.remove("hidden");
_this.playerControls.classList.add("visible");
var remove = function () {
var popup = findWithClass(_this.dom, "spine-player-popup");
if (popup.length == 0 && !mouseOverChildren) {
_this.playerControls.classList.remove("visible");
_this.playerControls.classList.add("hidden");
}
else {
cancelId = setTimeout(remove, 1000);
}
};
cancelId = setTimeout(remove, 1000);
};
}; };
SpinePlayer.prototype.play = function () { SpinePlayer.prototype.play = function () {
this.paused = false; this.paused = false;

File diff suppressed because one or more lines are too long

View File

@ -152,6 +152,8 @@
right: 2px; right: 2px;
bottom: 42px; bottom: 42px;
border-radius: 4px; border-radius: 4px;
max-height: 400%;
overflow: auto;
} }
.spine-player-popup-title { .spine-player-popup-title {
@ -180,13 +182,17 @@
bottom: 0; bottom: 0;
left: 0; left: 0;
width: 100%; width: 100%;
opacity: 0;
transition: opacity 0.2s;
} }
.spine-player:hover .spine-player-controls { .spine-player-controls.hidden {
pointer-events: none;
opacity: 0;
transition: opacity 0.4s;
}
.spine-player-controls.visible {
opacity: 1; opacity: 1;
transition: opacity 0.2s; transition: opacity 0.4s;
} }
/** Player buttons **/ /** Player buttons **/
@ -208,7 +214,7 @@
height: 32px; height: 32px;
background-size: 20px; background-size: 20px;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 6; background-position: center;
cursor: pointer; cursor: pointer;
} }

View File

@ -1,15 +1,21 @@
<!doctype html>
<html> <html>
<script src="../../build/spine-widget.js"></script> <head>
<link rel="stylesheet" href="../css/spine-player.css"> <meta charset="utf-8">
<script src="../../build/spine-widget.js"></script>
<link rel="stylesheet" href="../css/spine-player.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<style> <style>
body { body {
background: gray; background: gray;
margin: 0px;
} }
</style> </style>
<body> <body>
<div id="container" style="width: 100%; height: 100%;"></div> <div id="container" style="width: 100%; height: 100vh;"></div>
</body> </body>
<script> <script>
new spine.SpinePlayer(document.getElementById("container"), { new spine.SpinePlayer(document.getElementById("container"), {
@ -17,7 +23,8 @@ body {
atlasUrl: "assets/spineboy.atlas", atlasUrl: "assets/spineboy.atlas",
animations: ["walk", "jump"], animations: ["walk", "jump"],
controlBones: ["root"], controlBones: ["root"],
backgroundColor: "#cccccc" backgroundColor: "#cccccc",
showControls: false,
}); });
</script> </script>
</body> </body>

View File

@ -170,6 +170,8 @@
private value: HTMLElement; private value: HTMLElement;
public change: (percentage: number) => void; public change: (percentage: number) => void;
constructor(public snaps = 0, public snapPercentage = 0.1) { }
render(): HTMLElement { render(): HTMLElement {
this.slider = createElement(/*html*/` this.slider = createElement(/*html*/`
<div class="spine-player-slider"> <div class="spine-player-slider">
@ -188,7 +190,7 @@
up: (x, y) => { up: (x, y) => {
dragging = false; dragging = false;
let percentage = x / this.slider.clientWidth; let percentage = x / this.slider.clientWidth;
percentage = Math.max(0, Math.min(percentage, 1)); percentage = percentage = Math.max(0, Math.min(percentage, 1));
this.setValue(x / this.slider.clientWidth); this.setValue(x / this.slider.clientWidth);
if (this.change) this.change(percentage); if (this.change) this.change(percentage);
}, },
@ -196,23 +198,34 @@
if (dragging) { if (dragging) {
let percentage = x / this.slider.clientWidth; let percentage = x / this.slider.clientWidth;
percentage = Math.max(0, Math.min(percentage, 1)); percentage = Math.max(0, Math.min(percentage, 1));
this.setValue(x / this.slider.clientWidth); percentage = this.setValue(x / this.slider.clientWidth);
if (this.change) this.change(percentage); if (this.change) this.change(percentage);
} }
}, },
dragged: (x, y) => { dragged: (x, y) => {
let percentage = x / this.slider.clientWidth; let percentage = x / this.slider.clientWidth;
percentage = Math.max(0, Math.min(percentage, 1)); percentage = Math.max(0, Math.min(percentage, 1));
this.setValue(x / this.slider.clientWidth); percentage = this.setValue(x / this.slider.clientWidth);
if (this.change) this.change(percentage); if (this.change) this.change(percentage);
} }
}); });
return this.slider; return this.slider;
} }
setValue(percentage: number) { setValue(percentage: number): number {
percentage = Math.max(0, Math.min(1, percentage)); percentage = Math.max(0, Math.min(1, percentage));
if (this.snaps > 0) {
let modulo = percentage % (1 / this.snaps);
// floor
if (modulo < (1 / this.snaps) * this.snapPercentage) {
percentage = percentage - modulo;
} else if (modulo > (1 / this.snaps) - (1 / this.snaps) * this.snapPercentage) {
percentage = percentage - modulo + (1 / this.snaps);
}
percentage = Math.max(0, Math.min(1, percentage));
}
this.value.style.width = "" + (percentage * 100) + "%"; this.value.style.width = "" + (percentage * 100) + "%";
return percentage;
} }
} }
@ -228,6 +241,8 @@
private canvas: HTMLCanvasElement; private canvas: HTMLCanvasElement;
private timelineSlider: Slider; private timelineSlider: Slider;
private playButton: HTMLElement; private playButton: HTMLElement;
private skinButton: HTMLElement;
private animationButton: HTMLElement;
private context: spine.webgl.ManagedWebGLRenderingContext; private context: spine.webgl.ManagedWebGLRenderingContext;
private loadingScreen: spine.webgl.LoadingScreen; private loadingScreen: spine.webgl.LoadingScreen;
@ -303,7 +318,7 @@
<div class="spine-player"> <div class="spine-player">
<canvas class="spine-player-canvas"></canvas> <canvas class="spine-player-canvas"></canvas>
<div class="spine-player-error spine-player-hidden"></div> <div class="spine-player-error spine-player-hidden"></div>
<div class="spine-player-controls spine-player-popup-parent"> <div class="spine-player-controls spine-player-popup-parent hidden">
<div class="spine-player-timeline"> <div class="spine-player-timeline">
</div> </div>
<div class="spine-player-buttons"> <div class="spine-player-buttons">
@ -357,8 +372,8 @@
timeline.appendChild(this.timelineSlider.render()); timeline.appendChild(this.timelineSlider.render());
this.playButton = findWithId(dom, "spine-player-button-play-pause")[0]; this.playButton = findWithId(dom, "spine-player-button-play-pause")[0];
let speedButton = findWithId(dom, "spine-player-button-speed")[0]; let speedButton = findWithId(dom, "spine-player-button-speed")[0];
let animationButton = findWithId(dom, "spine-player-button-animation")[0]; this.animationButton = findWithId(dom, "spine-player-button-animation")[0];
let skinButton = findWithId(dom, "spine-player-button-skin")[0]; this.skinButton = findWithId(dom, "spine-player-button-skin")[0];
let settingsButton = findWithId(dom, "spine-player-button-settings")[0]; let settingsButton = findWithId(dom, "spine-player-button-settings")[0];
let fullscreenButton = findWithId(dom, "spine-player-button-fullscreen")[0]; let fullscreenButton = findWithId(dom, "spine-player-button-fullscreen")[0];
@ -371,11 +386,11 @@
this.showSpeedDialog(); this.showSpeedDialog();
} }
animationButton.onclick = () => { this.animationButton.onclick = () => {
this.showAnimationsDialog(); this.showAnimationsDialog();
} }
skinButton.onclick = () => { this.skinButton.onclick = () => {
this.showSkinsDialog(); this.showSkinsDialog();
} }
@ -404,8 +419,6 @@
this.drawFrame(false); this.drawFrame(false);
} }
if (!config.showControls) findWithClass(dom, "spine-player-controls ")[0].classList.add("spine-player-hidden");
return dom; return dom;
} }
@ -424,7 +437,7 @@
</div> </div>
`); `);
let sliderParent = findWithClass(popup.dom, "spine-player-speed-slider")[0]; let sliderParent = findWithClass(popup.dom, "spine-player-speed-slider")[0];
let slider = new Slider(); let slider = new Slider(2);
sliderParent.appendChild(slider.render()); sliderParent.appendChild(slider.render());
slider.setValue(this.speed / 2); slider.setValue(this.speed / 2);
slider.change = (percentage) => { slider.change = (percentage) => {
@ -532,14 +545,14 @@
rows.appendChild(row); rows.appendChild(row);
}; };
makeItem("Show bones", "bones"); makeItem("Bones", "bones");
makeItem("Show regions", "regions"); makeItem("Regions", "regions");
makeItem("Show meshes", "meshes"); makeItem("Meshes", "meshes");
makeItem("Show bounds", "bounds"); makeItem("Bounds", "bounds");
makeItem("Show paths", "paths"); makeItem("Paths", "paths");
makeItem("Show clipping", "clipping"); makeItem("Clipping", "clipping");
makeItem("Show points", "points"); makeItem("Points", "points");
makeItem("Show hulls", "hulls"); makeItem("Hulls", "hulls");
popup.show(); popup.show();
} }
@ -580,9 +593,10 @@
this.animationState.update(delta); this.animationState.update(delta);
this.animationState.apply(this.skeleton); this.animationState.apply(this.skeleton);
this.skeleton.updateWorldTransform();
} }
this.skeleton.updateWorldTransform();
let viewportSize = this.scale(this.config.viewport.width, this.config.viewport.height, this.canvas.width, this.canvas.height); let viewportSize = this.scale(this.config.viewport.width, this.config.viewport.height, this.canvas.width, this.canvas.height);
this.sceneRenderer.camera.zoom = this.config.viewport.width / viewportSize.x; this.sceneRenderer.camera.zoom = this.config.viewport.width / viewportSize.x;
@ -720,12 +734,6 @@
} }
// Setup the animations after viewport, so default bounds don't get messed up. // Setup the animations after viewport, so default bounds don't get messed up.
if (!this.config.animation) {
if (skeletonData.animations.length > 0) {
this.config.animation = skeletonData.animations[0].name;
}
}
if (this.config.animations && this.config.animations.length > 0) { if (this.config.animations && this.config.animations.length > 0) {
this.config.animations.forEach(animation => { this.config.animations.forEach(animation => {
if (!this.skeleton.data.findAnimation(animation)) { if (!this.skeleton.data.findAnimation(animation)) {
@ -733,6 +741,16 @@
return; return;
} }
}); });
if (!this.config.animation) {
this.config.animation = this.config.animations[0];
}
}
if (!this.config.animation) {
if (skeletonData.animations.length > 0) {
this.config.animation = skeletonData.animations[0].name;
}
} }
if(this.config.animation) { if(this.config.animation) {
@ -755,6 +773,10 @@
// Setup the input processor and controllable bones // Setup the input processor and controllable bones
this.setupInput(); this.setupInput();
// Hide skin and animation if there's only the default skin / no animation
if (skeletonData.skins.length == 1) this.skinButton.classList.add("spine-player-hidden");
if (skeletonData.animations.length == 1) this.animationButton.classList.add("spine-player-hidden");
this.config.success(this); this.config.success(this);
this.loaded = true; this.loaded = true;
} }
@ -780,9 +802,11 @@
target = bone; target = bone;
} }
} }
handleHover();
}, },
up: (x, y) => { up: (x, y) => {
target = null; target = null;
handleHover();
}, },
dragged: (x, y) => { dragged: (x, y) => {
if (target != null) { if (target != null) {
@ -796,6 +820,7 @@
target.y = coords.y - skeleton.y; target.y = coords.y - skeleton.y;
} }
} }
handleHover();
}, },
moved: (x, y) => { moved: (x, y) => {
for (var i = 0; i < controlBones.length; i++) { for (var i = 0; i < controlBones.length; i++) {
@ -808,8 +833,42 @@
selectedBones[i] = null; selectedBones[i] = null;
} }
} }
handleHover();
} }
}); });
// For the manual hover to work, we need to disable
// hidding the controls if the mouse/touch entered
// the clickable area of a child of the controls
let mouseOverChildren = false;
canvas.onmouseover = (ev) => {
mouseOverChildren = false;
}
canvas.onmouseout = (ev) => {
if (ev.relatedTarget == null) {
mouseOverChildren = false;
} else {
mouseOverChildren = isContained(this.dom, (ev.relatedTarget as any));
}
}
let cancelId = 0;
let handleHover = () => {
if (!this.config.showControls) return;
clearTimeout(cancelId);
this.playerControls.classList.remove("hidden");
this.playerControls.classList.add("visible");
let remove = () => {
let popup = findWithClass(this.dom, "spine-player-popup");
if (popup.length == 0 && !mouseOverChildren) {
this.playerControls.classList.remove("visible");
this.playerControls.classList.add("hidden");
} else {
cancelId = setTimeout(remove, 1000);
}
};
cancelId = setTimeout(remove, 1000);
}
} }
private play () { private play () {