支持spine4.3

This commit is contained in:
tianmo committed 2026-09-02 13:53:12 +08:00
1 parent 63e4f61631
commit 0656684a92
206 files changed
+100597 -1320

No files matched your search

+270
View File
@@ -0,0 +1,270 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
import { TextureFilter, TextureRegion, TextureWrap } from "./Texture.js";
import { Utils } from "./Utils.js";
export class TextureAtlas {
pages = [];
regions = [];
constructor(atlasText) {
const reader = new TextureAtlasReader(atlasText);
const entry = new Array(4);
const pageFields = {};
pageFields.size = (page) => {
page.width = parseInt(entry[1]);
page.height = parseInt(entry[2]);
};
pageFields.format = () => {
// page.format = Format[tuple[0]]; we don't need format in WebGL
};
pageFields.filter = (page) => {
page.minFilter = Utils.enumValue(TextureFilter, entry[1]);
page.magFilter = Utils.enumValue(TextureFilter, entry[2]);
};
pageFields.repeat = (page) => {
if (entry[1].indexOf('x') !== -1)
page.uWrap = TextureWrap.Repeat;
if (entry[1].indexOf('y') !== -1)
page.vWrap = TextureWrap.Repeat;
};
pageFields.pma = (page) => {
page.pma = entry[1] === "true";
};
var regionFields = {};
regionFields.xy = (region) => {
region.x = parseInt(entry[1]);
region.y = parseInt(entry[2]);
};
regionFields.size = (region) => {
region.width = parseInt(entry[1]);
region.height = parseInt(entry[2]);
};
regionFields.bounds = (region) => {
region.x = parseInt(entry[1]);
region.y = parseInt(entry[2]);
region.width = parseInt(entry[3]);
region.height = parseInt(entry[4]);
};
regionFields.offset = (region) => {
region.offsetX = parseInt(entry[1]);
region.offsetY = parseInt(entry[2]);
};
regionFields.orig = (region) => {
region.originalWidth = parseInt(entry[1]);
region.originalHeight = parseInt(entry[2]);
};
regionFields.offsets = (region) => {
region.offsetX = parseInt(entry[1]);
region.offsetY = parseInt(entry[2]);
region.originalWidth = parseInt(entry[3]);
region.originalHeight = parseInt(entry[4]);
};
regionFields.rotate = (region) => {
const value = entry[1];
if (value === "true")
region.degrees = 90;
else if (value !== "false")
region.degrees = parseInt(value);
};
regionFields.index = (region) => {
region.index = parseInt(entry[1]);
};
let line = reader.readLine();
// Ignore empty lines before first entry.
while (line && line.trim().length === 0)
line = reader.readLine();
// Header entries.
while (true) {
if (!line || line.trim().length === 0)
break;
if (reader.readEntry(entry, line) === 0)
break; // Silently ignore all header fields.
line = reader.readLine();
}
// Page and region entries.
let page = null;
let names = null;
let values = null;
while (true) {
if (line === null)
break;
if (line.trim().length === 0) {
page = null;
line = reader.readLine();
}
else if (!page) {
page = new TextureAtlasPage(line.trim());
while (true) {
if (reader.readEntry(entry, line = reader.readLine()) === 0)
break;
const field = pageFields[entry[0]];
if (field)
field(page);
}
this.pages.push(page);
}
else {
const region = new TextureAtlasRegion(page, line);
while (true) {
const count = reader.readEntry(entry, line = reader.readLine());
if (count === 0)
break;
const field = regionFields[entry[0]];
if (field)
field(region);
else {
if (!names)
names = [];
if (!values)
values = [];
names.push(entry[0]);
const entryValues = [];
for (let i = 0; i < count; i++)
entryValues.push(parseInt(entry[i + 1]));
values.push(entryValues);
}
}
if (region.originalWidth === 0 && region.originalHeight === 0) {
region.originalWidth = region.width;
region.originalHeight = region.height;
}
if (names && names.length > 0 && values && values.length > 0) {
region.names = names;
region.values = values;
names = null;
values = null;
}
region.u = region.x / page.width;
region.v = region.y / page.height;
if (region.degrees === 90) {
region.u2 = (region.x + region.height) / page.width;
region.v2 = (region.y + region.width) / page.height;
}
else {
region.u2 = (region.x + region.width) / page.width;
region.v2 = (region.y + region.height) / page.height;
}
this.regions.push(region);
}
}
}
findRegion(name) {
for (let i = 0; i < this.regions.length; i++) {
if (this.regions[i].name === name) {
return this.regions[i];
}
}
return null;
}
setTextures(assetManager, pathPrefix = "") {
for (const page of this.pages)
page.setTexture(assetManager.get(pathPrefix + page.name));
}
dispose() {
for (let i = 0; i < this.pages.length; i++) {
this.pages[i].texture?.dispose();
}
}
}
class TextureAtlasReader {
lines;
index = 0;
constructor(text) {
this.lines = text.split(/\r\n|\r|\n/);
}
readLine() {
if (this.index >= this.lines.length)
return null;
return this.lines[this.index++];
}
readEntry(entry, line) {
if (!line)
return 0;
line = line.trim();
if (line.length === 0)
return 0;
const colon = line.indexOf(':');
if (colon === -1)
return 0;
entry[0] = line.substr(0, colon).trim();
for (let i = 1, lastMatch = colon + 1;; i++) {
const comma = line.indexOf(',', lastMatch);
if (comma === -1) {
entry[i] = line.substr(lastMatch).trim();
return i;
}
entry[i] = line.substr(lastMatch, comma - lastMatch).trim();
lastMatch = comma + 1;
if (i === 4)
return 4;
}
}
}
export class TextureAtlasPage {
name;
minFilter = TextureFilter.Nearest;
magFilter = TextureFilter.Nearest;
uWrap = TextureWrap.ClampToEdge;
vWrap = TextureWrap.ClampToEdge;
texture = null;
width = 0;
height = 0;
pma = false;
regions = [];
constructor(name) {
this.name = name;
}
setTexture(texture) {
this.texture = texture;
texture.setFilters(this.minFilter, this.magFilter);
texture.setWraps(this.uWrap, this.vWrap);
for (const region of this.regions)
region.texture = texture;
}
}
export class TextureAtlasRegion extends TextureRegion {
page;
name;
x = 0;
y = 0;
offsetX = 0;
offsetY = 0;
originalWidth = 0;
originalHeight = 0;
index = 0;
degrees = 0;
names = null;
values = null;
constructor(page, name) {
super();
this.page = page;
this.name = name;
page.regions.push(this);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVGV4dHVyZUF0bGFzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL1RleHR1cmVBdGxhcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OytFQTJCK0U7QUFHL0UsT0FBTyxFQUFnQixhQUFhLEVBQUUsYUFBYSxFQUFFLFdBQVcsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUN2RixPQUFPLEVBQW1DLEtBQUssRUFBRSxNQUFNLFlBQVksQ0FBQztBQUVwRSxNQUFNLE9BQU8sWUFBWTtJQUN4QixLQUFLLEdBQUcsRUFBd0IsQ0FBQztJQUNqQyxPQUFPLEdBQUcsRUFBMEIsQ0FBQztJQUVyQyxZQUFhLFNBQWlCO1FBQzdCLE1BQU0sTUFBTSxHQUFHLElBQUksa0JBQWtCLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDakQsTUFBTSxLQUFLLEdBQUcsSUFBSSxLQUFLLENBQVMsQ0FBQyxDQUFDLENBQUM7UUFFbkMsTUFBTSxVQUFVLEdBQWdELEVBQUUsQ0FBQztRQUNuRSxVQUFVLENBQUMsSUFBSSxHQUFHLENBQUMsSUFBc0IsRUFBRSxFQUFFO1lBQzVDLElBQUksQ0FBQyxLQUFLLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2hDLElBQUksQ0FBQyxNQUFNLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xDLENBQUMsQ0FBQztRQUNGLFVBQVUsQ0FBQyxNQUFNLEdBQUcsR0FBRyxFQUFFO1lBQ3hCLGdFQUFnRTtRQUNqRSxDQUFDLENBQUM7UUFDRixVQUFVLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBc0IsRUFBRSxFQUFFO1lBQzlDLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxhQUFhLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDMUQsSUFBSSxDQUFDLFNBQVMsR0FB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 Line truncated