[ts][player] Added controllable bones to player.

This commit is contained in:
badlogic 2018-11-08 16:00:23 +01:00
parent fe44bece46
commit 49ba1d2bd9
5 changed files with 11940 additions and 11812 deletions

View File

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

View File

@ -1,7 +1,10 @@
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __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]; };
return extendStatics(d, b);
}
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
@ -9561,6 +9564,8 @@ var spine;
if (config.skins.indexOf(config.skin) < 0)
throw new Error("Default skin " + config.skin + " is not contained in the list of selectable skins.");
}
if (!config.controlBones)
config.controlBones = [];
return config;
};
SpinePlayer.prototype.render = function () {
@ -9743,7 +9748,7 @@ var spine;
var delta = this.time.delta * this.speed;
var animationDuration = this.animationState.getCurrent(0).animation.duration;
this.playTime += delta;
while (this.playTime >= animationDuration) {
while (this.playTime >= animationDuration && animationDuration != 0) {
this.playTime -= animationDuration;
}
this.playTime = Math.max(0, Math.min(this.playTime, animationDuration));
@ -9775,6 +9780,20 @@ var spine;
this.sceneRenderer.skeletonDebugRenderer.drawRegionAttachments = this.config.debug.regions;
this.sceneRenderer.skeletonDebugRenderer.drawMeshTriangles = this.config.debug.meshes;
this.sceneRenderer.drawSkeletonDebug(this.skeleton, this.config.premultipliedAlpha);
var controlBones = this.config.controlBones;
var selectedBones = this.selectedBones;
var skeleton = this.skeleton;
gl.lineWidth(2);
for (var i = 0; i < controlBones.length; i++) {
var bone = skeleton.findBone(controlBones[i]);
if (!bone)
continue;
var colorInner = selectedBones[i] !== null ? SpinePlayer.HOVER_COLOR_INNER : SpinePlayer.NON_HOVER_COLOR_INNER;
var colorOuter = selectedBones[i] !== null ? SpinePlayer.HOVER_COLOR_OUTER : SpinePlayer.NON_HOVER_COLOR_OUTER;
this.sceneRenderer.circle(true, skeleton.x + bone.worldX, skeleton.y + bone.worldY, 20, colorInner);
this.sceneRenderer.circle(false, skeleton.x + bone.worldX, skeleton.y + bone.worldY, 20, colorOuter);
}
gl.lineWidth(1);
this.sceneRenderer.end();
this.sceneRenderer.camera.zoom = 0;
}
@ -9842,8 +9861,65 @@ var spine;
_this.playTime = time;
};
}
this.setupInput();
this.loaded = true;
};
SpinePlayer.prototype.setupInput = function () {
var controlBones = this.config.controlBones;
var selectedBones = this.selectedBones = new Array(this.config.controlBones.length);
var canvas = this.canvas;
var input = new spine.webgl.Input(canvas);
var target = null;
var coords = new spine.webgl.Vector3();
var temp = new spine.webgl.Vector3();
var temp2 = new spine.Vector2();
var skeleton = this.skeleton;
var renderer = this.sceneRenderer;
input.addListener({
down: function (x, y) {
for (var i = 0; i < controlBones.length; i++) {
var bone = skeleton.findBone(controlBones[i]);
if (!bone)
continue;
renderer.camera.screenToWorld(coords.set(x, y, 0), canvas.width, canvas.height);
if (temp.set(skeleton.x + bone.worldX, skeleton.y + bone.worldY, 0).distance(coords) < 30) {
target = bone;
}
}
},
up: function (x, y) {
target = null;
},
dragged: function (x, y) {
if (target != null) {
renderer.camera.screenToWorld(coords.set(x, y, 0), canvas.width, canvas.height);
if (target.parent !== null) {
target.parent.worldToLocal(temp2.set(coords.x - skeleton.x, coords.y - skeleton.y));
target.x = temp2.x;
target.y = temp2.y;
}
else {
target.x = coords.x - skeleton.x;
target.y = coords.y - skeleton.y;
}
}
},
moved: function (x, y) {
for (var i = 0; i < controlBones.length; i++) {
var bone = skeleton.findBone(controlBones[i]);
if (!bone)
continue;
renderer.camera.screenToWorld(coords.set(x, y, 0), canvas.width, canvas.height);
if (temp.set(skeleton.x + bone.worldX, skeleton.y + bone.worldY, 0).distance(coords) < 30) {
selectedBones[i] = bone;
}
else {
selectedBones[i] = null;
}
}
}
});
};
SpinePlayer.prototype.play = function () {
this.paused = false;
this.playButton.classList.remove("spine-player-button-icon-play");
@ -9859,18 +9935,10 @@ var spine;
this.playButton.classList.remove("spine-player-button-icon-pause");
this.playButton.classList.add("spine-player-button-icon-play");
};
SpinePlayer.prototype.resize = function () {
var canvas = this.canvas;
var w = canvas.clientWidth;
var h = canvas.clientHeight;
var devicePixelRatio = window.devicePixelRatio || 1;
if (canvas.width != Math.floor(w * devicePixelRatio) || canvas.height != Math.floor(h * devicePixelRatio)) {
canvas.width = Math.floor(w * devicePixelRatio);
canvas.height = Math.floor(h * devicePixelRatio);
}
this.context.gl.viewport(0, 0, canvas.width, canvas.height);
this.sceneRenderer.camera.setViewport(canvas.width, canvas.height);
};
SpinePlayer.HOVER_COLOR_INNER = new spine.Color(0.478, 0, 0, 0.25);
SpinePlayer.HOVER_COLOR_OUTER = new spine.Color(1, 1, 1, 1);
SpinePlayer.NON_HOVER_COLOR_INNER = new spine.Color(0.478, 0, 0, 0.5);
SpinePlayer.NON_HOVER_COLOR_OUTER = new spine.Color(1, 0, 0, 0.8);
return SpinePlayer;
}());
spine.SpinePlayer = SpinePlayer;

