mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-20 01:06:00 +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.
|
||||
*****************************************************************************/
|
||||
|
||||
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 { BlendingModeSpineToC3, type C3TextureEditor, type C3TextureRuntime } from "./C3Texture";
|
||||
|
||||
@ -40,6 +40,7 @@ abstract class C3SkeletonRenderer<
|
||||
Texture extends C3Texture,
|
||||
> extends SkeletonRendererCore {
|
||||
|
||||
private command?: RenderCommand;
|
||||
private tempVertices = new Float32Array(4096);
|
||||
private tempColors = new Float32Array(4096);
|
||||
private tempPoint = new Vector2();
|
||||
@ -53,10 +54,15 @@ abstract class C3SkeletonRenderer<
|
||||
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;
|
||||
|
||||
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) {
|
||||
const { numVertices, positions, uvs, colors, indices, numIndices, blendMode } = command;
|
||||
|
||||
@ -70,11 +76,11 @@ abstract class C3SkeletonRenderer<
|
||||
|
||||
for (let i = 0; i < numVertices; i++) {
|
||||
const srcIndex = i * 2;
|
||||
const { x, y } = matrix.skeletonToGame(positions[srcIndex], positions[srcIndex + 1]);
|
||||
|
||||
const dstIndex = i * 3;
|
||||
vertices[dstIndex] = x;
|
||||
vertices[dstIndex + 1] = y;
|
||||
const x = positions[srcIndex];
|
||||
const y = positions[srcIndex + 1];
|
||||
vertices[dstIndex] = a * x + c * y + tx;
|
||||
vertices[dstIndex + 1] = b * x + d * y + ty;
|
||||
vertices[dstIndex + 2] = 0;
|
||||
|
||||
const color = colors[i];
|
||||
|
||||
@ -19,7 +19,7 @@ class SpineC3Instance extends globalThis.ISDKWorldInstanceBase {
|
||||
propDebugSkeleton = false;
|
||||
|
||||
isFlippedX = false;
|
||||
isPlaying = true;
|
||||
isPlaying = false;
|
||||
animationSpeed = 1.0;
|
||||
physicsMode = spine.Physics.update;
|
||||
customSkins: Record<string, Skin> = {};
|
||||
@ -111,12 +111,19 @@ class SpineC3Instance extends globalThis.ISDKWorldInstanceBase {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.isPlaying) return;
|
||||
this.matrix.update(
|
||||
this.x + this.propOffsetX,
|
||||
this.y + this.propOffsetY,
|
||||
this.angle + this.propOffsetAngle);
|
||||
|
||||
this.update(this.dt);
|
||||
this.runtime.sdk.updateRender();
|
||||
if (this.isPlaying) {
|
||||
this.update(this.dt);
|
||||
this.runtime.sdk.updateRender();
|
||||
}
|
||||
}
|
||||
|
||||
private fromUpdate = false;
|
||||
|
||||
private update (delta: number) {
|
||||
const { state, skeleton, animationSpeed, physicsMode, matrix } = this;
|
||||
|
||||
@ -126,16 +133,14 @@ class SpineC3Instance extends globalThis.ISDKWorldInstanceBase {
|
||||
state.update(adjustedDelta);
|
||||
skeleton.update(adjustedDelta);
|
||||
state.apply(skeleton);
|
||||
matrix.update(
|
||||
this.x + this.propOffsetX,
|
||||
this.y + this.propOffsetY,
|
||||
this.angle + this.propOffsetAngle);
|
||||
|
||||
this.updateHandles(skeleton, matrix);
|
||||
|
||||
skeleton.updateWorldTransform(physicsMode);
|
||||
|
||||
this.updateBoneFollowers();
|
||||
this.updateBoneFollowers(matrix);
|
||||
|
||||
this.fromUpdate = true;
|
||||
}
|
||||
|
||||
_draw (renderer: IRenderer) {
|
||||
@ -148,7 +153,8 @@ class SpineC3Instance extends globalThis.ISDKWorldInstanceBase {
|
||||
if (!skeleton) return;
|
||||
|
||||
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));
|
||||
this.renderDragHandles();
|
||||
@ -187,6 +193,7 @@ class SpineC3Instance extends globalThis.ISDKWorldInstanceBase {
|
||||
this.runtime.addEventListener("pointermove", this.dragHandleMove);
|
||||
this.runtime.addEventListener("pointerup", this.dragHandleUp);
|
||||
}
|
||||
this.isPlaying = true;
|
||||
}
|
||||
|
||||
private dragHandleDown = (event: ConstructPointerEvent) => {
|
||||
@ -394,6 +401,7 @@ class SpineC3Instance extends globalThis.ISDKWorldInstanceBase {
|
||||
|
||||
if (this.propAnimation) {
|
||||
this.setAnimation(0, this.propAnimation, true);
|
||||
this.isPlaying = true;
|
||||
}
|
||||
|
||||
this._setSkin();
|
||||
@ -402,6 +410,7 @@ class SpineC3Instance extends globalThis.ISDKWorldInstanceBase {
|
||||
this.skeleton.scaleY = this.propScaleY;
|
||||
|
||||
this.update(0);
|
||||
this.runtime.sdk.updateRender();
|
||||
|
||||
this.skeletonLoaded = true;
|
||||
this._trigger(C3.Plugins.EsotericSoftware_SpineConstruct3.Cnds.OnSkeletonLoaded);
|
||||
@ -582,7 +591,6 @@ class SpineC3Instance extends globalThis.ISDKWorldInstanceBase {
|
||||
}
|
||||
|
||||
skeleton.setupPose();
|
||||
this.update(0);
|
||||
}
|
||||
|
||||
public createCustomSkin (skinName: string) {
|
||||
@ -691,13 +699,14 @@ class SpineC3Instance extends globalThis.ISDKWorldInstanceBase {
|
||||
}
|
||||
|
||||
this.boneFollowers.set(boneName, { uid, offsetX, offsetY, offsetAngle });
|
||||
this.isPlaying = true;
|
||||
}
|
||||
|
||||
public detachInstanceFromBone (boneName: string) {
|
||||
this.boneFollowers.delete(boneName);
|
||||
}
|
||||
|
||||
private updateBoneFollowers () {
|
||||
private updateBoneFollowers (matrix: C3Matrix) {
|
||||
if (this.boneFollowers.size === 0) return;
|
||||
|
||||
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;
|
||||
if (!instance) continue;
|
||||
|
||||
const { x, y } = this.matrix.boneToGame(bone);
|
||||
const { x, y } = matrix.boneToGame(bone);
|
||||
const boneRotation = bone.applied.getWorldRotationX();
|
||||
|
||||
// Apply rotation to offset
|
||||
|
||||
@ -292,7 +292,7 @@ export class SkeletonRendererCore {
|
||||
|
||||
// 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
|
||||
interface RenderCommand {
|
||||
export interface RenderCommand {
|
||||
positions: Float32Array;
|
||||
uvs: Float32Array;
|
||||
colors: Uint32Array;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user