mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 14:24:53 +08:00
Add pma, wraps and filter management.
This commit is contained in:
parent
235a96ca5c
commit
75f30e297d
@ -65,7 +65,7 @@ export class AssetLoader {
|
||||
await Promise.all(textureAtlas.pages.map(async page => {
|
||||
const texture = await this.loadSpineTextureEditor(page.name, page.pma, instance);
|
||||
if (texture) {
|
||||
const spineTexture = new C3TextureEditor(texture, renderer);
|
||||
const spineTexture = new C3TextureEditor(texture, renderer, page);
|
||||
page.setTexture(spineTexture);
|
||||
}
|
||||
return texture;
|
||||
@ -116,7 +116,7 @@ export class AssetLoader {
|
||||
await Promise.all(textureAtlas.pages.map(async page => {
|
||||
const texture = await this.loadSpineTextureRuntime(page.name, page.pma, instance);
|
||||
if (texture) {
|
||||
const spineTexture = new C3Texture(texture, renderer);
|
||||
const spineTexture = new C3Texture(texture, renderer, page);
|
||||
page.setTexture(spineTexture);
|
||||
}
|
||||
return texture;
|
||||
@ -136,6 +136,7 @@ export class AssetLoader {
|
||||
|
||||
static async createImageBitmapFromBlob (blob: Blob, pma: boolean): Promise<ImageBitmap | null> {
|
||||
try {
|
||||
// pma parameters seems to do not matter here. It matters in C3 Texture creation
|
||||
return createImageBitmap(blob, { premultiplyAlpha: pma ? "none" : "premultiply" });
|
||||
} catch (e) {
|
||||
console.error("Failed to create ImageBitmap from blob:", e);
|
||||
|
||||
@ -27,25 +27,34 @@
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
import { BlendMode, Texture, type TextureFilter, type TextureWrap } from "@esotericsoftware/spine-core";
|
||||
import { BlendMode, Texture, type TextureAtlasPage, TextureFilter, TextureWrap } from "@esotericsoftware/spine-core";
|
||||
|
||||
export class C3TextureEditor extends Texture {
|
||||
texture: SDK.Gfx.IWebGLTexture;
|
||||
renderer: SDK.Gfx.IWebGLRenderer;
|
||||
|
||||
constructor (image: HTMLImageElement | ImageBitmap, renderer: SDK.Gfx.IWebGLRenderer) {
|
||||
constructor (image: HTMLImageElement | ImageBitmap, renderer: SDK.Gfx.IWebGLRenderer, page: TextureAtlasPage) {
|
||||
super(image);
|
||||
this.renderer = renderer;
|
||||
this.texture = renderer.CreateDynamicTexture(image.width, image.height);
|
||||
this.renderer.UpdateTexture(image, this.texture);
|
||||
const options: TextureCreateOptions = {
|
||||
wrapX: toC3TextureWrap(page.uWrap),
|
||||
wrapY: toC3TextureWrap(page.vWrap),
|
||||
sampling: toC3Filter(page.minFilter),
|
||||
mipMap: toC3MipMap(page.minFilter),
|
||||
}
|
||||
this.texture = renderer.CreateDynamicTexture(image.width, image.height, options);
|
||||
this.renderer.UpdateTexture(image, this.texture, { premultiplyAlpha: !page.pma });
|
||||
}
|
||||
|
||||
setFilters (minFilter: TextureFilter, magFilter: TextureFilter) {
|
||||
setFilters () {
|
||||
// cannot change filter after texture creation
|
||||
}
|
||||
|
||||
setWraps (uWrap: TextureWrap, vWrap: TextureWrap) {
|
||||
setWraps () {
|
||||
// cannot change wraps after texture creation
|
||||
}
|
||||
|
||||
|
||||
dispose () {
|
||||
this.renderer.DeleteTexture(this.texture);
|
||||
}
|
||||
@ -55,17 +64,26 @@ export class C3Texture extends Texture {
|
||||
texture: ITexture;
|
||||
renderer: IRenderer;
|
||||
|
||||
constructor (image: HTMLImageElement | ImageBitmap, renderer: IRenderer) {
|
||||
constructor (image: HTMLImageElement | ImageBitmap, renderer: IRenderer, page: TextureAtlasPage) {
|
||||
super(image);
|
||||
this.renderer = renderer;
|
||||
this.texture = renderer.createDynamicTexture(image.width, image.height);
|
||||
this.renderer.updateTexture(image, this.texture);
|
||||
const options: TextureCreateOptions = {
|
||||
wrapX: toC3TextureWrap(page.uWrap),
|
||||
wrapY: toC3TextureWrap(page.vWrap),
|
||||
sampling: toC3Filter(page.minFilter),
|
||||
mipMap: toC3MipMap(page.minFilter),
|
||||
}
|
||||
this.texture = renderer.createDynamicTexture(image.width, image.height, options);
|
||||
this.renderer.updateTexture(image, this.texture, { premultiplyAlpha: !page.pma });
|
||||
}
|
||||
|
||||
setFilters (minFilter: TextureFilter, magFilter: TextureFilter) {
|
||||
|
||||
setFilters () {
|
||||
// cannot change filter after texture creation
|
||||
}
|
||||
|
||||
setWraps (uWrap: TextureWrap, vWrap: TextureWrap) {
|
||||
setWraps () {
|
||||
// cannot change wraps after texture creation
|
||||
}
|
||||
|
||||
dispose () {
|
||||
@ -73,6 +91,49 @@ export class C3Texture extends Texture {
|
||||
}
|
||||
}
|
||||
|
||||
function toC3TextureWrap (wrap: TextureWrap): TextureWrapMode {
|
||||
if (wrap === TextureWrap.ClampToEdge) return "clamp-to-edge";
|
||||
else if (wrap === TextureWrap.MirroredRepeat) return "mirror-repeat";
|
||||
else if (wrap === TextureWrap.Repeat) return "repeat";
|
||||
else throw new Error(`Unknown texture wrap: ${wrap}`);
|
||||
}
|
||||
|
||||
function toC3MipMap (filter: TextureFilter): boolean {
|
||||
switch (filter) {
|
||||
case TextureFilter.MipMap:
|
||||
case TextureFilter.MipMapLinearNearest:
|
||||
case TextureFilter.MipMapNearestLinear:
|
||||
case TextureFilter.MipMapNearestNearest:
|
||||
return true;
|
||||
|
||||
case TextureFilter.Linear:
|
||||
case TextureFilter.Nearest:
|
||||
return false;
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown texture filter: ${filter}`);
|
||||
}
|
||||
}
|
||||
|
||||
function toC3Filter (filter: TextureFilter): TextureSamplingMode {
|
||||
switch (filter) {
|
||||
case TextureFilter.Nearest:
|
||||
case TextureFilter.MipMapNearestNearest:
|
||||
return "nearest";
|
||||
|
||||
case TextureFilter.Linear:
|
||||
case TextureFilter.MipMapLinearNearest:
|
||||
case TextureFilter.MipMapNearestLinear:
|
||||
return "bilinear";
|
||||
|
||||
case TextureFilter.MipMap:
|
||||
case TextureFilter.MipMapLinearLinear:
|
||||
return "trilinear";
|
||||
default:
|
||||
throw new Error(`Unknown texture filter: ${filter}`);
|
||||
}
|
||||
}
|
||||
|
||||
export const BlendingModeSpineToC3: Record<BlendMode, BlendModeParameter> = {
|
||||
[BlendMode.Normal]: "normal",
|
||||
[BlendMode.Additive]: "additive",
|
||||
|
||||
@ -71,8 +71,10 @@ class DrawingInstance extends globalThis.ISDKWorldInstanceBase {
|
||||
return;
|
||||
}
|
||||
|
||||
// workaround to request a redraw: https://github.com/Scirra/Construct-feature-requests/issues/615
|
||||
this.x++;
|
||||
this.x--;
|
||||
|
||||
this.update(this.dt);
|
||||
}
|
||||
|
||||
@ -224,8 +226,12 @@ class DrawingInstance extends globalThis.ISDKWorldInstanceBase {
|
||||
const offsetY = this.y + this.propOffsetY;
|
||||
const offsetAngle = this.angle + this.propOffsetAngle;
|
||||
|
||||
const cos = Math.cos(offsetAngle);
|
||||
const sin = Math.sin(offsetAngle);
|
||||
let cos = 0;
|
||||
let sin = 0;
|
||||
if (offsetAngle) {
|
||||
cos = Math.cos(offsetAngle);
|
||||
sin = Math.sin(offsetAngle);
|
||||
}
|
||||
while (command) {
|
||||
const { numVertices, positions, uvs, colors, indices, numIndices, blendMode } = command;
|
||||
|
||||
@ -236,10 +242,17 @@ class DrawingInstance extends globalThis.ISDKWorldInstanceBase {
|
||||
const dstIndex = i * 3;
|
||||
const x = positions[srcIndex];
|
||||
const y = positions[srcIndex + 1];
|
||||
vertices[dstIndex] = x * cos - y * sin + offsetX;
|
||||
vertices[dstIndex + 1] = x * sin + y * cos + offsetY;
|
||||
|
||||
if (offsetAngle) {
|
||||
vertices[dstIndex] = x * cos - y * sin + offsetX;
|
||||
vertices[dstIndex + 1] = x * sin + y * cos + offsetY;
|
||||
} else {
|
||||
vertices[dstIndex] = x + offsetX;
|
||||
vertices[dstIndex + 1] = y + offsetY;
|
||||
}
|
||||
vertices[dstIndex + 2] = 0;
|
||||
|
||||
|
||||
// there's something wrong with the hand after adding the colors on spineboy portal animation
|
||||
const color = colors[i];
|
||||
const colorDst = i * 4;
|
||||
@ -254,6 +267,7 @@ class DrawingInstance extends globalThis.ISDKWorldInstanceBase {
|
||||
renderer.drawMesh(
|
||||
vertices.subarray(0, numVertices * 3),
|
||||
uvs.subarray(0, numVertices * 2),
|
||||
// workaround for this bug: https://github.com/Scirra/Construct-bugs/issues/8746
|
||||
this.padUint16ArrayForWebGPU(indices.subarray(0, numIndices)),
|
||||
c3colors.subarray(0, numVertices * 4),
|
||||
);
|
||||
|
||||
@ -136,10 +136,10 @@ class MyDrawingInstance extends SDK.IWorldInstanceBase {
|
||||
iRenderer.SetTextureFillMode();
|
||||
iRenderer.SetTexture(command.texture.texture);
|
||||
|
||||
const padded = this.padUint16ArrayForWebGPU(indices.subarray(0, numIndices));
|
||||
iRenderer.DrawMesh(
|
||||
vertices.subarray(0, numVertices * 3),
|
||||
uvs.subarray(0, numVertices * 2),
|
||||
// workaround for this bug: https://github.com/Scirra/Construct-bugs/issues/8746
|
||||
this.padUint16ArrayForWebGPU(indices.subarray(0, numIndices)),
|
||||
);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user