File diff suppressed because one or more lines are too long

View File

@ -277,25 +277,10 @@ body {
</body>
<script>
new spine.SpinePlayer(document.getElementById("container"), {
jsonUrl: "assets/raptor-pro.json",
atlasUrl: "assets/raptor.atlas",
animation: "walk",
animations: ["walk", "roar", "jump"],
skin: "default",
skins: ["default"],
backgroundColor: "#ff00ff",
backgroundImage: {
url: "assets/spineboy.png",
x: 0,
y: 0,
width: 300,
height: 200
},
debug: {
bones: true,
regions: true,
meshes: true,
}
jsonUrl: "assets/spineboy-pro.json",
atlasUrl: "assets/spineboy.atlas",
controlBones: ["root"],
backgroundColor: "#cccccc"
});
</script>
</body>

View File

@ -62,6 +62,7 @@
height: number
}
premultipliedAlpha: boolean
controlBones: string[]
success: (widget: SpineWidget) => void
error: (widget: SpineWidget, msg: string) => void
}
@ -181,6 +182,11 @@
}
export class SpinePlayer {
static HOVER_COLOR_INNER = new spine.Color(0.478, 0, 0, 0.25);
static HOVER_COLOR_OUTER = new spine.Color(1, 1, 1, 1);
static NON_HOVER_COLOR_INNER = new spine.Color(0.478, 0, 0, 0.5);
static NON_HOVER_COLOR_OUTER = new spine.Color(1, 0, 0, 0.8);
private sceneRenderer: spine.webgl.SceneRenderer;
private dom: HTMLElement;
private playerControls: HTMLElement;
@ -200,6 +206,8 @@
private playTime = 0;
private speed = 1;
private selectedBones: Bone[];
constructor(parent: HTMLElement, private config: SpinePlayerConfig) {
this.config = this.validateConfig(config);
parent.appendChild(this.render());
@ -241,6 +249,7 @@
if (config.skins.indexOf(config.skin) < 0) throw new Error("Default skin " + config.skin + " is not contained in the list of selectable skins.");
}
if (!config.controlBones) config.controlBones = [];
return config;
}
@ -338,6 +347,8 @@
this.drawFrame(false);
}
// Setup input handler for control bones and pan/zoom
return dom;
}
@ -504,7 +515,7 @@
let animationDuration = this.animationState.getCurrent(0).animation.duration;
this.playTime += delta;
while (this.playTime >= animationDuration) {
while (this.playTime >= animationDuration && animationDuration != 0) {
this.playTime -= animationDuration;
}
this.playTime = Math.max(0, Math.min(this.playTime, animationDuration));
@ -544,6 +555,21 @@
this.sceneRenderer.skeletonDebugRenderer.drawMeshTriangles = this.config.debug.meshes;
this.sceneRenderer.drawSkeletonDebug(this.skeleton, this.config.premultipliedAlpha);
// Render the selected bones
let controlBones = this.config.controlBones;
let selectedBones = this.selectedBones;
let skeleton = this.skeleton;
gl.lineWidth(2);
for (var i = 0; i < controlBones.length; i++) {
var bone = skeleton.findBone(controlBones[i]);
if (!bone) continue;
var colorInner = selectedBones[i] !== null ? SpinePlayer.HOVER_COLOR_INNER : SpinePlayer.NON_HOVER_COLOR_INNER;
var colorOuter = selectedBones[i] !== null ? SpinePlayer.HOVER_COLOR_OUTER : SpinePlayer.NON_HOVER_COLOR_OUTER;
this.sceneRenderer.circle(true, skeleton.x + bone.worldX, skeleton.y + bone.worldY, 20, colorInner);
this.sceneRenderer.circle(false, skeleton.x + bone.worldX, skeleton.y + bone.worldY, 20, colorOuter);
}
gl.lineWidth(1);
this.sceneRenderer.end();
this.sceneRenderer.camera.zoom = 0;
@ -608,6 +634,7 @@
this.config.animation = skeletonData.animations[0].name;
}
}
if(this.config.animation) {
this.play()
this.timelineSlider.change = (percentage) => {
@ -621,9 +648,65 @@
}
}
// Setup the input processor and controllable bones
this.setupInput();
this.loaded = true;
}
setupInput () {
let controlBones = this.config.controlBones;
let selectedBones = this.selectedBones = new Array<Bone>(this.config.controlBones.length);
let canvas = this.canvas;
let input = new spine.webgl.Input(canvas);
var target:Bone = null;
let coords = new spine.webgl.Vector3();
let temp = new spine.webgl.Vector3();
let temp2 = new spine.Vector2();
let skeleton = this.skeleton
let renderer = this.sceneRenderer;
input.addListener({
down: (x, y) => {
for (var i = 0; i < controlBones.length; i++) {
var bone = skeleton.findBone(controlBones[i]);
if (!bone) continue;
renderer.camera.screenToWorld(coords.set(x, y, 0), canvas.width, canvas.height);
if (temp.set(skeleton.x + bone.worldX, skeleton.y + bone.worldY, 0).distance(coords) < 30) {
target = bone;
}
}
},
up: (x, y) => {
target = null;
},
dragged: (x, y) => {
if (target != null) {
renderer.camera.screenToWorld(coords.set(x, y, 0), canvas.width, canvas.height);
if (target.parent !== null) {
target.parent.worldToLocal(temp2.set(coords.x - skeleton.x, coords.y - skeleton.y));
target.x = temp2.x;
target.y = temp2.y;
} else {
target.x = coords.x - skeleton.x;
target.y = coords.y - skeleton.y;
}
}
},
moved: (x, y) => {
for (var i = 0; i < controlBones.length; i++) {
var bone = skeleton.findBone(controlBones[i]);
if (!bone) continue;
renderer.camera.screenToWorld(coords.set(x, y, 0), canvas.width, canvas.height);
if (temp.set(skeleton.x + bone.worldX, skeleton.y + bone.worldY, 0).distance(coords) < 30) {
selectedBones[i] = bone;
} else {
selectedBones[i] = null;
}
}
}
});
}
private play () {
this.paused = false;
this.playButton.classList.remove("spine-player-button-icon-play");
@ -641,20 +724,6 @@
this.playButton.classList.remove("spine-player-button-icon-pause");
this.playButton.classList.add("spine-player-button-icon-play");
}
private resize () {
let canvas = this.canvas;
let w = canvas.clientWidth;
let h = canvas.clientHeight;
var devicePixelRatio = window.devicePixelRatio || 1;
if (canvas.width != Math.floor(w * devicePixelRatio) || canvas.height != Math.floor(h * devicePixelRatio)) {
canvas.width = Math.floor(w * devicePixelRatio);
canvas.height = Math.floor(h * devicePixelRatio);
}
this.context.gl.viewport(0, 0, canvas.width, canvas.height);
this.sceneRenderer.camera.setViewport(canvas.width, canvas.height);
}
}
function isContained(dom: HTMLElement, needle: HTMLElement): boolean {