mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-20 09:16:01 +08:00
Reuse previous render command, if game object not updated.
This commit is contained in:
parent
546c9f8a6b
commit
4e2d01d67a
@ -27,7 +27,7 @@
|
|||||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
import { type BlendMode, type Bone, ClippingAttachment, MathUtils, MeshAttachment, PathAttachment, RegionAttachment, type Skeleton, SkeletonRendererCore, Utils, Vector2 } from "@esotericsoftware/spine-core";
|
import { type BlendMode, type Bone, ClippingAttachment, MathUtils, MeshAttachment, PathAttachment, RegionAttachment, RenderCommand, type Skeleton, SkeletonRendererCore, Utils, Vector2 } from "@esotericsoftware/spine-core";
|
||||||
import type { C3Matrix } from "./C3Matrix";
|
import type { C3Matrix } from "./C3Matrix";
|
||||||
import { BlendingModeSpineToC3, type C3TextureEditor, type C3TextureRuntime } from "./C3Texture";
|
import { BlendingModeSpineToC3, type C3TextureEditor, type C3TextureRuntime } from "./C3Texture";
|
||||||
|
|
||||||
@ -40,6 +40,7 @@ abstract class C3SkeletonRenderer<
|
|||||||
Texture extends C3Texture,
|
Texture extends C3Texture,
|
||||||
> extends SkeletonRendererCore {
|
> extends SkeletonRendererCore {
|
||||||
|
|
||||||
|
private command?: RenderCommand;
|
||||||
private tempVertices = new Float32Array(4096);
|
private tempVertices = new Float32Array(4096);
|
||||||
private tempColors = new Float32Array(4096);
|
private tempColors = new Float32Array(4096);
|
||||||
private tempPoint = new Vector2();
|
private tempPoint = new Vector2();
|
||||||
@ -53,10 +54,15 @@ abstract class C3SkeletonRenderer<
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
draw (skeleton: Skeleton, inColors: [number, number, number], opacity = 1) {
|
draw (skeleton: Skeleton, inColors: [number, number, number], opacity = 1, isPlaying = true, fromUpdate = true) {
|
||||||
const { matrix, inv255 } = this;
|
const { matrix, inv255 } = this;
|
||||||
|
|
||||||
let command = this.render(skeleton, true, [...inColors, opacity]);
|
this.command = (isPlaying || !this.command)
|
||||||
|
? this.render(skeleton, true, [...inColors, opacity])
|
||||||
|
: this.command;
|
||||||
|
let command = this.command;
|
||||||
|
|
||||||
|
const { a, b, c, d, tx, ty } = matrix;
|
||||||
while (command) {
|
while (command) {
|
||||||
const { numVertices, positions, uvs, colors, indices, numIndices, blendMode } = command;
|
const { numVertices, positions, uvs, colors, indices, numIndices, blendMode } = command;
|
||||||
|
|
||||||
@ -70,11 +76,11 @@ abstract class C3SkeletonRenderer<
|
|||||||
|
|
||||||
for (let i = 0; i < numVertices; i++) {
|
for (let i = 0; i < numVertices; i++) {
|
||||||
const srcIndex = i * 2;
|
const srcIndex = i * 2;
|
||||||
const { x, y } = matrix.skeletonToGame(positions[srcIndex], positions[srcIndex + 1]);
|
|
||||||
|
|
||||||
const dstIndex = i * 3;
|
const dstIndex = i * 3;
|
||||||
vertices[dstIndex] = x;
|
const x = positions[srcIndex];
|
||||||
vertices[dstIndex + 1] = y;
|
const y = positions[srcIndex + 1];
|
||||||
|
vertices[dstIndex] = a * x + c * y + tx;
|
||||||
|
vertices[dstIndex + 1] = b * x + d * y + ty;
|
||||||
vertices[dstIndex + 2] = 0;
|
vertices[dstIndex + 2] = 0;
|
||||||
|
|
||||||
const color = colors[i];
|
const color = colors[i];
|
||||||
|
|||||||
@ -19,7 +19,7 @@ class SpineC3Instance extends globalThis.ISDKWorldInstanceBase {
|
|||||||
propDebugSkeleton = false;
|
propDebugSkeleton = false;
|
||||||
|
|
||||||
isFlippedX = false;
|
isFlippedX = false;
|
||||||
isPlaying = true;
|
isPlaying = false;
|
||||||
animationSpeed = 1.0;
|
animationSpeed = 1.0;
|
||||||
physicsMode = spine.Physics.update;
|
physicsMode = spine.Physics.update;
|
||||||
customSkins: Record<string, Skin> = {};
|
customSkins: Record<string, Skin> = {};
|
||||||
@ -111,11 +111,18 @@ class SpineC3Instance extends globalThis.ISDKWorldInstanceBase {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.isPlaying) return;
|
this.matrix.update(
|
||||||
|
this.x + this.propOffsetX,
|
||||||
|
this.y + this.propOffsetY,
|
||||||
|
this.angle + this.propOffsetAngle);
|
||||||
|
|
||||||
|
if (this.isPlaying) {
|
||||||
this.update(this.dt);
|
this.update(this.dt);
|
||||||
this.runtime.sdk.updateRender();
|
this.runtime.sdk.updateRender();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fromUpdate = false;
|
||||||
|
|
||||||
private update (delta: number) {
|
private update (delta: number) {
|
||||||
const { state, skeleton, animationSpeed, physicsMode, matrix } = this;
|
const { state, skeleton, animationSpeed, physicsMode, matrix } = this;
|
||||||
@ -126,16 +133,14 @@ class SpineC3Instance extends globalThis.ISDKWorldInstanceBase {
|
|||||||
state.update(adjustedDelta);
|
state.update(adjustedDelta);
|
||||||
skeleton.update(adjustedDelta);
|
skeleton.update(adjustedDelta);
|
||||||
state.apply(skeleton);
|
state.apply(skeleton);
|
||||||
matrix.update(
|
|
||||||
this.x + this.propOffsetX,
|
|
||||||
this.y + this.propOffsetY,
|
|
||||||
this.angle + this.propOffsetAngle);
|
|
||||||
|
|
||||||
this.updateHandles(skeleton, matrix);
|
this.updateHandles(skeleton, matrix);
|
||||||
|
|
||||||
skeleton.updateWorldTransform(physicsMode);
|
skeleton.updateWorldTransform(physicsMode);
|
||||||
|
|
||||||
this.updateBoneFollowers();
|
this.updateBoneFollowers(matrix);
|
||||||
|
|
||||||
|
this.fromUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_draw (renderer: IRenderer) {
|
_draw (renderer: IRenderer) {
|
||||||
@ -148,7 +153,8 @@ class SpineC3Instance extends globalThis.ISDKWorldInstanceBase {
|
|||||||
if (!skeleton) return;
|
if (!skeleton) return;
|
||||||
|
|
||||||
this.skeletonRenderer ||= new spine.C3RendererRuntime(renderer, this.matrix);
|
this.skeletonRenderer ||= new spine.C3RendererRuntime(renderer, this.matrix);
|
||||||
this.skeletonRenderer.draw(skeleton, this.colorRgb, this.opacity);
|
this.skeletonRenderer.draw(skeleton, this.colorRgb, this.opacity, this.isPlaying, this.fromUpdate);
|
||||||
|
this.fromUpdate = false;
|
||||||
|
|
||||||
if (this.propDebugSkeleton) this.skeletonRenderer.drawDebug(skeleton, this.x, this.y, this.getBoundingQuad(false));
|
if (this.propDebugSkeleton) this.skeletonRenderer.drawDebug(skeleton, this.x, this.y, this.getBoundingQuad(false));
|
||||||
this.renderDragHandles();
|
this.renderDragHandles();
|
||||||
@ -187,6 +193,7 @@ class SpineC3Instance extends globalThis.ISDKWorldInstanceBase {
|
|||||||
this.runtime.addEventListener("pointermove", this.dragHandleMove);
|
this.runtime.addEventListener("pointermove", this.dragHandleMove);
|
||||||
this.runtime.addEventListener("pointerup", this.dragHandleUp);
|
this.runtime.addEventListener("pointerup", this.dragHandleUp);
|
||||||
}
|
}
|
||||||
|
this.isPlaying = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private dragHandleDown = (event: ConstructPointerEvent) => {
|
private dragHandleDown = (event: ConstructPointerEvent) => {
|
||||||
@ -394,6 +401,7 @@ class SpineC3Instance extends globalThis.ISDKWorldInstanceBase {
|
|||||||
|
|
||||||
if (this.propAnimation) {
|
if (this.propAnimation) {
|
||||||
this.setAnimation(0, this.propAnimation, true);
|
this.setAnimation(0, this.propAnimation, true);
|
||||||
|
this.isPlaying = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._setSkin();
|
this._setSkin();
|
||||||
@ -402,6 +410,7 @@ class SpineC3Instance extends globalThis.ISDKWorldInstanceBase {
|
|||||||
this.skeleton.scaleY = this.propScaleY;
|
this.skeleton.scaleY = this.propScaleY;
|
||||||
|
|
||||||
this.update(0);
|
this.update(0);
|
||||||
|
this.runtime.sdk.updateRender();
|
||||||
|
|
||||||
this.skeletonLoaded = true;
|
this.skeletonLoaded = true;
|
||||||
this._trigger(C3.Plugins.EsotericSoftware_SpineConstruct3.Cnds.OnSkeletonLoaded);
|
this._trigger(C3.Plugins.EsotericSoftware_SpineConstruct3.Cnds.OnSkeletonLoaded);
|
||||||
@ -582,7 +591,6 @@ class SpineC3Instance extends globalThis.ISDKWorldInstanceBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
skeleton.setupPose();
|
skeleton.setupPose();
|
||||||
this.update(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public createCustomSkin (skinName: string) {
|
public createCustomSkin (skinName: string) {
|
||||||
@ -691,13 +699,14 @@ class SpineC3Instance extends globalThis.ISDKWorldInstanceBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.boneFollowers.set(boneName, { uid, offsetX, offsetY, offsetAngle });
|
this.boneFollowers.set(boneName, { uid, offsetX, offsetY, offsetAngle });
|
||||||
|
this.isPlaying = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public detachInstanceFromBone (boneName: string) {
|
public detachInstanceFromBone (boneName: string) {
|
||||||
this.boneFollowers.delete(boneName);
|
this.boneFollowers.delete(boneName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateBoneFollowers () {
|
private updateBoneFollowers (matrix: C3Matrix) {
|
||||||
if (this.boneFollowers.size === 0) return;
|
if (this.boneFollowers.size === 0) return;
|
||||||
|
|
||||||
for (const [boneName, follower] of this.boneFollowers) {
|
for (const [boneName, follower] of this.boneFollowers) {
|
||||||
@ -707,7 +716,7 @@ class SpineC3Instance extends globalThis.ISDKWorldInstanceBase {
|
|||||||
const instance = this.runtime.getInstanceByUid(follower.uid) as IWorldInstance;
|
const instance = this.runtime.getInstanceByUid(follower.uid) as IWorldInstance;
|
||||||
if (!instance) continue;
|
if (!instance) continue;
|
||||||
|
|
||||||
const { x, y } = this.matrix.boneToGame(bone);
|
const { x, y } = matrix.boneToGame(bone);
|
||||||
const boneRotation = bone.applied.getWorldRotationX();
|
const boneRotation = bone.applied.getWorldRotationX();
|
||||||
|
|
||||||
// Apply rotation to offset
|
// Apply rotation to offset
|
||||||
|
|||||||
@ -292,7 +292,7 @@ export class SkeletonRendererCore {
|
|||||||
|
|
||||||
// values with under score is the original sized array, bigger than necessary
|
// values with under score is the original sized array, bigger than necessary
|
||||||
// values without under score is a view of the orignal array, sized as needed
|
// values without under score is a view of the orignal array, sized as needed
|
||||||
interface RenderCommand {
|
export interface RenderCommand {
|
||||||
positions: Float32Array;
|
positions: Float32Array;
|
||||||
uvs: Float32Array;
|
uvs: Float32Array;
|
||||||
colors: Uint32Array;
|
colors: Uint32Array;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user