@pixi-ui-editor/schema 0.17.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assetReferences.js +0 -1
- package/dist/assetReferences.js.map +1 -1
- package/dist/index.d.ts +32 -72
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +68 -18
- package/dist/index.js.map +1 -1
- package/dist/nodeReferences.d.ts.map +1 -1
- package/dist/nodeReferences.js +6 -1
- package/dist/nodeReferences.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { collectLocalizationIssues, createDefaultLocalization, LocalizationSchem
|
|
|
7
7
|
export { collectBindingKeys, collectBindingKeyScopes, OWNER_BINDING_KEY_SCOPE } from "./bindingKeys.js";
|
|
8
8
|
export { rewriteNodeReferences, rewritePrefabInstanceReferencePatches } from "./nodeReferences.js";
|
|
9
9
|
export { clearNodeAssetReferences } from "./assetReferences.js";
|
|
10
|
-
export const CURRENT_SCHEMA_VERSION =
|
|
10
|
+
export const CURRENT_SCHEMA_VERSION = 44;
|
|
11
11
|
const Id = Type.String({ format: "uuid" });
|
|
12
12
|
const Name = Type.String({ minLength: 1 });
|
|
13
13
|
/**
|
|
@@ -53,9 +53,11 @@ const GridLayout = Type.Composite([NodeBase, Type.Object({ type: Type.Literal("g
|
|
|
53
53
|
// assetId отсутствует — нода без источника: рантайм и редактор рисуют белый прямоугольник её размера.
|
|
54
54
|
// `nineSlice` отсутствует — обычный Sprite, растянутый по transform (старое поведение, без миграции).
|
|
55
55
|
// При наличии — рамки в пикселях источника (как @pixi/ui fillPadding), не сериализованные проценты:
|
|
56
|
-
// нода `NineSliceSprite`, углы/края не искажаются при растяжении.
|
|
56
|
+
// нода `NineSliceSprite`, углы/края не искажаются при растяжении. `cornerRadius` — третий режим
|
|
57
|
+
// отображения: тот же растянутый Sprite, но с GPU-маской скруглённого прямоугольника в logical pixels.
|
|
58
|
+
// Inspector делает `nineSlice` и `cornerRadius` взаимоисключающими.
|
|
57
59
|
const ImageTint = Type.String({ pattern: "^#[0-9A-Fa-f]{6}$" });
|
|
58
|
-
const Image = Type.Composite([NodeBase, Type.Object({ type: Type.Literal("image"), assetId: Type.Optional(Id), opacity: Type.Optional(Type.Number({ minimum: 0, maximum: 1 })), tint: Type.Optional(ImageTint), nineSlice: Type.Optional(Padding) })]);
|
|
60
|
+
const Image = Type.Composite([NodeBase, Type.Object({ type: Type.Literal("image"), assetId: Type.Optional(Id), opacity: Type.Optional(Type.Number({ minimum: 0, maximum: 1 })), tint: Type.Optional(ImageTint), nineSlice: Type.Optional(Padding), cornerRadius: Type.Optional(Type.Number({ minimum: 0 })) })]);
|
|
59
61
|
const TextStroke = Type.Object({ color: Type.String({ pattern: "^#[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$" }), width: Type.Number({ minimum: 0 }) });
|
|
60
62
|
// Числовые начертания соответствуют CSS/PIXI `font-weight` напрямую (без адаптера): у каждого
|
|
61
63
|
// значения должен быть загружен свой файл шрифта с тем же `family` (см. FontAsset.weight), иначе
|
|
@@ -105,7 +107,7 @@ export function resolveSpineConnectorPositionMultiplier(connector, profile) {
|
|
|
105
107
|
const override = profile === "desktop" ? undefined : connector.positionMultiplierOverrides?.mobile;
|
|
106
108
|
return { x: override?.x ?? base.x, y: override?.y ?? base.y };
|
|
107
109
|
}
|
|
108
|
-
const Spine = Type.Composite([NodeBase, Type.Object({ type: Type.Literal("spine"), assetId: Id, animation: Type.Optional(Type.String({ minLength: 1 })), autoplay: Type.Optional(Type.Boolean()), loop: Type.Optional(Type.Boolean()), animationSpeed: Type.Optional(Type.Number({ exclusiveMinimum: 0 })), spineOverrides: Type.Optional(SpineOverrides), connectors: Type.Optional(Type.Array(SpineConnectorSchema)) })]);
|
|
110
|
+
const Spine = Type.Composite([NodeBase, Type.Object({ type: Type.Literal("spine"), assetId: Id, opacity: Type.Optional(Type.Number({ minimum: 0, maximum: 1 })), animation: Type.Optional(Type.String({ minLength: 1 })), autoplay: Type.Optional(Type.Boolean()), loop: Type.Optional(Type.Boolean()), animationSpeed: Type.Optional(Type.Number({ exclusiveMinimum: 0 })), spineOverrides: Type.Optional(SpineOverrides), connectors: Type.Optional(Type.Array(SpineConnectorSchema)) })]);
|
|
109
111
|
const BitmapTextAlign = Type.Union([Type.Literal("left"), Type.Literal("center"), Type.Literal("right")]);
|
|
110
112
|
// A bitmap font's glyphs come pre-rendered from its texture, so unlike `Text` there is no system
|
|
111
113
|
// fallback: `assetId` is required (like Spine's), and the "Bitmap Text" add-node entry stays disabled
|
|
@@ -299,12 +301,6 @@ const Pagination = Type.Composite([NodeBase, Type.Object({
|
|
|
299
301
|
inactiveAssetId: Type.Optional(Id),
|
|
300
302
|
numberStyle: Type.Optional(TextStyleDefinitionSchema),
|
|
301
303
|
numberActiveColor: Type.Optional(Type.String({ pattern: "^#[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$" })),
|
|
302
|
-
// Optional "pill" background behind the current page's digit only (a plain Sprite, or a
|
|
303
|
-
// NineSliceSprite when `numberActiveNineSlice` is set) — sized to `dotSize`, the same field a
|
|
304
|
-
// `dots`-style item already uses for its own box. Absent means no background, same as before this
|
|
305
|
-
// field existed: just the `numberActiveColor` text highlight.
|
|
306
|
-
numberActiveBackgroundAssetId: Type.Optional(Id),
|
|
307
|
-
numberActiveNineSlice: Type.Optional(Padding),
|
|
308
304
|
pageCount: Type.Integer({ minimum: 1 }),
|
|
309
305
|
defaultPage: Type.Integer({ minimum: 0 }),
|
|
310
306
|
direction: PaginationDirection,
|
|
@@ -318,6 +314,12 @@ const Pagination = Type.Composite([NodeBase, Type.Object({
|
|
|
318
314
|
// `NodeAddress`, а не `Id`: стрелка часто лежит внутри инстанса пресета и адресуется путём.
|
|
319
315
|
prevButtonNodeId: Type.Optional(NodeAddress),
|
|
320
316
|
nextButtonNodeId: Type.Optional(NodeAddress),
|
|
317
|
+
// An existing authored node wired as the "current page" highlight, the same reference-not-owned
|
|
318
|
+
// contract as the prev/next arrows. The widget renders nothing itself: while `style: "numbers"` it
|
|
319
|
+
// only sets this node's `visible` flag on, so the node's own asset / nine-slice / rounded corners /
|
|
320
|
+
// size / position — authored on the node — are the entire visual. Absent means no highlight beyond
|
|
321
|
+
// `numberActiveColor`. Ignored while `style: "dots"` (the node is kept hidden).
|
|
322
|
+
activeBackgroundNodeId: Type.Optional(NodeAddress),
|
|
321
323
|
// How many indicator slots are rendered at once. Must be odd, because the active page always sits
|
|
322
324
|
// in the middle slot: 4 pages with page 3 active render 2-3-4. A slot whose page falls outside
|
|
323
325
|
// 0..pageCount-1 keeps its `dotSize` footprint and renders nothing, so the active page never moves
|
|
@@ -484,6 +486,13 @@ function checkNodeReferences(document, owner, path, issues) {
|
|
|
484
486
|
else if (target.type !== "button" && target.type !== "staged-button")
|
|
485
487
|
add(issues, "INVALID_PAGINATION_ARROW", arrowPath, "A pagination arrow must reference a button or staged-button node.");
|
|
486
488
|
}
|
|
489
|
+
if (node.activeBackgroundNodeId !== undefined) {
|
|
490
|
+
const backgroundPath = `${path}/paginationActiveBackground/${node.id}`;
|
|
491
|
+
if (!nodes.has(node.activeBackgroundNodeId))
|
|
492
|
+
add(issues, "MISSING_PAGINATION_ACTIVE_BACKGROUND", backgroundPath, `Pagination active background '${node.activeBackgroundNodeId}' does not exist in this owner.`);
|
|
493
|
+
else if (node.activeBackgroundNodeId === node.id)
|
|
494
|
+
add(issues, "INVALID_PAGINATION_ACTIVE_BACKGROUND", backgroundPath, "A pagination cannot use itself as its active background.");
|
|
495
|
+
}
|
|
487
496
|
continue;
|
|
488
497
|
}
|
|
489
498
|
if (node.type === "page-group") {
|
|
@@ -755,14 +764,6 @@ function hierarchy(owner, path, assets, prefabs, effects, issues) {
|
|
|
755
764
|
else if (asset.type !== "font")
|
|
756
765
|
add(issues, "INCOMPATIBLE_ASSET_REFERENCE", fontPath, "A pagination numberStyle fontAssetId requires a font asset.");
|
|
757
766
|
}
|
|
758
|
-
if (node.numberActiveBackgroundAssetId !== undefined) {
|
|
759
|
-
const asset = assets.get(node.numberActiveBackgroundAssetId);
|
|
760
|
-
const bgPath = `${nodePath}/numberActiveBackgroundAssetId`;
|
|
761
|
-
if (!asset)
|
|
762
|
-
addWarning(issues, "MISSING_ASSET_REFERENCE", bgPath, `Asset '${node.numberActiveBackgroundAssetId}' does not exist.`);
|
|
763
|
-
else if (asset.type !== "image")
|
|
764
|
-
add(issues, "INCOMPATIBLE_ASSET_REFERENCE", bgPath, "A pagination numberActiveBackgroundAssetId requires an image asset.");
|
|
765
|
-
}
|
|
766
767
|
}
|
|
767
768
|
if (node.defaultPage > node.pageCount - 1)
|
|
768
769
|
add(issues, "VALUE_OUT_OF_RANGE", `${nodePath}/defaultPage`, "Pagination defaultPage must be inside the inclusive 0..pageCount-1 range.");
|
|
@@ -1296,6 +1297,42 @@ function migrateV32ToV33(document) {
|
|
|
1296
1297
|
}
|
|
1297
1298
|
/** v40 adds sparse bitmap-text presentation overrides; existing values remain the shared base. */
|
|
1298
1299
|
function migrateV39ToV40(_document) { }
|
|
1300
|
+
/** v41 adds an optional image corner radius; older plain and nine-slice images already retain their meaning. */
|
|
1301
|
+
function migrateV40ToV41(_document) { }
|
|
1302
|
+
/** v42 adds an optional rounded mode to pagination's active number background. */
|
|
1303
|
+
function migrateV41ToV42(_document) { }
|
|
1304
|
+
/**
|
|
1305
|
+
* v43 replaces pagination's inline active-background asset (`numberActiveBackgroundAssetId` plus its
|
|
1306
|
+
* `numberActiveNineSlice`/`numberActiveCornerRadius` rendering fields) with a single
|
|
1307
|
+
* `activeBackgroundNodeId` reference to an authored node. There is no authored node to point the
|
|
1308
|
+
* reference at, so the obsolete fields are simply dropped from every pagination node and sparse patch.
|
|
1309
|
+
*/
|
|
1310
|
+
function migrateV42ToV43(document) {
|
|
1311
|
+
const obsolete = ["numberActiveBackgroundAssetId", "numberActiveNineSlice", "numberActiveCornerRadius"];
|
|
1312
|
+
const strip = (record) => { for (const key of obsolete)
|
|
1313
|
+
delete record[key]; };
|
|
1314
|
+
const visit = (node) => {
|
|
1315
|
+
if (node.type === "pagination")
|
|
1316
|
+
strip(node);
|
|
1317
|
+
if (Array.isArray(node.propertyOverrides))
|
|
1318
|
+
for (const override of node.propertyOverrides) {
|
|
1319
|
+
const patch = override.patch;
|
|
1320
|
+
if (typeof patch === "object" && patch !== null)
|
|
1321
|
+
strip(patch);
|
|
1322
|
+
}
|
|
1323
|
+
if (Array.isArray(node.locallyAddedNodes))
|
|
1324
|
+
for (const local of node.locallyAddedNodes)
|
|
1325
|
+
if (typeof local === "object" && local !== null)
|
|
1326
|
+
visit(local);
|
|
1327
|
+
};
|
|
1328
|
+
const owners = [...(document.scenes ?? []), ...(document.prefabs ?? [])];
|
|
1329
|
+
for (const owner of owners)
|
|
1330
|
+
for (const node of owner.nodes ?? [])
|
|
1331
|
+
if (typeof node === "object" && node !== null)
|
|
1332
|
+
visit(node);
|
|
1333
|
+
}
|
|
1334
|
+
/** v44 adds an optional Spine opacity; existing Spine nodes remain fully opaque. */
|
|
1335
|
+
function migrateV43ToV44(_document) { }
|
|
1299
1336
|
export function migrateProjectDocument(input) {
|
|
1300
1337
|
if (typeof input !== "object" || input === null || !Object.hasOwn(input, "schemaVersion"))
|
|
1301
1338
|
throw new ProjectDocumentMigrationError("A schemaVersion is required for migration.");
|
|
@@ -1353,6 +1390,14 @@ export function migrateProjectDocument(input) {
|
|
|
1353
1390
|
migrateV32ToV33(migrated);
|
|
1354
1391
|
if (version <= 39)
|
|
1355
1392
|
migrateV39ToV40(migrated);
|
|
1393
|
+
if (version <= 40)
|
|
1394
|
+
migrateV40ToV41(migrated);
|
|
1395
|
+
if (version <= 41)
|
|
1396
|
+
migrateV41ToV42(migrated);
|
|
1397
|
+
if (version <= 42)
|
|
1398
|
+
migrateV42ToV43(migrated);
|
|
1399
|
+
if (version <= 43)
|
|
1400
|
+
migrateV43ToV44(migrated);
|
|
1356
1401
|
// v36 → v37 (position multiplier у spine-коннекторов) не требует переписывания данных:
|
|
1357
1402
|
// добавлены только опциональные поля коннектора, и любой документ v36 уже валиден как v37.
|
|
1358
1403
|
// v34 → v35 (`states.normalAssetId` стал опциональным у button/staged-button) не требует
|
|
@@ -1368,6 +1413,11 @@ export function migrateProjectDocument(input) {
|
|
|
1368
1413
|
// v38 → v39 (per-state button tint/opacity) не требует переписывания данных: новые appearance
|
|
1369
1414
|
// fields optional and therefore resolve to white / 1 for every existing button.
|
|
1370
1415
|
// v39 → v40 (bitmap-text presentation overrides) likewise adds only optional sparse fields.
|
|
1416
|
+
// v40 → v41 (`image.cornerRadius`) is an optional field; existing plain and nine-slice images
|
|
1417
|
+
// already have their intended rendering mode.
|
|
1418
|
+
// v41 → v42 (`pagination.numberActiveCornerRadius`) is optional; existing active backgrounds
|
|
1419
|
+
// remain plain or nine-slice.
|
|
1420
|
+
// v43 → v44 (`spine.opacity`) is optional; existing Spine nodes remain fully opaque.
|
|
1371
1421
|
// v37 → v38 (page-group carousel arrows) не требует переписывания данных: добавлены только
|
|
1372
1422
|
// опциональные поля `pageUpButtonNodeId`/`pageDownButtonNodeId`, любой документ v37 уже валиден как v38.
|
|
1373
1423
|
migrated.schemaVersion = CURRENT_SCHEMA_VERSION;
|