@openfairygui/cli 0.2.0-alpha.10 → 0.2.0-alpha.11
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/cli.mjs +1284 -757
- package/package.json +6 -4
- package/src/cli.ts +30 -535
- package/src/commands/backend-capabilities.ts +37 -0
- package/src/commands/inspect.ts +44 -0
- package/src/commands/publish.ts +108 -0
- package/src/commands/restore.ts +209 -0
- package/src/utils/package-version.ts +22 -0
- package/src/utils/project-input.ts +26 -0
- package/src/utils/project-type.ts +31 -0
package/dist/cli.mjs
CHANGED
|
@@ -1,10 +1,178 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
+
import { Command } from "commander";
|
|
2
3
|
import { createNodeBackendRuntime } from "@openfairygui/backend/node";
|
|
3
|
-
import * as fs$1 from "node:fs/promises";
|
|
4
|
-
import fs from "node:fs/promises";
|
|
5
4
|
import * as path$1 from "node:path";
|
|
6
5
|
import path from "node:path";
|
|
7
|
-
import {
|
|
6
|
+
import { createJiti } from "jiti";
|
|
7
|
+
import * as fs$1 from "node:fs/promises";
|
|
8
|
+
import fs from "node:fs/promises";
|
|
9
|
+
//#region src/commands/backend-capabilities.ts
|
|
10
|
+
function registerBackendCapabilitiesCommand(program) {
|
|
11
|
+
program.command("backend-capabilities").description("Open a backend session, print runtime capabilities, then close it").argument("<project-dir>", "Project root directory").action(async (projectDir) => {
|
|
12
|
+
const runtime = createNodeBackendRuntime();
|
|
13
|
+
const opened = await runtime.openSession({ projectPath: path.resolve(projectDir) });
|
|
14
|
+
if (!opened.ok) throw new Error(`backend-capabilities: ${opened.error.message}`);
|
|
15
|
+
const capabilities = runtime.getCapabilities();
|
|
16
|
+
if (!capabilities.ok) {
|
|
17
|
+
await runtime.closeSession({ sessionId: opened.data.sessionId });
|
|
18
|
+
throw new Error("backend-capabilities: failed to read capabilities");
|
|
19
|
+
}
|
|
20
|
+
console.log(`Session: ${opened.data.sessionId}`);
|
|
21
|
+
console.log(`Project: ${opened.data.canonicalProjectPath}`);
|
|
22
|
+
console.log(`Revision: ${opened.data.revision}`);
|
|
23
|
+
console.log(`Runtime owner: ${capabilities.data.runtimeOwner}`);
|
|
24
|
+
console.log(`Transaction owner: ${capabilities.data.transactionKernelOwner}`);
|
|
25
|
+
console.log(`App seam owner: ${capabilities.data.appSeamOwner}`);
|
|
26
|
+
const closed = await runtime.closeSession({ sessionId: opened.data.sessionId });
|
|
27
|
+
if (!closed.ok) throw new Error(`backend-capabilities: ${closed.error.message}`);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region ../functions/src/inspect.ts
|
|
32
|
+
function mapResource(resource) {
|
|
33
|
+
return {
|
|
34
|
+
name: resource.getName(),
|
|
35
|
+
id: resource.getId(),
|
|
36
|
+
path: resource.getPath?.() ?? "/",
|
|
37
|
+
exported: resource.getExported?.() ?? false
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function mapComponentDetail(component, totals) {
|
|
41
|
+
const children = component.listChildren();
|
|
42
|
+
const controllers = component.listControllers();
|
|
43
|
+
const transitions = component.listTransitions();
|
|
44
|
+
totals.displayObjects += children.length;
|
|
45
|
+
totals.controllers += controllers.length;
|
|
46
|
+
totals.transitions += transitions.length;
|
|
47
|
+
for (const child of children) totals.gears += child.listGears().length;
|
|
48
|
+
return {
|
|
49
|
+
name: component.getName(),
|
|
50
|
+
id: component.getId(),
|
|
51
|
+
childCount: children.length,
|
|
52
|
+
controllerCount: controllers.length,
|
|
53
|
+
transitionCount: transitions.length
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Generates a detailed report of the project contents.
|
|
58
|
+
*
|
|
59
|
+
* Unlike other transforms, `inspect()` does NOT modify the document —
|
|
60
|
+
* it returns a structured report.
|
|
61
|
+
*
|
|
62
|
+
* ```ts
|
|
63
|
+
* const report = inspect(doc);
|
|
64
|
+
* console.log(`${report.totals.packages} packages, ${report.totals.components} components`);
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
function inspect(doc) {
|
|
68
|
+
const root = doc.getRoot();
|
|
69
|
+
const totals = {
|
|
70
|
+
packages: 0,
|
|
71
|
+
images: 0,
|
|
72
|
+
sounds: 0,
|
|
73
|
+
fonts: 0,
|
|
74
|
+
movieClips: 0,
|
|
75
|
+
components: 0,
|
|
76
|
+
displayObjects: 0,
|
|
77
|
+
gears: 0,
|
|
78
|
+
controllers: 0,
|
|
79
|
+
transitions: 0
|
|
80
|
+
};
|
|
81
|
+
const packages = root.listPackages().map((pkg) => {
|
|
82
|
+
totals.packages++;
|
|
83
|
+
const resources = pkg.listResources();
|
|
84
|
+
const images = resources.filter((r) => r.propertyType === "ImageResource");
|
|
85
|
+
const sounds = resources.filter((r) => r.propertyType === "SoundResource");
|
|
86
|
+
const fonts = resources.filter((r) => r.propertyType === "FontResource");
|
|
87
|
+
const movieClips = resources.filter((r) => r.propertyType === "MovieClipResource");
|
|
88
|
+
const components = pkg.listComponents();
|
|
89
|
+
totals.images += images.length;
|
|
90
|
+
totals.sounds += sounds.length;
|
|
91
|
+
totals.fonts += fonts.length;
|
|
92
|
+
totals.movieClips += movieClips.length;
|
|
93
|
+
totals.components += components.length;
|
|
94
|
+
const componentDetails = components.map((component) => mapComponentDetail(component, totals));
|
|
95
|
+
return {
|
|
96
|
+
name: pkg.getName(),
|
|
97
|
+
id: pkg.getId(),
|
|
98
|
+
publishName: pkg.getPublishName() || pkg.getName(),
|
|
99
|
+
resources: {
|
|
100
|
+
images: {
|
|
101
|
+
count: images.length,
|
|
102
|
+
details: images.map(mapResource)
|
|
103
|
+
},
|
|
104
|
+
sounds: {
|
|
105
|
+
count: sounds.length,
|
|
106
|
+
details: sounds.map(mapResource)
|
|
107
|
+
},
|
|
108
|
+
fonts: {
|
|
109
|
+
count: fonts.length,
|
|
110
|
+
details: fonts.map(mapResource)
|
|
111
|
+
},
|
|
112
|
+
movieClips: {
|
|
113
|
+
count: movieClips.length,
|
|
114
|
+
details: movieClips.map(mapResource)
|
|
115
|
+
},
|
|
116
|
+
components: {
|
|
117
|
+
count: components.length,
|
|
118
|
+
details: components.map(mapResource)
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
componentDetails
|
|
122
|
+
};
|
|
123
|
+
});
|
|
124
|
+
return {
|
|
125
|
+
projectId: root.getProjectId(),
|
|
126
|
+
projectType: root.getProjectType(),
|
|
127
|
+
version: root.getVersion(),
|
|
128
|
+
packages,
|
|
129
|
+
totals
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
//#endregion
|
|
133
|
+
//#region ../functions/src/utils.ts
|
|
134
|
+
/**
|
|
135
|
+
* Wraps a transform function, assigning it a name for the transform stack.
|
|
136
|
+
*/
|
|
137
|
+
function createTransform(name, fn) {
|
|
138
|
+
Object.defineProperty(fn, "name", { value: name });
|
|
139
|
+
return fn;
|
|
140
|
+
}
|
|
141
|
+
function parseTextureSetMode(value) {
|
|
142
|
+
const raw = value?.trim() ?? "";
|
|
143
|
+
if (!raw) return {
|
|
144
|
+
kind: "auto",
|
|
145
|
+
raw: ""
|
|
146
|
+
};
|
|
147
|
+
if (raw === "alone") return {
|
|
148
|
+
kind: "standalone",
|
|
149
|
+
raw,
|
|
150
|
+
sizeMode: "default"
|
|
151
|
+
};
|
|
152
|
+
if (raw === "alone_npot") return {
|
|
153
|
+
kind: "standalone",
|
|
154
|
+
raw,
|
|
155
|
+
sizeMode: "npot"
|
|
156
|
+
};
|
|
157
|
+
if (raw === "alone_mof") return {
|
|
158
|
+
kind: "standalone",
|
|
159
|
+
raw,
|
|
160
|
+
sizeMode: "multipleOf4"
|
|
161
|
+
};
|
|
162
|
+
if (/^\d+$/.test(raw)) {
|
|
163
|
+
const pageIndex = Number(raw);
|
|
164
|
+
if (pageIndex >= 0 && pageIndex <= 10) return {
|
|
165
|
+
kind: "page",
|
|
166
|
+
raw,
|
|
167
|
+
pageIndex
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
kind: "auto",
|
|
172
|
+
raw
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
//#endregion
|
|
8
176
|
//#region ../../node_modules/.pnpm/property-graph@4.1.0/node_modules/property-graph/dist/index.mjs
|
|
9
177
|
var EventDispatcher = class {
|
|
10
178
|
_listeners = {};
|
|
@@ -1688,6 +1856,7 @@ var MovieClipResource = class extends ExtensibleProperty {
|
|
|
1688
1856
|
highResolutionItemIds: [],
|
|
1689
1857
|
fileName: "",
|
|
1690
1858
|
exported: false,
|
|
1859
|
+
textureSetMode: "",
|
|
1691
1860
|
width: 0,
|
|
1692
1861
|
height: 0,
|
|
1693
1862
|
interval: 0,
|
|
@@ -1739,6 +1908,12 @@ var MovieClipResource = class extends ExtensibleProperty {
|
|
|
1739
1908
|
setExported(v) {
|
|
1740
1909
|
return this.set("exported", v);
|
|
1741
1910
|
}
|
|
1911
|
+
getTextureSetMode() {
|
|
1912
|
+
return this.get("textureSetMode");
|
|
1913
|
+
}
|
|
1914
|
+
setTextureSetMode(v) {
|
|
1915
|
+
return this.set("textureSetMode", v);
|
|
1916
|
+
}
|
|
1742
1917
|
getWidth() {
|
|
1743
1918
|
return this.get("width");
|
|
1744
1919
|
}
|
|
@@ -4451,6 +4626,8 @@ var GComponent = class extends GObject {
|
|
|
4451
4626
|
instanceController: "",
|
|
4452
4627
|
instancePage: "",
|
|
4453
4628
|
instanceChecked: false,
|
|
4629
|
+
instanceSound: "",
|
|
4630
|
+
instanceSoundVolumeScale: 1,
|
|
4454
4631
|
instancePromptText: "",
|
|
4455
4632
|
instanceSelectionController: "",
|
|
4456
4633
|
instanceVisibleItemCount: 0,
|
|
@@ -4723,6 +4900,18 @@ var GComponent = class extends GObject {
|
|
|
4723
4900
|
setInstanceChecked(v) {
|
|
4724
4901
|
return this.setComponentProp("instanceChecked", v);
|
|
4725
4902
|
}
|
|
4903
|
+
getInstanceSound() {
|
|
4904
|
+
return firstString$1(this.getComponentProp("instanceSound"));
|
|
4905
|
+
}
|
|
4906
|
+
setInstanceSound(v) {
|
|
4907
|
+
return this.setComponentProp("instanceSound", v);
|
|
4908
|
+
}
|
|
4909
|
+
getInstanceSoundVolumeScale() {
|
|
4910
|
+
return this.getComponentProp("instanceSoundVolumeScale");
|
|
4911
|
+
}
|
|
4912
|
+
setInstanceSoundVolumeScale(v) {
|
|
4913
|
+
return this.setComponentProp("instanceSoundVolumeScale", v);
|
|
4914
|
+
}
|
|
4726
4915
|
getInstancePromptText() {
|
|
4727
4916
|
return firstString$1(this.getComponentProp("instancePromptText"));
|
|
4728
4917
|
}
|
|
@@ -9081,6 +9270,7 @@ var Document = class Document {
|
|
|
9081
9270
|
_graph = new Graph();
|
|
9082
9271
|
_root = new Root(this._graph);
|
|
9083
9272
|
_logger = Logger.DEFAULT_INSTANCE;
|
|
9273
|
+
_projectDir = "";
|
|
9084
9274
|
static _GRAPH_DOCUMENTS = /* @__PURE__ */ new WeakMap();
|
|
9085
9275
|
static fromGraph(graph) {
|
|
9086
9276
|
return Document._GRAPH_DOCUMENTS.get(graph) || null;
|
|
@@ -9102,6 +9292,13 @@ var Document = class Document {
|
|
|
9102
9292
|
this._logger = logger;
|
|
9103
9293
|
return this;
|
|
9104
9294
|
}
|
|
9295
|
+
getProjectDir() {
|
|
9296
|
+
return this._projectDir;
|
|
9297
|
+
}
|
|
9298
|
+
setProjectDir(projectDir) {
|
|
9299
|
+
this._projectDir = projectDir;
|
|
9300
|
+
return this;
|
|
9301
|
+
}
|
|
9105
9302
|
async transform(...transforms) {
|
|
9106
9303
|
const stack = transforms.map((fn) => fn.name);
|
|
9107
9304
|
for (const transform of transforms) await transform(this, { stack });
|
|
@@ -9282,6 +9479,7 @@ const PACKAGE_FONT_RESOURCE_ATTRS = {
|
|
|
9282
9479
|
renderMode: { canonical: "renderMode" },
|
|
9283
9480
|
samplePointSize: { canonical: "samplePointSize" }
|
|
9284
9481
|
};
|
|
9482
|
+
const PACKAGE_MOVIE_CLIP_RESOURCE_ATTRS = { atlas: { canonical: "atlas" } };
|
|
9285
9483
|
const PACKAGE_SKELETON_RESOURCE_ATTRS = {
|
|
9286
9484
|
width: { canonical: "width" },
|
|
9287
9485
|
height: { canonical: "height" },
|
|
@@ -9518,7 +9716,10 @@ const LIST_PANEL_ATTRS = {
|
|
|
9518
9716
|
const BUTTON_EXTENSION_ATTRS = {
|
|
9519
9717
|
mode: { canonical: "mode" },
|
|
9520
9718
|
sound: { canonical: "sound" },
|
|
9521
|
-
soundVolumeScale: {
|
|
9719
|
+
soundVolumeScale: {
|
|
9720
|
+
canonical: "soundVolumeScale",
|
|
9721
|
+
aliases: ["volume"]
|
|
9722
|
+
},
|
|
9522
9723
|
downEffect: { canonical: "downEffect" },
|
|
9523
9724
|
downEffectValue: { canonical: "downEffectValue" },
|
|
9524
9725
|
title: { canonical: "title" },
|
|
@@ -9644,6 +9845,7 @@ const PACKAGE_PUBLISH_NODE = defineNode(PACKAGE_PUBLISH_ATTRS, { atlas: PACKAGE_
|
|
|
9644
9845
|
const PACKAGE_RESOURCE_NODE = defineNode(PACKAGE_RESOURCE_BASE_ATTRS);
|
|
9645
9846
|
const PACKAGE_IMAGE_RESOURCE_NODE = defineNode(PACKAGE_IMAGE_RESOURCE_ATTRS);
|
|
9646
9847
|
const PACKAGE_FONT_RESOURCE_NODE = defineNode(PACKAGE_FONT_RESOURCE_ATTRS);
|
|
9848
|
+
const PACKAGE_MOVIE_CLIP_RESOURCE_NODE = defineNode(PACKAGE_MOVIE_CLIP_RESOURCE_ATTRS);
|
|
9647
9849
|
const PACKAGE_SKELETON_RESOURCE_NODE = defineNode(PACKAGE_SKELETON_RESOURCE_ATTRS);
|
|
9648
9850
|
const DISPLAY_OBJECT_NODE = defineNode(DISPLAY_OBJECT_IDENTITY_ATTRS);
|
|
9649
9851
|
const BUTTON_EXTENSION_NODE = defineNode(BUTTON_EXTENSION_ATTRS);
|
|
@@ -9734,6 +9936,7 @@ const PROJECT_XML_PROTOCOL = {
|
|
|
9734
9936
|
packageResource: PACKAGE_RESOURCE_NODE,
|
|
9735
9937
|
packageImageResource: PACKAGE_IMAGE_RESOURCE_NODE,
|
|
9736
9938
|
packageFontResource: PACKAGE_FONT_RESOURCE_NODE,
|
|
9939
|
+
packageMovieClipResource: PACKAGE_MOVIE_CLIP_RESOURCE_NODE,
|
|
9737
9940
|
packageSkeletonResource: PACKAGE_SKELETON_RESOURCE_NODE,
|
|
9738
9941
|
displayObject: DISPLAY_OBJECT_NODE,
|
|
9739
9942
|
image: IMAGE_NODE,
|
|
@@ -10177,6 +10380,7 @@ var ProjectReader = class {
|
|
|
10177
10380
|
const fs = this._fs;
|
|
10178
10381
|
const doc = new Document();
|
|
10179
10382
|
const basePath = getProjectBasePath(fs, projectPath);
|
|
10383
|
+
doc.setProjectDir(basePath);
|
|
10180
10384
|
const ctx = new ReaderContext(doc, basePath);
|
|
10181
10385
|
const projDesc = getXmlNode(parseXML(await fs.readFile(projectPath)).projectDescription);
|
|
10182
10386
|
if (projDesc) {
|
|
@@ -10493,6 +10697,8 @@ var ProjectReader = class {
|
|
|
10493
10697
|
res.setBranch(branchName);
|
|
10494
10698
|
res.setFileName(name);
|
|
10495
10699
|
res.setExported(exported);
|
|
10700
|
+
const textureSetMode = readXmlAttr(attrs, PROJECT_XML_PROTOCOL.packageMovieClipResource.attrs.atlas);
|
|
10701
|
+
if (textureSetMode !== void 0) res.setTextureSetMode(textureSetMode);
|
|
10496
10702
|
pkg.addResource(res);
|
|
10497
10703
|
ctx.registerResource(pkg.getId(), id, res);
|
|
10498
10704
|
return res;
|
|
@@ -11752,6 +11958,10 @@ var ProjectReader = class {
|
|
|
11752
11958
|
if (page !== void 0) componentObj.setInstancePage?.(page);
|
|
11753
11959
|
const checked = extSpecs.checked ? readXmlAttr(extAttrs, extSpecs.checked) : void 0;
|
|
11754
11960
|
if (checked !== void 0) componentObj.setInstanceChecked?.(parseBool(checked));
|
|
11961
|
+
const sound = extSpecs.sound ? readXmlAttr(extAttrs, extSpecs.sound) : void 0;
|
|
11962
|
+
if (sound !== void 0) componentObj.setInstanceSound?.(sound);
|
|
11963
|
+
const soundVolumeScale = extSpecs.soundVolumeScale ? readXmlAttr(extAttrs, extSpecs.soundVolumeScale) : void 0;
|
|
11964
|
+
if (soundVolumeScale !== void 0) componentObj.setInstanceSoundVolumeScale?.(parseFloat2(soundVolumeScale, 1));
|
|
11755
11965
|
const prompt = extSpecs.prompt ? readXmlAttr(extAttrs, extSpecs.prompt) : void 0;
|
|
11756
11966
|
if (prompt !== void 0) componentObj.setInstancePromptText?.(prompt);
|
|
11757
11967
|
const selectionController = extSpecs.selectionController ? readXmlAttr(extAttrs, extSpecs.selectionController) : void 0;
|
|
@@ -12418,6 +12628,10 @@ var ProjectWriter = class {
|
|
|
12418
12628
|
const samplePointSize = fontRes.getSamplePointSize?.() ?? 0;
|
|
12419
12629
|
if (samplePointSize !== 0) writeXmlAttr(attrs, PROJECT_XML_PROTOCOL.packageFontResource.attrs.samplePointSize, String(samplePointSize));
|
|
12420
12630
|
}
|
|
12631
|
+
if (res.propertyType === "MovieClipResource") {
|
|
12632
|
+
const textureSetMode = res.getTextureSetMode?.() ?? "";
|
|
12633
|
+
if (textureSetMode) writeXmlAttr(attrs, PROJECT_XML_PROTOCOL.packageMovieClipResource.attrs.atlas, textureSetMode);
|
|
12634
|
+
}
|
|
12421
12635
|
if (res.propertyType === "SpineResource" || res.propertyType === "DragonBonesResource") {
|
|
12422
12636
|
const skeletonRes = res;
|
|
12423
12637
|
writeXmlAttr(attrs, PROJECT_XML_PROTOCOL.packageSkeletonResource.attrs.width, String(skeletonRes.getWidth?.() ?? 0));
|
|
@@ -13099,6 +13313,8 @@ var ProjectWriter = class {
|
|
|
13099
13313
|
if (typedObj.getInstanceController?.() && extSpecs.controller) writeXmlAttr(extAttrs, extSpecs.controller, typedObj.getInstanceController?.());
|
|
13100
13314
|
if (typedObj.getInstancePage?.() && extSpecs.page) writeXmlAttr(extAttrs, extSpecs.page, typedObj.getInstancePage?.());
|
|
13101
13315
|
if (typedObj.getInstanceChecked?.() && extSpecs.checked) writeXmlAttr(extAttrs, extSpecs.checked, "1");
|
|
13316
|
+
if (typedObj.getInstanceSound?.() && extSpecs.sound) writeXmlAttr(extAttrs, extSpecs.sound, typedObj.getInstanceSound?.());
|
|
13317
|
+
if ((typedObj.getInstanceSoundVolumeScale?.() ?? 1) !== 1 && extSpecs.soundVolumeScale) writeXmlAttr(extAttrs, extSpecs.soundVolumeScale, String(typedObj.getInstanceSoundVolumeScale?.() ?? 1));
|
|
13102
13318
|
if (typedObj.getInstancePromptText?.() && extSpecs.prompt) writeXmlAttr(extAttrs, extSpecs.prompt, typedObj.getInstancePromptText?.());
|
|
13103
13319
|
if (typedObj.getInstanceSelectionController?.() && extSpecs.selectionController) writeXmlAttr(extAttrs, extSpecs.selectionController, typedObj.getInstanceSelectionController?.());
|
|
13104
13320
|
if ((typedObj.getInstanceVisibleItemCount?.() ?? 0) > 0 && extSpecs.visibleItemCount) writeXmlAttr(extAttrs, extSpecs.visibleItemCount, String(typedObj.getInstanceVisibleItemCount?.() ?? 0));
|
|
@@ -17569,8 +17785,8 @@ function decodeChildBlock6(resource, child, childBuf) {
|
|
|
17569
17785
|
if (relatedControllerIndex >= 0) component.setInstanceController(resource.listControllers()[relatedControllerIndex]?.getName() ?? "");
|
|
17570
17786
|
}
|
|
17571
17787
|
component.setInstancePage(childBuf.readS() ?? "");
|
|
17572
|
-
childBuf.readS();
|
|
17573
|
-
if (childBuf.readBool() && remainingBytes(childBuf) >= 4) childBuf.getFloat32();
|
|
17788
|
+
component.setInstanceSound(childBuf.readS() ?? "");
|
|
17789
|
+
if (childBuf.readBool() && remainingBytes(childBuf) >= 4) component.setInstanceSoundVolumeScale(childBuf.getFloat32());
|
|
17574
17790
|
if (remainingBytes(childBuf) >= 1) component.setInstanceChecked(childBuf.readBool());
|
|
17575
17791
|
break;
|
|
17576
17792
|
case "Label":
|
|
@@ -18144,8 +18360,9 @@ const BinItemType$1 = {
|
|
|
18144
18360
|
Font: 5,
|
|
18145
18361
|
Swf: 6,
|
|
18146
18362
|
Misc: 7,
|
|
18147
|
-
|
|
18148
|
-
|
|
18363
|
+
Unknown: 8,
|
|
18364
|
+
Spine: 9,
|
|
18365
|
+
DragonBones: 10
|
|
18149
18366
|
};
|
|
18150
18367
|
function normalizePackageResourcePath(path) {
|
|
18151
18368
|
const normalized = path.replace(/\\/g, "/").trim();
|
|
@@ -19983,8 +20200,13 @@ function _writeExtensionInstanceData(buf, extType, child, comp, pkg, version) {
|
|
|
19983
20200
|
buf.writeInt16(ctrlIdx >= 0 ? ctrlIdx : -1);
|
|
19984
20201
|
} else buf.writeInt16(-1);
|
|
19985
20202
|
buf.writeS(child.getInstancePage?.() ?? null);
|
|
19986
|
-
|
|
19987
|
-
buf.
|
|
20203
|
+
const sound = child.getInstanceSound?.() ?? null;
|
|
20204
|
+
buf.writeSEx(remapLocalUiUrl(pkg, sound) ?? null, false, false);
|
|
20205
|
+
const soundVolume = child.getInstanceSoundVolumeScale?.();
|
|
20206
|
+
if (soundVolume !== void 0 && soundVolume !== null && soundVolume !== 1) {
|
|
20207
|
+
buf.writeBool(true);
|
|
20208
|
+
buf.writeFloat32(soundVolume);
|
|
20209
|
+
} else buf.writeBool(false);
|
|
19988
20210
|
buf.writeBool(child.getInstanceChecked?.() ?? false);
|
|
19989
20211
|
break;
|
|
19990
20212
|
}
|
|
@@ -20165,8 +20387,9 @@ const BinItemType = {
|
|
|
20165
20387
|
Atlas: 4,
|
|
20166
20388
|
Font: 5,
|
|
20167
20389
|
Misc: 7,
|
|
20168
|
-
|
|
20169
|
-
|
|
20390
|
+
Unknown: 8,
|
|
20391
|
+
Spine: 9,
|
|
20392
|
+
DragonBones: 10
|
|
20170
20393
|
};
|
|
20171
20394
|
/**
|
|
20172
20395
|
* Maps our PropertyType to the editor's type string used for sorting.
|
|
@@ -20825,228 +21048,60 @@ var PlatformIO = class {
|
|
|
20825
21048
|
}
|
|
20826
21049
|
};
|
|
20827
21050
|
//#endregion
|
|
20828
|
-
//#region ../
|
|
20829
|
-
|
|
20830
|
-
|
|
20831
|
-
|
|
20832
|
-
|
|
20833
|
-
|
|
20834
|
-
|
|
20835
|
-
|
|
20836
|
-
|
|
20837
|
-
|
|
20838
|
-
|
|
20839
|
-
|
|
20840
|
-
|
|
20841
|
-
|
|
20842
|
-
|
|
20843
|
-
|
|
20844
|
-
|
|
20845
|
-
|
|
20846
|
-
|
|
20847
|
-
|
|
20848
|
-
|
|
20849
|
-
|
|
20850
|
-
|
|
20851
|
-
|
|
20852
|
-
|
|
20853
|
-
|
|
20854
|
-
|
|
20855
|
-
|
|
20856
|
-
|
|
20857
|
-
|
|
20858
|
-
|
|
20859
|
-
|
|
20860
|
-
|
|
20861
|
-
|
|
20862
|
-
|
|
20863
|
-
|
|
20864
|
-
|
|
20865
|
-
|
|
20866
|
-
|
|
20867
|
-
|
|
20868
|
-
|
|
20869
|
-
|
|
20870
|
-
|
|
20871
|
-
|
|
20872
|
-
|
|
20873
|
-
|
|
20874
|
-
|
|
20875
|
-
|
|
20876
|
-
|
|
20877
|
-
|
|
20878
|
-
|
|
20879
|
-
|
|
20880
|
-
|
|
20881
|
-
|
|
20882
|
-
}
|
|
20883
|
-
};
|
|
20884
|
-
//#endregion
|
|
20885
|
-
//#region ../functions/src/inspect.ts
|
|
20886
|
-
function mapResource(resource) {
|
|
20887
|
-
return {
|
|
20888
|
-
name: resource.getName(),
|
|
20889
|
-
id: resource.getId(),
|
|
20890
|
-
path: resource.getPath?.() ?? "/",
|
|
20891
|
-
exported: resource.getExported?.() ?? false
|
|
20892
|
-
};
|
|
20893
|
-
}
|
|
20894
|
-
function mapComponentDetail(component, totals) {
|
|
20895
|
-
const children = component.listChildren();
|
|
20896
|
-
const controllers = component.listControllers();
|
|
20897
|
-
const transitions = component.listTransitions();
|
|
20898
|
-
totals.displayObjects += children.length;
|
|
20899
|
-
totals.controllers += controllers.length;
|
|
20900
|
-
totals.transitions += transitions.length;
|
|
20901
|
-
for (const child of children) totals.gears += child.listGears().length;
|
|
20902
|
-
return {
|
|
20903
|
-
name: component.getName(),
|
|
20904
|
-
id: component.getId(),
|
|
20905
|
-
childCount: children.length,
|
|
20906
|
-
controllerCount: controllers.length,
|
|
20907
|
-
transitionCount: transitions.length
|
|
20908
|
-
};
|
|
20909
|
-
}
|
|
20910
|
-
/**
|
|
20911
|
-
* Generates a detailed report of the project contents.
|
|
20912
|
-
*
|
|
20913
|
-
* Unlike other transforms, `inspect()` does NOT modify the document —
|
|
20914
|
-
* it returns a structured report.
|
|
20915
|
-
*
|
|
20916
|
-
* ```ts
|
|
20917
|
-
* const report = inspect(doc);
|
|
20918
|
-
* console.log(`${report.totals.packages} packages, ${report.totals.components} components`);
|
|
20919
|
-
* ```
|
|
20920
|
-
*/
|
|
20921
|
-
function inspect(doc) {
|
|
20922
|
-
const root = doc.getRoot();
|
|
20923
|
-
const totals = {
|
|
20924
|
-
packages: 0,
|
|
20925
|
-
images: 0,
|
|
20926
|
-
sounds: 0,
|
|
20927
|
-
fonts: 0,
|
|
20928
|
-
movieClips: 0,
|
|
20929
|
-
components: 0,
|
|
20930
|
-
displayObjects: 0,
|
|
20931
|
-
gears: 0,
|
|
20932
|
-
controllers: 0,
|
|
20933
|
-
transitions: 0
|
|
20934
|
-
};
|
|
20935
|
-
const packages = root.listPackages().map((pkg) => {
|
|
20936
|
-
totals.packages++;
|
|
20937
|
-
const resources = pkg.listResources();
|
|
20938
|
-
const images = resources.filter((r) => r.propertyType === "ImageResource");
|
|
20939
|
-
const sounds = resources.filter((r) => r.propertyType === "SoundResource");
|
|
20940
|
-
const fonts = resources.filter((r) => r.propertyType === "FontResource");
|
|
20941
|
-
const movieClips = resources.filter((r) => r.propertyType === "MovieClipResource");
|
|
20942
|
-
const components = pkg.listComponents();
|
|
20943
|
-
totals.images += images.length;
|
|
20944
|
-
totals.sounds += sounds.length;
|
|
20945
|
-
totals.fonts += fonts.length;
|
|
20946
|
-
totals.movieClips += movieClips.length;
|
|
20947
|
-
totals.components += components.length;
|
|
20948
|
-
const componentDetails = components.map((component) => mapComponentDetail(component, totals));
|
|
20949
|
-
return {
|
|
20950
|
-
name: pkg.getName(),
|
|
20951
|
-
id: pkg.getId(),
|
|
20952
|
-
publishName: pkg.getPublishName() || pkg.getName(),
|
|
20953
|
-
resources: {
|
|
20954
|
-
images: {
|
|
20955
|
-
count: images.length,
|
|
20956
|
-
details: images.map(mapResource)
|
|
20957
|
-
},
|
|
20958
|
-
sounds: {
|
|
20959
|
-
count: sounds.length,
|
|
20960
|
-
details: sounds.map(mapResource)
|
|
20961
|
-
},
|
|
20962
|
-
fonts: {
|
|
20963
|
-
count: fonts.length,
|
|
20964
|
-
details: fonts.map(mapResource)
|
|
20965
|
-
},
|
|
20966
|
-
movieClips: {
|
|
20967
|
-
count: movieClips.length,
|
|
20968
|
-
details: movieClips.map(mapResource)
|
|
20969
|
-
},
|
|
20970
|
-
components: {
|
|
20971
|
-
count: components.length,
|
|
20972
|
-
details: components.map(mapResource)
|
|
20973
|
-
}
|
|
20974
|
-
},
|
|
20975
|
-
componentDetails
|
|
20976
|
-
};
|
|
20977
|
-
});
|
|
20978
|
-
return {
|
|
20979
|
-
projectId: root.getProjectId(),
|
|
20980
|
-
projectType: root.getProjectType(),
|
|
20981
|
-
version: root.getVersion(),
|
|
20982
|
-
packages,
|
|
20983
|
-
totals
|
|
20984
|
-
};
|
|
20985
|
-
}
|
|
20986
|
-
//#endregion
|
|
20987
|
-
//#region ../functions/src/utils.ts
|
|
20988
|
-
/**
|
|
20989
|
-
* Wraps a transform function, assigning it a name for the transform stack.
|
|
20990
|
-
*/
|
|
20991
|
-
function createTransform(name, fn) {
|
|
20992
|
-
Object.defineProperty(fn, "name", { value: name });
|
|
20993
|
-
return fn;
|
|
20994
|
-
}
|
|
20995
|
-
//#endregion
|
|
20996
|
-
//#region ../functions/src/max-rects-compat.ts
|
|
20997
|
-
const NO_ROTATION = 2;
|
|
20998
|
-
const MAX_SCORE = 2147483647;
|
|
20999
|
-
const MAX_RECTS_METHOD = {
|
|
21000
|
-
BestShortSideFit: 0,
|
|
21001
|
-
BestLongSideFit: 1,
|
|
21002
|
-
BestAreaFit: 2,
|
|
21003
|
-
BottomLeftRule: 3,
|
|
21004
|
-
ContactPointRule: 4
|
|
21005
|
-
};
|
|
21006
|
-
const COMPAT_NODE_RECT_FLAGS = {
|
|
21007
|
-
DUPLICATE_PADDING: 1,
|
|
21008
|
-
NO_ROTATION
|
|
21009
|
-
};
|
|
21010
|
-
var MaxRectsCompat = class MaxRectsCompat {
|
|
21011
|
-
static helperRect = createNodeRect();
|
|
21012
|
-
binWidth = 0;
|
|
21013
|
-
binHeight = 0;
|
|
21014
|
-
allowRotations = false;
|
|
21015
|
-
usedRectangles = [];
|
|
21016
|
-
freeRectangles = [];
|
|
21017
|
-
init(width, height, allowRotations = false) {
|
|
21018
|
-
this.binWidth = width;
|
|
21019
|
-
this.binHeight = height;
|
|
21020
|
-
this.allowRotations = allowRotations;
|
|
21021
|
-
this.usedRectangles.length = 0;
|
|
21022
|
-
this.freeRectangles.length = 0;
|
|
21023
|
-
this.freeRectangles.push({
|
|
21024
|
-
...createNodeRect(),
|
|
21025
|
-
x: 0,
|
|
21026
|
-
y: 0,
|
|
21027
|
-
width,
|
|
21028
|
-
height
|
|
21029
|
-
});
|
|
21030
|
-
}
|
|
21031
|
-
insert(rect, method) {
|
|
21032
|
-
const newNode = this.scoreRect(rect, method);
|
|
21033
|
-
if (newNode.height === 0) return null;
|
|
21034
|
-
const placed = cloneNodeRect(newNode);
|
|
21035
|
-
this.placeRect(placed);
|
|
21036
|
-
return placed;
|
|
21037
|
-
}
|
|
21038
|
-
pack(rects, method) {
|
|
21039
|
-
const remaining = rects.map(cloneNodeRect);
|
|
21040
|
-
while (remaining.length > 0) {
|
|
21041
|
-
let bestIndex = -1;
|
|
21042
|
-
const bestNode = createNodeRect();
|
|
21043
|
-
bestNode.score1 = MAX_SCORE;
|
|
21044
|
-
bestNode.score2 = MAX_SCORE;
|
|
21045
|
-
for (let index = 0; index < remaining.length; index += 1) {
|
|
21046
|
-
const candidate = this.scoreRect(remaining[index], method);
|
|
21047
|
-
if (candidate.score1 < bestNode.score1 || candidate.score1 === bestNode.score1 && candidate.score2 < bestNode.score2) {
|
|
21048
|
-
copyNodeRect(bestNode, candidate);
|
|
21049
|
-
bestIndex = index;
|
|
21051
|
+
//#region ../functions/src/max-rects-compat.ts
|
|
21052
|
+
const NO_ROTATION = 2;
|
|
21053
|
+
const MAX_SCORE = 2147483647;
|
|
21054
|
+
const MAX_RECTS_METHOD = {
|
|
21055
|
+
BestShortSideFit: 0,
|
|
21056
|
+
BestLongSideFit: 1,
|
|
21057
|
+
BestAreaFit: 2,
|
|
21058
|
+
BottomLeftRule: 3,
|
|
21059
|
+
ContactPointRule: 4
|
|
21060
|
+
};
|
|
21061
|
+
const COMPAT_NODE_RECT_FLAGS = {
|
|
21062
|
+
DUPLICATE_PADDING: 1,
|
|
21063
|
+
NO_ROTATION
|
|
21064
|
+
};
|
|
21065
|
+
var MaxRectsCompat = class MaxRectsCompat {
|
|
21066
|
+
static helperRect = createNodeRect();
|
|
21067
|
+
binWidth = 0;
|
|
21068
|
+
binHeight = 0;
|
|
21069
|
+
allowRotations = false;
|
|
21070
|
+
usedRectangles = [];
|
|
21071
|
+
freeRectangles = [];
|
|
21072
|
+
init(width, height, allowRotations = false) {
|
|
21073
|
+
this.binWidth = width;
|
|
21074
|
+
this.binHeight = height;
|
|
21075
|
+
this.allowRotations = allowRotations;
|
|
21076
|
+
this.usedRectangles.length = 0;
|
|
21077
|
+
this.freeRectangles.length = 0;
|
|
21078
|
+
this.freeRectangles.push({
|
|
21079
|
+
...createNodeRect(),
|
|
21080
|
+
x: 0,
|
|
21081
|
+
y: 0,
|
|
21082
|
+
width,
|
|
21083
|
+
height
|
|
21084
|
+
});
|
|
21085
|
+
}
|
|
21086
|
+
insert(rect, method) {
|
|
21087
|
+
const newNode = this.scoreRect(rect, method);
|
|
21088
|
+
if (newNode.height === 0) return null;
|
|
21089
|
+
const placed = cloneNodeRect(newNode);
|
|
21090
|
+
this.placeRect(placed);
|
|
21091
|
+
return placed;
|
|
21092
|
+
}
|
|
21093
|
+
pack(rects, method) {
|
|
21094
|
+
const remaining = rects.map(cloneNodeRect);
|
|
21095
|
+
while (remaining.length > 0) {
|
|
21096
|
+
let bestIndex = -1;
|
|
21097
|
+
const bestNode = createNodeRect();
|
|
21098
|
+
bestNode.score1 = MAX_SCORE;
|
|
21099
|
+
bestNode.score2 = MAX_SCORE;
|
|
21100
|
+
for (let index = 0; index < remaining.length; index += 1) {
|
|
21101
|
+
const candidate = this.scoreRect(remaining[index], method);
|
|
21102
|
+
if (candidate.score1 < bestNode.score1 || candidate.score1 === bestNode.score1 && candidate.score2 < bestNode.score2) {
|
|
21103
|
+
copyNodeRect(bestNode, candidate);
|
|
21104
|
+
bestIndex = index;
|
|
21050
21105
|
}
|
|
21051
21106
|
}
|
|
21052
21107
|
if (bestIndex === -1) break;
|
|
@@ -21707,6 +21762,19 @@ const ATLAS_DEFAULTS = {
|
|
|
21707
21762
|
function getPublishedItemId(resource) {
|
|
21708
21763
|
return (resource.getExtras() ?? {})._publishedId ?? resource.getId();
|
|
21709
21764
|
}
|
|
21765
|
+
function getSelectedSkeletonDependencyImageIds(resources) {
|
|
21766
|
+
const imageIds = /* @__PURE__ */ new Set();
|
|
21767
|
+
const resourcesById = new Map(resources.map((resource) => [resource.getId(), resource]));
|
|
21768
|
+
for (const resource of resources) {
|
|
21769
|
+
if (!isSkeletonResource$1(resource)) continue;
|
|
21770
|
+
for (const requiredId of resource.getRequireIds()) {
|
|
21771
|
+
if (!requiredId) continue;
|
|
21772
|
+
const required = resourcesById.get(requiredId);
|
|
21773
|
+
if (required && isImageResource$1(required)) imageIds.add(requiredId);
|
|
21774
|
+
}
|
|
21775
|
+
}
|
|
21776
|
+
return imageIds;
|
|
21777
|
+
}
|
|
21710
21778
|
function resolveFontFileName(fontName) {
|
|
21711
21779
|
return /\.fnt$/i.test(fontName) ? fontName : `${fontName}.fnt`;
|
|
21712
21780
|
}
|
|
@@ -21843,12 +21911,18 @@ function atlas(_options = {}) {
|
|
|
21843
21911
|
const logger = doc.getLogger();
|
|
21844
21912
|
const encoder = options.encoder;
|
|
21845
21913
|
const doTrim = options.trimImage && !!encoder && !!options.basePath;
|
|
21914
|
+
const packageFilter = options.packages ? new Set(options.packages) : null;
|
|
21846
21915
|
for (const pkg of root.listPackages()) {
|
|
21916
|
+
if (packageFilter && !packageFilter.has(pkg.getName())) continue;
|
|
21847
21917
|
const selectedPublishIds = new Set((pkg.getExtras() ?? {}).publishedResourceIds ?? []);
|
|
21848
21918
|
const allResources = selectedPublishIds.size > 0 ? pkg.listResources().filter((resource) => selectedPublishIds.has(resource.getId())) : pkg.listResources();
|
|
21919
|
+
const skeletonDependencyImageIds = getSelectedSkeletonDependencyImageIds(allResources);
|
|
21849
21920
|
const orderedResources = await resolveEditorCompatibleResourceOrder(pkg, allResources, options);
|
|
21850
21921
|
const orderedAllResources = sortResourcesByOrder(allResources, new Map(orderedResources.map((resource, index) => [resource.getId(), index])), new Map(allResources.map((resource, index) => [resource.getId(), index])));
|
|
21851
|
-
if (!allResources.some((resource) =>
|
|
21922
|
+
if (!allResources.some((resource) => {
|
|
21923
|
+
if (isImageResource$1(resource) && skeletonDependencyImageIds.has(resource.getId())) return false;
|
|
21924
|
+
return isPackableResource(resource);
|
|
21925
|
+
})) continue;
|
|
21852
21926
|
const inputs = [];
|
|
21853
21927
|
const referencedIds = /* @__PURE__ */ new Set();
|
|
21854
21928
|
const resourceMap = /* @__PURE__ */ new Map();
|
|
@@ -21917,6 +21991,7 @@ function atlas(_options = {}) {
|
|
|
21917
21991
|
}
|
|
21918
21992
|
for (const res of orderedAllResources) if (isImageResource$1(res)) {
|
|
21919
21993
|
const resId = res.getId();
|
|
21994
|
+
if (skeletonDependencyImageIds.has(resId)) continue;
|
|
21920
21995
|
if (selectedPublishIds.size === 0 && !res.getExported() && referencedIds.size > 0 && !referencedIds.has(resId)) continue;
|
|
21921
21996
|
await _collectImage(res, pkg, inputs, encoder, options, doTrim, logger);
|
|
21922
21997
|
} else if (isMovieClipResource$1(res)) {
|
|
@@ -21929,137 +22004,59 @@ function atlas(_options = {}) {
|
|
|
21929
22004
|
await _collectFontTexture(doc, res, pkg, options);
|
|
21930
22005
|
}
|
|
21931
22006
|
if (inputs.length === 0) continue;
|
|
21932
|
-
const branchGroups = buildBranchAtlasGroups(doc, inputs, options);
|
|
21933
22007
|
let totalPageCount = 0;
|
|
21934
22008
|
let usedDirectOutput = false;
|
|
22009
|
+
const { autoInputs, fixedPageGroups, standaloneGroups, reservedPageIndexes } = groupStandaloneInputs(doc, inputs, options);
|
|
22010
|
+
const branchGroups = buildBranchAtlasGroups(doc, autoInputs, options);
|
|
22011
|
+
const branchPageOffsets = /* @__PURE__ */ new Map();
|
|
21935
22012
|
for (const group of branchGroups) {
|
|
21936
|
-
const directOutput = resolveDirectImageOutput(group.inputs, options);
|
|
22013
|
+
const directOutput = fixedPageGroups.length === 0 && standaloneGroups.length === 0 ? resolveDirectImageOutput(group.inputs, options) : null;
|
|
21937
22014
|
if (directOutput) {
|
|
21938
22015
|
await emitDirectImageOutput(doc, pkg, directOutput, encoder, options, logger, group.branchName, group.branchOrdinal);
|
|
21939
22016
|
usedDirectOutput = true;
|
|
21940
22017
|
totalPageCount += 1;
|
|
21941
22018
|
continue;
|
|
21942
22019
|
}
|
|
21943
|
-
const
|
|
21944
|
-
|
|
22020
|
+
const pageStart = reserveAutoPageStart(branchPageOffsets, group.branchOrdinal, reservedPageIndexes);
|
|
22021
|
+
const emittedPageCount = await emitPagedAtlasGroup(doc, pkg, allResources, group.inputs, {
|
|
22022
|
+
branchName: group.branchName,
|
|
22023
|
+
branchOrdinal: group.branchOrdinal,
|
|
22024
|
+
pageStart,
|
|
22025
|
+
fileNameAt: (pageIndex) => resolveAtlasOutputFileName(pkg, pageIndex, group.branchName),
|
|
22026
|
+
options,
|
|
22027
|
+
encoder,
|
|
22028
|
+
logger
|
|
21945
22029
|
});
|
|
21946
|
-
|
|
21947
|
-
|
|
21948
|
-
|
|
21949
|
-
|
|
21950
|
-
|
|
21951
|
-
|
|
21952
|
-
|
|
21953
|
-
|
|
21954
|
-
|
|
21955
|
-
|
|
21956
|
-
|
|
21957
|
-
|
|
21958
|
-
|
|
21959
|
-
|
|
21960
|
-
|
|
21961
|
-
|
|
21962
|
-
|
|
21963
|
-
|
|
21964
|
-
|
|
21965
|
-
|
|
21966
|
-
|
|
21967
|
-
|
|
21968
|
-
|
|
21969
|
-
|
|
21970
|
-
|
|
21971
|
-
|
|
21972
|
-
|
|
21973
|
-
|
|
21974
|
-
|
|
21975
|
-
|
|
21976
|
-
const rotated = pr.rotated;
|
|
21977
|
-
const sprite = doc.createSprite();
|
|
21978
|
-
sprite.setItemId(input.id);
|
|
21979
|
-
sprite.setRectX(pr.x);
|
|
21980
|
-
sprite.setRectY(pr.y);
|
|
21981
|
-
sprite.setRectWidth(packedSize.width);
|
|
21982
|
-
sprite.setRectHeight(packedSize.height);
|
|
21983
|
-
sprite.setRotated(rotated);
|
|
21984
|
-
sprite.setOffsetX(input.offsetX);
|
|
21985
|
-
sprite.setOffsetY(input.offsetY);
|
|
21986
|
-
sprite.setOriginalWidth(input.originalWidth);
|
|
21987
|
-
sprite.setOriginalHeight(input.originalHeight);
|
|
21988
|
-
sprite.setAtlas(atlasNode);
|
|
21989
|
-
atlasNode.addSprite(sprite);
|
|
21990
|
-
}
|
|
21991
|
-
for (const res of allResources) {
|
|
21992
|
-
if (!isFontResource$1(res)) continue;
|
|
21993
|
-
const alias = res.getExtras()?._fontSpriteAlias;
|
|
21994
|
-
if (!alias) continue;
|
|
21995
|
-
const imgSprite = page.outputRects.find((result) => group.inputs[result.index]?.id === alias.textureId);
|
|
21996
|
-
if (!imgSprite) continue;
|
|
21997
|
-
const imgInput = group.inputs[imgSprite.index];
|
|
21998
|
-
const fontSprite = doc.createSprite();
|
|
21999
|
-
fontSprite.setItemId(alias.fontId);
|
|
22000
|
-
fontSprite.setRectX(imgSprite.x);
|
|
22001
|
-
fontSprite.setRectY(imgSprite.y);
|
|
22002
|
-
fontSprite.setRectWidth(imgSprite.width);
|
|
22003
|
-
fontSprite.setRectHeight(imgSprite.height);
|
|
22004
|
-
fontSprite.setRotated(imgSprite.rotated);
|
|
22005
|
-
if (imgInput) {
|
|
22006
|
-
fontSprite.setOffsetX(imgInput.offsetX);
|
|
22007
|
-
fontSprite.setOffsetY(imgInput.offsetY);
|
|
22008
|
-
fontSprite.setOriginalWidth(imgInput.originalWidth);
|
|
22009
|
-
fontSprite.setOriginalHeight(imgInput.originalHeight);
|
|
22010
|
-
}
|
|
22011
|
-
fontSprite.setAtlas(atlasNode);
|
|
22012
|
-
atlasNode.addSprite(fontSprite);
|
|
22013
|
-
}
|
|
22014
|
-
}
|
|
22015
|
-
if (encoder && options.outputPath) {
|
|
22016
|
-
if (options.mkdir) await options.mkdir(options.outputPath);
|
|
22017
|
-
for (let p = 0; p < pages.length; p++) {
|
|
22018
|
-
const page = pages[p];
|
|
22019
|
-
const compositeInputs = [];
|
|
22020
|
-
for (const pr of page.outputRects) {
|
|
22021
|
-
const input = group.inputs[pr.index];
|
|
22022
|
-
if (!input) continue;
|
|
22023
|
-
if (pr.width <= 0 || pr.height <= 0 || input.width <= 0 || input.height <= 0) continue;
|
|
22024
|
-
try {
|
|
22025
|
-
let imgBuffer;
|
|
22026
|
-
if (input.trimBuffer) {
|
|
22027
|
-
imgBuffer = input.trimBuffer;
|
|
22028
|
-
if (imgBuffer.length === 0) continue;
|
|
22029
|
-
} else if (input.rasterizedBuffer) imgBuffer = input.rasterizedBuffer;
|
|
22030
|
-
else {
|
|
22031
|
-
if (!isImageResource$1(input.resource)) {
|
|
22032
|
-
logger.warn(`atlas: Non-image input "${input.id}" is missing inline buffer, skipping compositing.`);
|
|
22033
|
-
continue;
|
|
22034
|
-
}
|
|
22035
|
-
imgBuffer = await encoder(_resolveImagePath(input.resource, pkg, options.basePath)).toBuffer();
|
|
22036
|
-
}
|
|
22037
|
-
if (pr.rotated) imgBuffer = await encoder(imgBuffer).rotate(270).toBuffer();
|
|
22038
|
-
compositeInputs.push({
|
|
22039
|
-
input: imgBuffer,
|
|
22040
|
-
left: pr.x,
|
|
22041
|
-
top: pr.y
|
|
22042
|
-
});
|
|
22043
|
-
} catch {
|
|
22044
|
-
logger.warn(`atlas: Could not read image "${input.id}" for compositing.`);
|
|
22045
|
-
}
|
|
22046
|
-
}
|
|
22047
|
-
const atlasFileName = resolveAtlasOutputFileName(pkg, p, group.branchName);
|
|
22048
|
-
const outputFile = `${options.outputPath}/${atlasFileName}`;
|
|
22049
|
-
await encoder({ create: {
|
|
22050
|
-
width: page.width,
|
|
22051
|
-
height: page.height,
|
|
22052
|
-
channels: 4,
|
|
22053
|
-
background: {
|
|
22054
|
-
r: 0,
|
|
22055
|
-
g: 0,
|
|
22056
|
-
b: 0,
|
|
22057
|
-
alpha: 0
|
|
22058
|
-
}
|
|
22059
|
-
} }).composite(compositeInputs).png().toFile(outputFile);
|
|
22060
|
-
logger.info(`atlas: Generated ${atlasFileName} (${page.width}x${page.height}, ${page.outputRects.length} sprites)`);
|
|
22061
|
-
}
|
|
22062
|
-
}
|
|
22030
|
+
totalPageCount += emittedPageCount;
|
|
22031
|
+
branchPageOffsets.set(group.branchOrdinal, pageStart + emittedPageCount);
|
|
22032
|
+
}
|
|
22033
|
+
for (const group of fixedPageGroups) {
|
|
22034
|
+
const emittedPageCount = await emitPagedAtlasGroup(doc, pkg, allResources, group.inputs, {
|
|
22035
|
+
branchName: group.branchName,
|
|
22036
|
+
branchOrdinal: group.branchOrdinal,
|
|
22037
|
+
pageStart: group.pageIndex,
|
|
22038
|
+
forceSinglePage: true,
|
|
22039
|
+
fileNameAt: () => resolveAtlasOutputFileName(pkg, group.pageIndex, group.branchName),
|
|
22040
|
+
options,
|
|
22041
|
+
encoder,
|
|
22042
|
+
logger
|
|
22043
|
+
});
|
|
22044
|
+
totalPageCount += emittedPageCount;
|
|
22045
|
+
}
|
|
22046
|
+
const standalonePageOffsets = new Map(branchPageOffsets);
|
|
22047
|
+
for (const group of fixedPageGroups) {
|
|
22048
|
+
const nextPageIndex = group.pageIndex + 1;
|
|
22049
|
+
if (nextPageIndex > (standalonePageOffsets.get(group.branchOrdinal) ?? 0)) standalonePageOffsets.set(group.branchOrdinal, nextPageIndex);
|
|
22050
|
+
}
|
|
22051
|
+
for (const group of standaloneGroups) {
|
|
22052
|
+
const emittedPageCount = await emitStandaloneAtlasGroup(doc, pkg, group, {
|
|
22053
|
+
atlasIndexStart: standalonePageOffsets.get(group.branchOrdinal) ?? 0,
|
|
22054
|
+
options,
|
|
22055
|
+
encoder,
|
|
22056
|
+
logger
|
|
22057
|
+
});
|
|
22058
|
+
totalPageCount += emittedPageCount;
|
|
22059
|
+
standalonePageOffsets.set(group.branchOrdinal, (standalonePageOffsets.get(group.branchOrdinal) ?? 0) + emittedPageCount);
|
|
22063
22060
|
}
|
|
22064
22061
|
if (usedDirectOutput) logger.info(`atlas: Direct output for single image package "${pkg.getName()}".`);
|
|
22065
22062
|
logger.info(`atlas: Packed ${inputs.length} images into ${totalPageCount} atlas(es) for package "${pkg.getName()}".`);
|
|
@@ -22096,6 +22093,171 @@ function buildBranchAtlasGroups(doc, inputs, options) {
|
|
|
22096
22093
|
inputs: groups.get(branchName) ?? []
|
|
22097
22094
|
}));
|
|
22098
22095
|
}
|
|
22096
|
+
function reserveAutoPageStart(branchPageOffsets, branchOrdinal, reservedPageIndexes) {
|
|
22097
|
+
let pageIndex = branchPageOffsets.get(branchOrdinal) ?? 0;
|
|
22098
|
+
while (branchOrdinal === 0 && reservedPageIndexes.has(pageIndex)) pageIndex += 1;
|
|
22099
|
+
return pageIndex;
|
|
22100
|
+
}
|
|
22101
|
+
async function emitPagedAtlasGroup(doc, pkg, allResources, inputs, context) {
|
|
22102
|
+
if (inputs.length === 0) return 0;
|
|
22103
|
+
const pages = packAtlasPages(inputs, context.options, context.forceSinglePage === true);
|
|
22104
|
+
if (pages.length === 0) return 0;
|
|
22105
|
+
for (let pageOffset = 0; pageOffset < pages.length; pageOffset += 1) {
|
|
22106
|
+
const page = pages[pageOffset];
|
|
22107
|
+
const pageIndex = context.pageStart + pageOffset;
|
|
22108
|
+
const atlasNode = doc.createAtlas(`atlas${resolveAtlasIndex(context.branchOrdinal, pageIndex)}`);
|
|
22109
|
+
atlasNode.setIndex(resolveAtlasIndex(context.branchOrdinal, pageIndex));
|
|
22110
|
+
atlasNode.setFile(context.fileNameAt(pageIndex));
|
|
22111
|
+
atlasNode.setWidth(page.width);
|
|
22112
|
+
atlasNode.setHeight(page.height);
|
|
22113
|
+
pkg.addAtlas(atlasNode);
|
|
22114
|
+
attachSpritesToAtlas(doc, allResources, inputs, page.outputRects, atlasNode);
|
|
22115
|
+
await writeAtlasPageImage(pkg, inputs, page, atlasNode.getFile(), context.encoder, context.options, context.logger);
|
|
22116
|
+
}
|
|
22117
|
+
return pages.length;
|
|
22118
|
+
}
|
|
22119
|
+
async function emitStandaloneAtlasGroup(doc, pkg, group, context) {
|
|
22120
|
+
if (group.inputs.length === 0) return 0;
|
|
22121
|
+
const pages = packAtlasPages(group.inputs, context.options, true, group.sizeMode === "npot" ? {
|
|
22122
|
+
powerOfTwo: false,
|
|
22123
|
+
multipleOfFour: false,
|
|
22124
|
+
square: false
|
|
22125
|
+
} : group.sizeMode === "multipleOf4" ? {
|
|
22126
|
+
powerOfTwo: false,
|
|
22127
|
+
multipleOfFour: true,
|
|
22128
|
+
square: false
|
|
22129
|
+
} : void 0);
|
|
22130
|
+
if (pages.length === 0) return 0;
|
|
22131
|
+
for (let pageOffset = 0; pageOffset < pages.length; pageOffset += 1) {
|
|
22132
|
+
const page = pages[pageOffset];
|
|
22133
|
+
const baseFileName = resolveStandaloneAtlasOutputFileName(pkg, group.resource, group.branchName);
|
|
22134
|
+
const atlasFileName = pages.length <= 1 ? baseFileName : insertFileNameSuffix(baseFileName, `_${pageOffset}`);
|
|
22135
|
+
const atlasIndex = context.atlasIndexStart + pageOffset;
|
|
22136
|
+
const atlasNode = doc.createAtlas(`atlas${resolveAtlasIndex(group.branchOrdinal, atlasIndex)}`);
|
|
22137
|
+
atlasNode.setIndex(resolveAtlasIndex(group.branchOrdinal, atlasIndex));
|
|
22138
|
+
atlasNode.setFile(atlasFileName);
|
|
22139
|
+
const standaloneSize = resolveStandaloneAtlasSize(page.width, page.height, group.sizeMode, context.options);
|
|
22140
|
+
atlasNode.setWidth(standaloneSize.width);
|
|
22141
|
+
atlasNode.setHeight(standaloneSize.height);
|
|
22142
|
+
pkg.addAtlas(atlasNode);
|
|
22143
|
+
attachSpritesToAtlas(doc, [], group.inputs, page.outputRects, atlasNode);
|
|
22144
|
+
await writeAtlasPageImage(pkg, group.inputs, {
|
|
22145
|
+
...page,
|
|
22146
|
+
width: standaloneSize.width,
|
|
22147
|
+
height: standaloneSize.height
|
|
22148
|
+
}, atlasFileName, context.encoder, context.options, context.logger);
|
|
22149
|
+
}
|
|
22150
|
+
return pages.length;
|
|
22151
|
+
}
|
|
22152
|
+
function packAtlasPages(inputs, options, forceSinglePage, sizeOverrides) {
|
|
22153
|
+
const hasDuplicatePadding = inputs.some((input) => {
|
|
22154
|
+
return isImageResource$1(input.resource) && input.resource.getDuplicatePadding?.() === true;
|
|
22155
|
+
});
|
|
22156
|
+
return new MaxRectsPackerCompat({
|
|
22157
|
+
pot: sizeOverrides?.powerOfTwo ?? options.powerOfTwo,
|
|
22158
|
+
mof: sizeOverrides?.multipleOfFour ?? !options.powerOfTwo,
|
|
22159
|
+
padding: options.padding,
|
|
22160
|
+
rotation: options.allowRotation,
|
|
22161
|
+
minWidth: 16,
|
|
22162
|
+
minHeight: 16,
|
|
22163
|
+
maxWidth: options.maxSize,
|
|
22164
|
+
maxHeight: options.maxSize,
|
|
22165
|
+
square: sizeOverrides?.square ?? options.square,
|
|
22166
|
+
fast: options.fast,
|
|
22167
|
+
edgePadding: false,
|
|
22168
|
+
duplicatePadding: hasDuplicatePadding,
|
|
22169
|
+
multiPage: forceSinglePage ? false : options.multiPage,
|
|
22170
|
+
preserveInputOrderOnTie: options.preserveInputOrderOnTie
|
|
22171
|
+
}).pack(inputs.map((input, index) => inputToCompatRect(input, index))) ?? [];
|
|
22172
|
+
}
|
|
22173
|
+
function attachSpritesToAtlas(doc, allResources, inputs, outputRects, atlasNode) {
|
|
22174
|
+
for (const packedRect of outputRects) {
|
|
22175
|
+
const input = inputs[packedRect.index];
|
|
22176
|
+
if (!input) continue;
|
|
22177
|
+
const packedSize = resolvePackedRectSize(input, packedRect.width, packedRect.height, packedRect.rotated);
|
|
22178
|
+
const sprite = doc.createSprite();
|
|
22179
|
+
sprite.setItemId(input.id);
|
|
22180
|
+
sprite.setRectX(packedRect.x);
|
|
22181
|
+
sprite.setRectY(packedRect.y);
|
|
22182
|
+
sprite.setRectWidth(packedSize.width);
|
|
22183
|
+
sprite.setRectHeight(packedSize.height);
|
|
22184
|
+
sprite.setRotated(packedRect.rotated);
|
|
22185
|
+
sprite.setOffsetX(input.offsetX);
|
|
22186
|
+
sprite.setOffsetY(input.offsetY);
|
|
22187
|
+
sprite.setOriginalWidth(input.originalWidth);
|
|
22188
|
+
sprite.setOriginalHeight(input.originalHeight);
|
|
22189
|
+
sprite.setAtlas(atlasNode);
|
|
22190
|
+
atlasNode.addSprite(sprite);
|
|
22191
|
+
}
|
|
22192
|
+
for (const resource of allResources) {
|
|
22193
|
+
if (!isFontResource$1(resource)) continue;
|
|
22194
|
+
const alias = resource.getExtras()?._fontSpriteAlias;
|
|
22195
|
+
if (!alias) continue;
|
|
22196
|
+
const imageSprite = outputRects.find((result) => inputs[result.index]?.id === alias.textureId);
|
|
22197
|
+
if (!imageSprite) continue;
|
|
22198
|
+
const imageInput = inputs[imageSprite.index];
|
|
22199
|
+
const fontSprite = doc.createSprite();
|
|
22200
|
+
fontSprite.setItemId(alias.fontId);
|
|
22201
|
+
fontSprite.setRectX(imageSprite.x);
|
|
22202
|
+
fontSprite.setRectY(imageSprite.y);
|
|
22203
|
+
fontSprite.setRectWidth(imageSprite.width);
|
|
22204
|
+
fontSprite.setRectHeight(imageSprite.height);
|
|
22205
|
+
fontSprite.setRotated(imageSprite.rotated);
|
|
22206
|
+
if (imageInput) {
|
|
22207
|
+
fontSprite.setOffsetX(imageInput.offsetX);
|
|
22208
|
+
fontSprite.setOffsetY(imageInput.offsetY);
|
|
22209
|
+
fontSprite.setOriginalWidth(imageInput.originalWidth);
|
|
22210
|
+
fontSprite.setOriginalHeight(imageInput.originalHeight);
|
|
22211
|
+
}
|
|
22212
|
+
fontSprite.setAtlas(atlasNode);
|
|
22213
|
+
atlasNode.addSprite(fontSprite);
|
|
22214
|
+
}
|
|
22215
|
+
}
|
|
22216
|
+
async function writeAtlasPageImage(pkg, inputs, page, atlasFileName, encoder, options, logger) {
|
|
22217
|
+
if (!encoder || !options.outputPath) return;
|
|
22218
|
+
if (options.mkdir) await options.mkdir(options.outputPath);
|
|
22219
|
+
const compositeInputs = [];
|
|
22220
|
+
for (const packedRect of page.outputRects) {
|
|
22221
|
+
const input = inputs[packedRect.index];
|
|
22222
|
+
if (!input) continue;
|
|
22223
|
+
if (packedRect.width <= 0 || packedRect.height <= 0 || input.width <= 0 || input.height <= 0) continue;
|
|
22224
|
+
try {
|
|
22225
|
+
let imageBuffer;
|
|
22226
|
+
if (input.trimBuffer) {
|
|
22227
|
+
imageBuffer = input.trimBuffer;
|
|
22228
|
+
if (imageBuffer.length === 0) continue;
|
|
22229
|
+
} else if (input.rasterizedBuffer) imageBuffer = input.rasterizedBuffer;
|
|
22230
|
+
else {
|
|
22231
|
+
if (!isImageResource$1(input.resource)) {
|
|
22232
|
+
logger.warn(`atlas: Non-image input "${input.id}" is missing inline buffer, skipping compositing.`);
|
|
22233
|
+
continue;
|
|
22234
|
+
}
|
|
22235
|
+
imageBuffer = await encoder(_resolveImagePath(input.resource, pkg, options.basePath)).toBuffer();
|
|
22236
|
+
}
|
|
22237
|
+
if (packedRect.rotated) imageBuffer = await encoder(imageBuffer).rotate(270).toBuffer();
|
|
22238
|
+
compositeInputs.push({
|
|
22239
|
+
input: imageBuffer,
|
|
22240
|
+
left: packedRect.x,
|
|
22241
|
+
top: packedRect.y
|
|
22242
|
+
});
|
|
22243
|
+
} catch {
|
|
22244
|
+
logger.warn(`atlas: Could not read image "${input.id}" for compositing.`);
|
|
22245
|
+
}
|
|
22246
|
+
}
|
|
22247
|
+
const outputFile = `${options.outputPath}/${atlasFileName}`;
|
|
22248
|
+
await encoder({ create: {
|
|
22249
|
+
width: page.width,
|
|
22250
|
+
height: page.height,
|
|
22251
|
+
channels: 4,
|
|
22252
|
+
background: {
|
|
22253
|
+
r: 0,
|
|
22254
|
+
g: 0,
|
|
22255
|
+
b: 0,
|
|
22256
|
+
alpha: 0
|
|
22257
|
+
}
|
|
22258
|
+
} }).composite(compositeInputs).toFile(outputFile);
|
|
22259
|
+
logger.info(`atlas: Generated ${atlasFileName} (${page.width}x${page.height}, ${page.outputRects.length} sprites)`);
|
|
22260
|
+
}
|
|
22099
22261
|
function inputToCompatRect(input, index) {
|
|
22100
22262
|
const duplicatePadding = isImageResource$1(input.resource) && input.resource.getDuplicatePadding?.() === true;
|
|
22101
22263
|
return {
|
|
@@ -22210,14 +22372,47 @@ function resolveAtlasOutputFileName(pkg, pageIndex, branchName) {
|
|
|
22210
22372
|
const suffix = branchName ? `_${branchName}` : "";
|
|
22211
22373
|
return `${pkg.getPublishName() || pkg.getName()}_atlas${pageIndex}${suffix}.png`;
|
|
22212
22374
|
}
|
|
22375
|
+
function resolveStandaloneAtlasOutputFileName(pkg, resource, branchName) {
|
|
22376
|
+
const baseName = `${pkg.getPublishName() || pkg.getName()}_atlas_${getPublishedItemId(resource)}`;
|
|
22377
|
+
const suffix = branchName ? `_${branchName}` : "";
|
|
22378
|
+
if (isImageResource$1(resource)) return `${baseName}${suffix}${extname$1(resolveImageFileName$1(resource)) || ".png"}`;
|
|
22379
|
+
return `${baseName}${suffix}.png`;
|
|
22380
|
+
}
|
|
22381
|
+
function resolveStandaloneAtlasSize(width, height, sizeMode, options) {
|
|
22382
|
+
if (sizeMode === "npot") return {
|
|
22383
|
+
width,
|
|
22384
|
+
height
|
|
22385
|
+
};
|
|
22386
|
+
if (sizeMode === "multipleOf4") return {
|
|
22387
|
+
width: roundUpToMultiple(width, 4),
|
|
22388
|
+
height: roundUpToMultiple(height, 4)
|
|
22389
|
+
};
|
|
22390
|
+
return resolveDirectOutputAtlasSize(width, height, options);
|
|
22391
|
+
}
|
|
22213
22392
|
function resolveImageFileName$1(resource) {
|
|
22214
22393
|
const extras = resource.getExtras();
|
|
22215
22394
|
return resource.getFileName() || extras._fileName || resource.getName();
|
|
22216
22395
|
}
|
|
22396
|
+
function extname$1(fileName) {
|
|
22397
|
+
const normalized = fileName.replace(/\\/g, "/");
|
|
22398
|
+
const lastSlash = normalized.lastIndexOf("/");
|
|
22399
|
+
const lastDot = normalized.lastIndexOf(".");
|
|
22400
|
+
if (lastDot <= lastSlash) return "";
|
|
22401
|
+
return normalized.slice(lastDot);
|
|
22402
|
+
}
|
|
22403
|
+
function insertFileNameSuffix(fileName, suffix) {
|
|
22404
|
+
const extension = extname$1(fileName);
|
|
22405
|
+
if (!extension) return `${fileName}${suffix}`;
|
|
22406
|
+
return `${fileName.slice(0, -extension.length)}${suffix}${extension}`;
|
|
22407
|
+
}
|
|
22217
22408
|
function nextPow2(value) {
|
|
22218
22409
|
if (value <= 1) return 1;
|
|
22219
22410
|
return 2 ** Math.ceil(Math.log2(value));
|
|
22220
22411
|
}
|
|
22412
|
+
function roundUpToMultiple(value, base) {
|
|
22413
|
+
if (value <= 0) return 0;
|
|
22414
|
+
return Math.ceil(value / base) * base;
|
|
22415
|
+
}
|
|
22221
22416
|
function sortResourcesByOrder(resources, orderMap, inputOrderMap) {
|
|
22222
22417
|
const ordered = [...resources];
|
|
22223
22418
|
ordered.sort((left, right) => {
|
|
@@ -22233,6 +22428,63 @@ function sortResourcesByOrder(resources, orderMap, inputOrderMap) {
|
|
|
22233
22428
|
});
|
|
22234
22429
|
return ordered;
|
|
22235
22430
|
}
|
|
22431
|
+
function getResourceTextureSetMode(resource) {
|
|
22432
|
+
if (isImageResource$1(resource)) return parseTextureSetMode(resource.getTextureSetMode?.());
|
|
22433
|
+
return parseTextureSetMode(resource.getTextureSetMode?.());
|
|
22434
|
+
}
|
|
22435
|
+
function groupStandaloneInputs(doc, inputs, options) {
|
|
22436
|
+
const autoInputs = [];
|
|
22437
|
+
const fixedInputsByPage = /* @__PURE__ */ new Map();
|
|
22438
|
+
const standaloneGroups = /* @__PURE__ */ new Map();
|
|
22439
|
+
const reservedPageIndexes = /* @__PURE__ */ new Set();
|
|
22440
|
+
const discoveredBranchNames = [...new Set(inputs.map((input) => getInputBranchName(input)).filter((branchName) => !!branchName))];
|
|
22441
|
+
const orderedBranchNames = doc.getRoot().listBranches().filter((branchName) => discoveredBranchNames.includes(branchName));
|
|
22442
|
+
for (const branchName of discoveredBranchNames) if (!orderedBranchNames.includes(branchName)) orderedBranchNames.push(branchName);
|
|
22443
|
+
const branchOrdinalByName = /* @__PURE__ */ new Map();
|
|
22444
|
+
branchOrdinalByName.set("", 0);
|
|
22445
|
+
if (options.separatedAtlasForBranch) {
|
|
22446
|
+
let ordinal = 1;
|
|
22447
|
+
for (const branchName of orderedBranchNames) branchOrdinalByName.set(branchName, ordinal++);
|
|
22448
|
+
} else for (const branchName of orderedBranchNames) branchOrdinalByName.set(branchName, 0);
|
|
22449
|
+
for (const input of inputs) {
|
|
22450
|
+
const branchName = getInputBranchName(input);
|
|
22451
|
+
const branchOrdinal = branchOrdinalByName.get(branchName) ?? 0;
|
|
22452
|
+
const mode = getResourceTextureSetMode(input.resource);
|
|
22453
|
+
if (mode.kind === "standalone") {
|
|
22454
|
+
const key = `${branchName}\u0000${getPublishedItemId(input.resource)}`;
|
|
22455
|
+
const existing = standaloneGroups.get(key);
|
|
22456
|
+
if (existing) existing.inputs.push(input);
|
|
22457
|
+
else standaloneGroups.set(key, {
|
|
22458
|
+
resource: input.resource,
|
|
22459
|
+
branchName,
|
|
22460
|
+
branchOrdinal,
|
|
22461
|
+
sizeMode: mode.sizeMode,
|
|
22462
|
+
inputs: [input]
|
|
22463
|
+
});
|
|
22464
|
+
continue;
|
|
22465
|
+
}
|
|
22466
|
+
if (mode.kind === "page") {
|
|
22467
|
+
reservedPageIndexes.add(mode.pageIndex);
|
|
22468
|
+
const key = `${branchName}\u0000${mode.pageIndex}`;
|
|
22469
|
+
const existing = fixedInputsByPage.get(key);
|
|
22470
|
+
if (existing) existing.inputs.push(input);
|
|
22471
|
+
else fixedInputsByPage.set(key, {
|
|
22472
|
+
pageIndex: mode.pageIndex,
|
|
22473
|
+
branchName,
|
|
22474
|
+
branchOrdinal,
|
|
22475
|
+
inputs: [input]
|
|
22476
|
+
});
|
|
22477
|
+
continue;
|
|
22478
|
+
}
|
|
22479
|
+
autoInputs.push(input);
|
|
22480
|
+
}
|
|
22481
|
+
return {
|
|
22482
|
+
autoInputs,
|
|
22483
|
+
fixedPageGroups: [...fixedInputsByPage.values()].sort((left, right) => left.branchOrdinal - right.branchOrdinal || left.pageIndex - right.pageIndex),
|
|
22484
|
+
standaloneGroups: [...standaloneGroups.values()].sort((left, right) => left.branchOrdinal - right.branchOrdinal || getPublishedItemId(left.resource).localeCompare(getPublishedItemId(right.resource))),
|
|
22485
|
+
reservedPageIndexes
|
|
22486
|
+
};
|
|
22487
|
+
}
|
|
22236
22488
|
/**
|
|
22237
22489
|
* Trim transparent edges from an image using sharp.
|
|
22238
22490
|
* Returns the trimmed buffer, dimensions, and offsets.
|
|
@@ -22793,6 +23045,62 @@ const FGUI_TYPESCRIPT_BINDER_TEMPLATE = `{{generatedMark}}
|
|
|
22793
23045
|
}
|
|
22794
23046
|
`;
|
|
22795
23047
|
//#endregion
|
|
23048
|
+
//#region ../functions/src/plugins/loader.ts
|
|
23049
|
+
const importNative = new Function("id", "return import(id)");
|
|
23050
|
+
async function loadPlugins(doc, pluginsDir) {
|
|
23051
|
+
if (!pluginsDir) return [];
|
|
23052
|
+
const fs = await importNative("node:fs/promises");
|
|
23053
|
+
const path = await importNative("node:path");
|
|
23054
|
+
let entries;
|
|
23055
|
+
try {
|
|
23056
|
+
entries = await fs.readdir(pluginsDir, { withFileTypes: true });
|
|
23057
|
+
} catch {
|
|
23058
|
+
return [];
|
|
23059
|
+
}
|
|
23060
|
+
const plugins = [];
|
|
23061
|
+
for (const entry of entries) {
|
|
23062
|
+
if (!entry.isDirectory()) continue;
|
|
23063
|
+
const pluginDir = path.join(pluginsDir, entry.name);
|
|
23064
|
+
try {
|
|
23065
|
+
const manifest = await readPluginManifest(fs, path, pluginDir);
|
|
23066
|
+
if (!manifest) continue;
|
|
23067
|
+
const plugin = await loadPlugin(resolvePluginMain(path, pluginDir, manifest));
|
|
23068
|
+
plugins.push({
|
|
23069
|
+
name: manifest.name,
|
|
23070
|
+
plugin
|
|
23071
|
+
});
|
|
23072
|
+
} catch (error) {
|
|
23073
|
+
doc.getLogger().warn(`publish: Plugin "${entry.name}" was skipped: ${formatPluginError(error)}`);
|
|
23074
|
+
}
|
|
23075
|
+
}
|
|
23076
|
+
return plugins;
|
|
23077
|
+
}
|
|
23078
|
+
function formatPluginError(error) {
|
|
23079
|
+
return error instanceof Error ? error.message : String(error);
|
|
23080
|
+
}
|
|
23081
|
+
async function readPluginManifest(fs, path, pluginDir) {
|
|
23082
|
+
const manifestPath = path.join(pluginDir, "package.json");
|
|
23083
|
+
const content = await fs.readFile(manifestPath, "utf-8");
|
|
23084
|
+
const manifest = JSON.parse(content);
|
|
23085
|
+
if (!manifest.name) throw new Error(`Codegen plugin at ${pluginDir} is missing package.json name.`);
|
|
23086
|
+
if (!manifest.main) throw new Error(`Codegen plugin "${manifest.name}" is missing package.json main.`);
|
|
23087
|
+
return manifest;
|
|
23088
|
+
}
|
|
23089
|
+
function resolvePluginMain(path, pluginDir, manifest) {
|
|
23090
|
+
const mainPath = path.resolve(pluginDir, manifest.main);
|
|
23091
|
+
const relative = path.relative(pluginDir, mainPath);
|
|
23092
|
+
if (relative.startsWith("..") || path.isAbsolute(relative)) throw new Error(`Codegen plugin "${manifest.name}" main must resolve inside its plugin directory.`);
|
|
23093
|
+
return mainPath;
|
|
23094
|
+
}
|
|
23095
|
+
async function loadPlugin(mainPath) {
|
|
23096
|
+
const mod = await createJiti(import.meta.url).import(mainPath);
|
|
23097
|
+
const defaultExport = mod.default;
|
|
23098
|
+
return isObject(defaultExport) ? defaultExport : mod;
|
|
23099
|
+
}
|
|
23100
|
+
function isObject(value) {
|
|
23101
|
+
return value !== null && typeof value === "object";
|
|
23102
|
+
}
|
|
23103
|
+
//#endregion
|
|
22796
23104
|
//#region ../functions/src/codegen.ts
|
|
22797
23105
|
const AUTO_GENERATED_CODE_MARK = "/** This is an automatically generated class by FairyGUI. Please do not modify it. **/";
|
|
22798
23106
|
const DEFAULT_CLASS_NAME_PREFIX = "UI_";
|
|
@@ -22828,6 +23136,18 @@ async function publishCodeGeneration(doc, options) {
|
|
|
22828
23136
|
const logger = doc.getLogger();
|
|
22829
23137
|
const settings = resolveCodeGenerationSettings(doc);
|
|
22830
23138
|
if (!settings.allowGenCode) return;
|
|
23139
|
+
const plugins = options.plugins?.filter((plugin) => typeof plugin.plugin.genCode === "function") ?? [];
|
|
23140
|
+
if (plugins.length > 0) {
|
|
23141
|
+
let handled = false;
|
|
23142
|
+
for (const plugin of plugins) try {
|
|
23143
|
+
await plugin.plugin.genCode(doc, settings, options);
|
|
23144
|
+
handled = true;
|
|
23145
|
+
logger.info(`publish: Generated code using plugin "${plugin.name}"`);
|
|
23146
|
+
} catch (error) {
|
|
23147
|
+
logger.warn(`publish: Code generation plugin "${plugin.name}" failed: ${formatPluginError(error)}`);
|
|
23148
|
+
}
|
|
23149
|
+
if (handled) return;
|
|
23150
|
+
}
|
|
22831
23151
|
for (const pkg of options.packages) {
|
|
22832
23152
|
if (!pkg.getGenCode()) continue;
|
|
22833
23153
|
const plan = resolvePackageCodegenPlan(pkg, settings, options);
|
|
@@ -22926,9 +23246,9 @@ async function cleanupGeneratedFiles(directory, fs, extension = ".cs") {
|
|
|
22926
23246
|
}
|
|
22927
23247
|
}
|
|
22928
23248
|
function buildCodegenClasses(doc, pkg, plan) {
|
|
22929
|
-
const
|
|
23249
|
+
const codegenComponents = pkg.listComponents().sort((left, right) => left.getId().localeCompare(right.getId()));
|
|
22930
23250
|
const generatedById = /* @__PURE__ */ new Map();
|
|
22931
|
-
for (const component of
|
|
23251
|
+
for (const component of codegenComponents) {
|
|
22932
23252
|
const encodedClassName = `${plan.settings.classNamePrefix}${normalizeTypeName(component.getName()) || "Component"}`;
|
|
22933
23253
|
generatedById.set(component.getId(), {
|
|
22934
23254
|
classId: component.getId(),
|
|
@@ -22941,7 +23261,13 @@ function buildCodegenClasses(doc, pkg, plan) {
|
|
|
22941
23261
|
members: []
|
|
22942
23262
|
});
|
|
22943
23263
|
}
|
|
22944
|
-
for (const component of
|
|
23264
|
+
for (const component of codegenComponents) {
|
|
23265
|
+
const classInfo = generatedById.get(component.getId());
|
|
23266
|
+
if (!classInfo) continue;
|
|
23267
|
+
classInfo.members = buildCodegenMembers(doc, pkg, component, plan, generatedById);
|
|
23268
|
+
}
|
|
23269
|
+
for (const [componentId, classInfo] of generatedById) if (classInfo.members.every((member) => member.ignored)) generatedById.delete(componentId);
|
|
23270
|
+
for (const component of codegenComponents) {
|
|
22945
23271
|
const classInfo = generatedById.get(component.getId());
|
|
22946
23272
|
if (!classInfo) continue;
|
|
22947
23273
|
classInfo.members = buildCodegenMembers(doc, pkg, component, plan, generatedById);
|
|
@@ -22955,7 +23281,12 @@ function buildCodegenMembers(doc, pkg, component, plan, generatedById) {
|
|
|
22955
23281
|
let childIndex = 0;
|
|
22956
23282
|
let transitionIndex = 0;
|
|
22957
23283
|
for (const controller of component.listControllers()) members.push(createMember(ownerType, "controller", "Controller", controller.getName(), controllerIndex++, plan));
|
|
22958
|
-
for (const child of component.listChildren())
|
|
23284
|
+
for (const child of component.listChildren()) {
|
|
23285
|
+
if (!isRuntimeChild(child)) continue;
|
|
23286
|
+
const index = childIndex++;
|
|
23287
|
+
const resolvedChild = resolveChildType(doc, pkg, child, generatedById);
|
|
23288
|
+
members.push(createMember(ownerType, "child", resolvedChild.type, child.getName(), index, plan, resolvedChild.referencedComponent));
|
|
23289
|
+
}
|
|
22959
23290
|
for (const transition of component.listTransitions()) members.push(createMember(ownerType, "transition", "Transition", transition.getName(), transitionIndex++, plan));
|
|
22960
23291
|
const usedNames = /* @__PURE__ */ new Map();
|
|
22961
23292
|
for (const member of members) {
|
|
@@ -22967,7 +23298,10 @@ function buildCodegenMembers(doc, pkg, component, plan, generatedById) {
|
|
|
22967
23298
|
}
|
|
22968
23299
|
return members;
|
|
22969
23300
|
}
|
|
22970
|
-
function
|
|
23301
|
+
function isRuntimeChild(child) {
|
|
23302
|
+
return child.propertyType !== "GGroup" || child.getAdvanced?.() === true;
|
|
23303
|
+
}
|
|
23304
|
+
function createMember(ownerType, kind, type, originalName, index, plan, referencedComponent) {
|
|
22971
23305
|
const ignored = plan.settings.ignoreNoname && isDefaultMemberName(ownerType, kind, originalName);
|
|
22972
23306
|
return {
|
|
22973
23307
|
index,
|
|
@@ -22975,30 +23309,41 @@ function createMember(ownerType, kind, type, originalName, index, plan) {
|
|
|
22975
23309
|
name: applyMemberNamePrefix(originalName, plan.settings.memberNamePrefix),
|
|
22976
23310
|
originalName,
|
|
22977
23311
|
type,
|
|
22978
|
-
ignored
|
|
23312
|
+
ignored,
|
|
23313
|
+
referencedComponent
|
|
22979
23314
|
};
|
|
22980
23315
|
}
|
|
22981
23316
|
function resolveChildType(doc, pkg, child, generatedById) {
|
|
22982
23317
|
const src = child.getSrc?.();
|
|
22983
23318
|
if (src) {
|
|
22984
|
-
|
|
22985
|
-
if (
|
|
23319
|
+
let referencedComponent = null;
|
|
23320
|
+
if (src.startsWith("ui://")) {
|
|
23321
|
+
const rest = src.slice(5);
|
|
23322
|
+
const pkgId = rest.slice(0, 8);
|
|
23323
|
+
const resourceId = rest.slice(8);
|
|
23324
|
+
const targetPackage = doc.getRoot().listPackages().find((candidate) => candidate.getId() === pkgId);
|
|
23325
|
+
const targetResource = targetPackage?.getResourceById(resourceId);
|
|
23326
|
+
if (targetPackage && targetResource?.propertyType === "Component") referencedComponent = {
|
|
23327
|
+
component: targetResource,
|
|
23328
|
+
package: targetPackage
|
|
23329
|
+
};
|
|
23330
|
+
} else {
|
|
23331
|
+
const packageId = child.getPackageId?.();
|
|
23332
|
+
const targetPackage = packageId ? doc.getRoot().listPackages().find((candidate) => candidate.getId() === packageId) : pkg;
|
|
23333
|
+
const targetResource = targetPackage?.getResourceById(src);
|
|
23334
|
+
if (targetPackage && targetResource?.propertyType === "Component") referencedComponent = {
|
|
23335
|
+
component: targetResource,
|
|
23336
|
+
package: targetPackage
|
|
23337
|
+
};
|
|
23338
|
+
}
|
|
23339
|
+
if (referencedComponent) return {
|
|
23340
|
+
type: (referencedComponent.package === pkg ? generatedById.get(referencedComponent.component.getId()) : void 0)?.encodedClassName ?? resolveComponentBaseType(referencedComponent.component),
|
|
23341
|
+
referencedComponent
|
|
23342
|
+
};
|
|
22986
23343
|
}
|
|
22987
23344
|
const instanceExtType = child.getInstanceExtType?.();
|
|
22988
|
-
if (instanceExtType) return `G${instanceExtType}
|
|
22989
|
-
return child.propertyType;
|
|
22990
|
-
}
|
|
22991
|
-
function resolveChildSourceComponent(doc, pkg, src) {
|
|
22992
|
-
if (!src) return null;
|
|
22993
|
-
if (src.startsWith("ui://")) {
|
|
22994
|
-
const rest = src.slice(5);
|
|
22995
|
-
const pkgId = rest.slice(0, 8);
|
|
22996
|
-
const resourceId = rest.slice(8);
|
|
22997
|
-
const targetResource = doc.getRoot().listPackages().find((candidate) => candidate.getId() === pkgId)?.getResourceById(resourceId);
|
|
22998
|
-
return targetResource?.propertyType === "Component" ? targetResource : null;
|
|
22999
|
-
}
|
|
23000
|
-
const localResource = pkg.getResourceById(src);
|
|
23001
|
-
return localResource?.propertyType === "Component" ? localResource : null;
|
|
23345
|
+
if (instanceExtType) return { type: `G${instanceExtType}` };
|
|
23346
|
+
return { type: child.propertyType };
|
|
23002
23347
|
}
|
|
23003
23348
|
function resolveComponentBaseType(component) {
|
|
23004
23349
|
const extensionType = component.getExtensionType();
|
|
@@ -23069,21 +23414,21 @@ function renderFguiTypescriptMemberAssignment(member, getMemberByName, variant)
|
|
|
23069
23414
|
return getMemberByName ? `\t\tthis.${member.name} = <${translatedType}><any>(this.getChild("${escapeTypeScriptString(member.originalName)}"));` : `\t\tthis.${member.name} = <${translatedType}><any>(this.getChildAt(${member.index}));`;
|
|
23070
23415
|
}
|
|
23071
23416
|
function resolveCodePath(codePath, basePath, fs) {
|
|
23072
|
-
if (isAbsolutePath(codePath)) return trimTrailingSlashes$
|
|
23417
|
+
if (isAbsolutePath(codePath)) return trimTrailingSlashes$2(codePath);
|
|
23073
23418
|
const projectBasePath = resolveProjectBasePath(basePath);
|
|
23074
|
-
return projectBasePath ? trimTrailingSlashes$
|
|
23419
|
+
return projectBasePath ? trimTrailingSlashes$2(fs.join(projectBasePath, codePath)) : trimTrailingSlashes$2(codePath);
|
|
23075
23420
|
}
|
|
23076
23421
|
function resolveProjectBasePath(basePath) {
|
|
23077
23422
|
if (!basePath) return "";
|
|
23078
|
-
const normalized = trimTrailingSlashes$
|
|
23423
|
+
const normalized = trimTrailingSlashes$2(basePath);
|
|
23079
23424
|
const assetsMatch = normalized.match(/^(.*)[/\\]assets(?:_[^/\\]+)?$/i);
|
|
23080
23425
|
if (assetsMatch?.[1]) return assetsMatch[1];
|
|
23081
23426
|
return dirname$2(normalized);
|
|
23082
23427
|
}
|
|
23083
23428
|
function dirname$2(filePath) {
|
|
23084
|
-
return trimTrailingSlashes$
|
|
23429
|
+
return trimTrailingSlashes$2(filePath).match(/^(.*)[/\\][^/\\]+$/)?.[1] ?? "";
|
|
23085
23430
|
}
|
|
23086
|
-
function trimTrailingSlashes$
|
|
23431
|
+
function trimTrailingSlashes$2(value) {
|
|
23087
23432
|
return value.replace(/[/\\]+$/, "");
|
|
23088
23433
|
}
|
|
23089
23434
|
function isAbsolutePath(value) {
|
|
@@ -23092,9 +23437,15 @@ function isAbsolutePath(value) {
|
|
|
23092
23437
|
function isDefaultMemberName(ownerType, kind, name) {
|
|
23093
23438
|
if (kind === "controller") return (ownerType === "GButton" || ownerType === "GComboBox") && name === "button";
|
|
23094
23439
|
if (kind === "transition") return false;
|
|
23095
|
-
if (ownerType === "GButton" || ownerType === "GLabel" || ownerType === "GComboBox")
|
|
23096
|
-
|
|
23097
|
-
|
|
23440
|
+
if (ownerType === "GButton" || ownerType === "GLabel" || ownerType === "GComboBox") {
|
|
23441
|
+
if (name === "title" || name === "icon") return true;
|
|
23442
|
+
}
|
|
23443
|
+
if (ownerType === "GProgressBar") {
|
|
23444
|
+
if (name === "bar" || name === "bar_v" || name === "title" || name === "ani") return true;
|
|
23445
|
+
}
|
|
23446
|
+
if (ownerType === "GSlider") {
|
|
23447
|
+
if (name === "bar" || name === "bar_v" || name === "grip" || name === "title" || name === "ani") return true;
|
|
23448
|
+
}
|
|
23098
23449
|
return /^n\d+(?:_.*)?$/i.test(name);
|
|
23099
23450
|
}
|
|
23100
23451
|
function applyMemberNamePrefix(name, prefix) {
|
|
@@ -23383,11 +23734,11 @@ function inferPackageName(fileName) {
|
|
|
23383
23734
|
if (/\.fui$/i.test(fileName)) return fileName.replace(/\.fui$/i, "");
|
|
23384
23735
|
return fileName.replace(/\.bin$/i, "");
|
|
23385
23736
|
}
|
|
23386
|
-
function trimTrailingSlashes(value) {
|
|
23737
|
+
function trimTrailingSlashes$1(value) {
|
|
23387
23738
|
return value.replace(/[/\\]+$/, "");
|
|
23388
23739
|
}
|
|
23389
23740
|
function normalizeComparablePath(value) {
|
|
23390
|
-
const normalized = trimTrailingSlashes(value).replace(/\\/g, "/");
|
|
23741
|
+
const normalized = trimTrailingSlashes$1(value).replace(/\\/g, "/");
|
|
23391
23742
|
const driveMatch = normalized.match(/^([a-z]:)(?:\/(.*))?$/i);
|
|
23392
23743
|
const drivePrefix = driveMatch?.[1].toLowerCase() ?? "";
|
|
23393
23744
|
const remainder = driveMatch ? driveMatch[2] ?? "" : normalized;
|
|
@@ -23407,14 +23758,14 @@ function normalizeComparablePath(value) {
|
|
|
23407
23758
|
return (drivePrefix ? `${drivePrefix}/${joined}`.replace(/\/$/, "") : hasRoot ? `/${joined}`.replace(/\/$/, "") : joined || ".").toLowerCase();
|
|
23408
23759
|
}
|
|
23409
23760
|
function dirname$1(filePath) {
|
|
23410
|
-
return trimTrailingSlashes(filePath).match(/^(.*)[/\\][^/\\]+$/)?.[1] ?? "";
|
|
23761
|
+
return trimTrailingSlashes$1(filePath).match(/^(.*)[/\\][^/\\]+$/)?.[1] ?? "";
|
|
23411
23762
|
}
|
|
23412
23763
|
function basename(filePath) {
|
|
23413
|
-
return trimTrailingSlashes(filePath).match(/([^/\\]+)$/)?.[1] ?? "";
|
|
23764
|
+
return trimTrailingSlashes$1(filePath).match(/([^/\\]+)$/)?.[1] ?? "";
|
|
23414
23765
|
}
|
|
23415
23766
|
function resolveOutputProjectPath(output, fs) {
|
|
23416
23767
|
if (/\.fairy$/i.test(output)) return output;
|
|
23417
|
-
const normalizedOutput = trimTrailingSlashes(output);
|
|
23768
|
+
const normalizedOutput = trimTrailingSlashes$1(output);
|
|
23418
23769
|
const projectName = basename(normalizedOutput) || "Restored";
|
|
23419
23770
|
return fs.join(normalizedOutput, `${projectName}.fairy`);
|
|
23420
23771
|
}
|
|
@@ -23460,7 +23811,7 @@ async function prepareRestoreOutputDir(inputDir, outputDir, outputProjectPath, f
|
|
|
23460
23811
|
await fs.mkdir(outputDir);
|
|
23461
23812
|
}
|
|
23462
23813
|
async function restore(options) {
|
|
23463
|
-
const sourceDir = trimTrailingSlashes(options.inputDir);
|
|
23814
|
+
const sourceDir = trimTrailingSlashes$1(options.inputDir);
|
|
23464
23815
|
const outputIsProjectFile = /\.fairy$/i.test(options.output);
|
|
23465
23816
|
const outputProjectPath = resolveOutputProjectPath(options.output, options.fs);
|
|
23466
23817
|
await prepareRestoreOutputDir(sourceDir, dirname$1(outputProjectPath) || ".", outputProjectPath, options.fs, options.force === true, outputIsProjectFile);
|
|
@@ -23602,16 +23953,23 @@ var RestoreWorkflow = class {
|
|
|
23602
23953
|
async _ensureLooseImageResource(doc, pkg, owner, sourceDir, fileName) {
|
|
23603
23954
|
const resources = pkg.listResources();
|
|
23604
23955
|
const existing = this._findResourceByFile(resources, owner, "ImageResource", fileName);
|
|
23605
|
-
if (existing) return existing;
|
|
23606
23956
|
const sourcePath = await this._resolveLooseSourceFile(pkg, sourceDir, fileName);
|
|
23607
|
-
if (!sourcePath) return null;
|
|
23957
|
+
if (!sourcePath) return existing ?? null;
|
|
23958
|
+
if (existing) {
|
|
23959
|
+
existing.setExtras?.({
|
|
23960
|
+
...existing.getExtras?.() ?? {},
|
|
23961
|
+
_publishedFile: fileBaseName(sourcePath),
|
|
23962
|
+
_restoreAsLooseImage: true
|
|
23963
|
+
});
|
|
23964
|
+
return existing;
|
|
23965
|
+
}
|
|
23608
23966
|
const resource = doc.createImageResource(stripExtension(fileName));
|
|
23609
23967
|
resource.setId(generateId()).setPath(owner.getPath?.() ?? "/").setBranch(owner.getBranch?.() ?? "").setBranchItemIds(owner.getBranchItemIds?.() ?? []).setExported(false).setFileName(fileName);
|
|
23610
23968
|
resource.setExtras?.({
|
|
23611
23969
|
...resource.getExtras?.() ?? {},
|
|
23612
23970
|
_publishedFile: fileBaseName(sourcePath),
|
|
23613
23971
|
_suppressPackageSize: true,
|
|
23614
|
-
|
|
23972
|
+
_restoreAsLooseImage: true
|
|
23615
23973
|
});
|
|
23616
23974
|
pkg.addResource(resource);
|
|
23617
23975
|
return resource;
|
|
@@ -23785,13 +24143,13 @@ var RestoreWorkflow = class {
|
|
|
23785
24143
|
}
|
|
23786
24144
|
async _copyLooseResources(pkg, options, warnings) {
|
|
23787
24145
|
for (const resource of pkg.listResources()) {
|
|
23788
|
-
const
|
|
24146
|
+
const restoreAsLooseImage = resource.getExtras?.()?._restoreAsLooseImage === true;
|
|
23789
24147
|
if (![
|
|
23790
24148
|
"SoundResource",
|
|
23791
24149
|
"MiscResource",
|
|
23792
24150
|
"SpineResource",
|
|
23793
24151
|
"DragonBonesResource"
|
|
23794
|
-
].includes(resource.propertyType) && !
|
|
24152
|
+
].includes(resource.propertyType) && !restoreAsLooseImage) continue;
|
|
23795
24153
|
const fileName = resourceFileName(resource);
|
|
23796
24154
|
if (!fileName) continue;
|
|
23797
24155
|
const sourcePath = await this._resolveSourceFile(options.sourceDir, this._sourceFileCandidates(pkg, resourcePublishedFileName(resource), fileName));
|
|
@@ -23961,6 +24319,26 @@ var RestoreWorkflow = class {
|
|
|
23961
24319
|
};
|
|
23962
24320
|
//#endregion
|
|
23963
24321
|
//#region ../functions/src/publish.ts
|
|
24322
|
+
async function runPublishPluginHook(plugins, hook, doc, options) {
|
|
24323
|
+
const logger = doc.getLogger();
|
|
24324
|
+
for (const plugin of plugins) {
|
|
24325
|
+
const fn = plugin.plugin[hook];
|
|
24326
|
+
if (typeof fn !== "function") continue;
|
|
24327
|
+
try {
|
|
24328
|
+
await fn(doc, options);
|
|
24329
|
+
} catch (error) {
|
|
24330
|
+
logger.warn(`publish: Plugin "${plugin.name}" ${hook} failed: ${formatPluginError(error)}`);
|
|
24331
|
+
}
|
|
24332
|
+
}
|
|
24333
|
+
}
|
|
24334
|
+
function resolvePublishPluginsDir(doc, options) {
|
|
24335
|
+
const fs = options.fs;
|
|
24336
|
+
const projectDir = doc.getProjectDir?.() ?? "";
|
|
24337
|
+
if (projectDir) return fs?.join ? fs.join(projectDir, "plugins") : `${projectDir.replace(/[/\\]+$/, "")}/plugins`;
|
|
24338
|
+
const projectBasePath = resolveProjectBasePath(options.basePath);
|
|
24339
|
+
if (!projectBasePath) return "";
|
|
24340
|
+
return fs?.join ? fs.join(projectBasePath, "plugins") : `${projectBasePath.replace(/[/\\]+$/, "")}/plugins`;
|
|
24341
|
+
}
|
|
23964
24342
|
const UNITY_PROJECT_TYPE = ProjectType.Unity;
|
|
23965
24343
|
const COCOS_CREATOR_PROJECT_TYPE = ProjectType.CocosCreator;
|
|
23966
24344
|
function resolveDefaultPublishFileExtension(projectType, publishSettings) {
|
|
@@ -24010,6 +24388,19 @@ function resolvePublishOptions(doc, overrides = {}) {
|
|
|
24010
24388
|
atlas: atlasOptions
|
|
24011
24389
|
};
|
|
24012
24390
|
}
|
|
24391
|
+
function trimTrailingSlashes(value) {
|
|
24392
|
+
return value.replace(/[/\\]+$/, "");
|
|
24393
|
+
}
|
|
24394
|
+
function isAbsolutePathLike(value) {
|
|
24395
|
+
return /^(?:[a-zA-Z]:[/\\]|[/\\]{1,2})/u.test(value);
|
|
24396
|
+
}
|
|
24397
|
+
function joinPathSegments(left, right) {
|
|
24398
|
+
const normalizedLeft = trimTrailingSlashes(left);
|
|
24399
|
+
const normalizedRight = right.replace(/^[/\\]+/, "");
|
|
24400
|
+
if (!normalizedLeft) return normalizedRight;
|
|
24401
|
+
if (!normalizedRight) return normalizedLeft;
|
|
24402
|
+
return `${normalizedLeft}${normalizedLeft.includes("\\") ? "\\" : "/"}${normalizedRight}`;
|
|
24403
|
+
}
|
|
24013
24404
|
function dirname(filePath) {
|
|
24014
24405
|
return filePath.replace(/[/\\]+$/, "").match(/^(.*)[/\\][^/\\]+$/)?.[1] ?? "";
|
|
24015
24406
|
}
|
|
@@ -24125,13 +24516,14 @@ function extname(fileName) {
|
|
|
24125
24516
|
if (lastDot <= lastSlash) return "";
|
|
24126
24517
|
return normalized.slice(lastDot);
|
|
24127
24518
|
}
|
|
24128
|
-
function resolvePublishedMiscFileName(resource) {
|
|
24519
|
+
function resolvePublishedMiscFileName(resource, projectType) {
|
|
24129
24520
|
const file = resource.getFile();
|
|
24521
|
+
if (projectType !== UNITY_PROJECT_TYPE) return file;
|
|
24130
24522
|
if (file.toLowerCase().endsWith(".atlas")) return `${file}.txt`;
|
|
24131
24523
|
return file;
|
|
24132
24524
|
}
|
|
24133
|
-
function resolvePublishedSkeletonFileName(resource) {
|
|
24134
|
-
if (isSpineResource(resource) && resource.getFile().toLowerCase().endsWith(".skel")) return `${resource.getFile()}.bytes`;
|
|
24525
|
+
function resolvePublishedSkeletonFileName(resource, projectType) {
|
|
24526
|
+
if (projectType === UNITY_PROJECT_TYPE && isSpineResource(resource) && resource.getFile().toLowerCase().endsWith(".skel")) return `${resource.getFile()}.bytes`;
|
|
24135
24527
|
return resource.getFile();
|
|
24136
24528
|
}
|
|
24137
24529
|
function setPublishedFileExtra(resource, fileName) {
|
|
@@ -24234,6 +24626,24 @@ function collectPackagePublishContext(pkg, options) {
|
|
|
24234
24626
|
const referencedIds = /* @__PURE__ */ new Set();
|
|
24235
24627
|
const pixelHitTestImageIds = /* @__PURE__ */ new Set();
|
|
24236
24628
|
const spriteItemIds = /* @__PURE__ */ new Set();
|
|
24629
|
+
const collectExportedResourceIds = (sourceResources, sourcePublishedResourceIds) => {
|
|
24630
|
+
const exportedResourceIds = new Set(sourcePublishedResourceIds);
|
|
24631
|
+
const resourcesById = new Map(sourceResources.map((resource) => [resource.getId(), resource]));
|
|
24632
|
+
let changed = true;
|
|
24633
|
+
while (changed) {
|
|
24634
|
+
changed = false;
|
|
24635
|
+
for (const resourceId of [...exportedResourceIds]) {
|
|
24636
|
+
const resource = resourcesById.get(resourceId);
|
|
24637
|
+
if (!resource || !isSkeletonResource(resource)) continue;
|
|
24638
|
+
for (const requiredId of resource.getRequireIds()) {
|
|
24639
|
+
if (!requiredId || exportedResourceIds.has(requiredId)) continue;
|
|
24640
|
+
exportedResourceIds.add(requiredId);
|
|
24641
|
+
changed = true;
|
|
24642
|
+
}
|
|
24643
|
+
}
|
|
24644
|
+
}
|
|
24645
|
+
return exportedResourceIds;
|
|
24646
|
+
};
|
|
24237
24647
|
for (const atlas of pkg.listAtlases()) for (const sprite of atlas.listSprites()) spriteItemIds.add(sprite.getItemId());
|
|
24238
24648
|
for (const resource of resources) {
|
|
24239
24649
|
if (!isComponentResource(resource)) continue;
|
|
@@ -24260,6 +24670,7 @@ function collectPackagePublishContext(pkg, options) {
|
|
|
24260
24670
|
child.getSelectedIcon?.(),
|
|
24261
24671
|
child.getDropdown?.(),
|
|
24262
24672
|
child.getSound?.(),
|
|
24673
|
+
child.getInstanceSound?.(),
|
|
24263
24674
|
child.getInstanceIcon?.(),
|
|
24264
24675
|
child.getInstanceSelectedIcon?.(),
|
|
24265
24676
|
child.getVtScrollBarRes?.(),
|
|
@@ -24317,19 +24728,7 @@ function collectPackagePublishContext(pkg, options) {
|
|
|
24317
24728
|
}
|
|
24318
24729
|
if (resource.getExported() || referencedIds.has(resourceId)) publishedResourceIds.add(resourceId);
|
|
24319
24730
|
}
|
|
24320
|
-
|
|
24321
|
-
while (changed) {
|
|
24322
|
-
changed = false;
|
|
24323
|
-
for (const resource of resources) {
|
|
24324
|
-
if (!isSkeletonResource(resource)) continue;
|
|
24325
|
-
if (!publishedResourceIds.has(resource.getId())) continue;
|
|
24326
|
-
for (const requiredId of resource.getRequireIds()) {
|
|
24327
|
-
if (!requiredId || publishedResourceIds.has(requiredId)) continue;
|
|
24328
|
-
publishedResourceIds.add(requiredId);
|
|
24329
|
-
changed = true;
|
|
24330
|
-
}
|
|
24331
|
-
}
|
|
24332
|
-
}
|
|
24731
|
+
for (const resourceId of collectExportedResourceIds(resources, publishedResourceIds)) publishedResourceIds.add(resourceId);
|
|
24333
24732
|
const highResolutionItemIds = collectHighResolutionItemIds(resources, publishedResourceIds, options.includeHighResolution);
|
|
24334
24733
|
if (!options.includeBranches) {
|
|
24335
24734
|
const mainByKey = /* @__PURE__ */ new Map();
|
|
@@ -24378,6 +24777,7 @@ function collectPackagePublishContext(pkg, options) {
|
|
|
24378
24777
|
return {
|
|
24379
24778
|
referencedIds,
|
|
24380
24779
|
publishedResourceIds,
|
|
24780
|
+
exportedResourceIds: collectExportedResourceIds(resources, publishedResourceIds),
|
|
24381
24781
|
pixelHitTestImageIds,
|
|
24382
24782
|
highResolutionItemIds,
|
|
24383
24783
|
effectiveResourceIds,
|
|
@@ -24387,6 +24787,7 @@ function collectPackagePublishContext(pkg, options) {
|
|
|
24387
24787
|
return {
|
|
24388
24788
|
referencedIds,
|
|
24389
24789
|
publishedResourceIds,
|
|
24790
|
+
exportedResourceIds: collectExportedResourceIds(resources, publishedResourceIds),
|
|
24390
24791
|
pixelHitTestImageIds,
|
|
24391
24792
|
highResolutionItemIds,
|
|
24392
24793
|
effectiveResourceIds: new Map([...publishedResourceIds].map((resourceId) => [resourceId, resourceId])),
|
|
@@ -24437,7 +24838,7 @@ async function applyPixelHitTests(pkg, imageIds, basePath, encoder) {
|
|
|
24437
24838
|
}
|
|
24438
24839
|
}
|
|
24439
24840
|
async function annotatePackagePublishArtifacts(pkg, basePath, encoder, options) {
|
|
24440
|
-
const { publishedResourceIds, pixelHitTestImageIds, highResolutionItemIds, effectiveResourceIds, includeBranches } = collectPackagePublishContext(pkg, options);
|
|
24841
|
+
const { publishedResourceIds, exportedResourceIds, pixelHitTestImageIds, highResolutionItemIds, effectiveResourceIds, includeBranches } = collectPackagePublishContext(pkg, options);
|
|
24441
24842
|
for (const resource of pkg.listResources()) {
|
|
24442
24843
|
setPublishedIdExtra(resource, effectiveResourceIds.get(resource.getId()) ?? null);
|
|
24443
24844
|
if (isHighResolutionResource(resource)) resource.setHighResolutionItemIds(highResolutionItemIds.get(resource.getId()) ?? []);
|
|
@@ -24447,21 +24848,26 @@ async function annotatePackagePublishArtifacts(pkg, basePath, encoder, options)
|
|
|
24447
24848
|
pkg.setExtras({
|
|
24448
24849
|
...extras,
|
|
24449
24850
|
publishedResourceIds: [...publishedResourceIds].sort((a, b) => a.localeCompare(b)),
|
|
24851
|
+
exportedResourceIds: [...exportedResourceIds].sort((a, b) => a.localeCompare(b)),
|
|
24450
24852
|
publishedIncludeBranches: includeBranches,
|
|
24451
24853
|
publishedEffectiveResourceIds: Object.fromEntries(effectiveResourceIds)
|
|
24452
24854
|
});
|
|
24453
24855
|
for (const resource of pkg.listResources()) {
|
|
24454
24856
|
if (isMiscResource(resource)) {
|
|
24455
|
-
setPublishedFileExtra(resource, resolvePublishedMiscFileName(resource));
|
|
24857
|
+
setPublishedFileExtra(resource, resolvePublishedMiscFileName(resource, options.projectType));
|
|
24456
24858
|
continue;
|
|
24457
24859
|
}
|
|
24458
|
-
if (isSkeletonResource(resource)) setPublishedFileExtra(resource, resolvePublishedSkeletonFileName(resource));
|
|
24860
|
+
if (isSkeletonResource(resource)) setPublishedFileExtra(resource, resolvePublishedSkeletonFileName(resource, options.projectType));
|
|
24459
24861
|
}
|
|
24460
24862
|
}
|
|
24461
24863
|
function getAnnotatedPublishedResourceIds(pkg) {
|
|
24462
24864
|
const extras = pkg.getExtras() ?? {};
|
|
24463
24865
|
return new Set(extras.publishedResourceIds ?? []);
|
|
24464
24866
|
}
|
|
24867
|
+
function getAnnotatedExportedResourceIds(pkg) {
|
|
24868
|
+
const extras = pkg.getExtras() ?? {};
|
|
24869
|
+
return new Set(extras.exportedResourceIds ?? []);
|
|
24870
|
+
}
|
|
24465
24871
|
function getPublishedSkeletonDependencyImageIds(pkg, publishedResourceIds) {
|
|
24466
24872
|
const imageIds = /* @__PURE__ */ new Set();
|
|
24467
24873
|
const resourcesById = new Map(pkg.listResources().map((resource) => [resource.getId(), resource]));
|
|
@@ -24500,18 +24906,18 @@ async function exportPackageSounds(pkg, outputDir, basePath, fs, readFileRaw, lo
|
|
|
24500
24906
|
}
|
|
24501
24907
|
}
|
|
24502
24908
|
async function exportPackageExternalResources(pkg, outputDir, basePath, fs, readFileRaw, logger) {
|
|
24503
|
-
const
|
|
24504
|
-
const skeletonDependencyImageIds = getPublishedSkeletonDependencyImageIds(pkg,
|
|
24505
|
-
if (
|
|
24909
|
+
const exportedResourceIds = getAnnotatedExportedResourceIds(pkg);
|
|
24910
|
+
const skeletonDependencyImageIds = getPublishedSkeletonDependencyImageIds(pkg, exportedResourceIds);
|
|
24911
|
+
if (exportedResourceIds.size === 0) return;
|
|
24506
24912
|
if (!basePath || !readFileRaw) {
|
|
24507
24913
|
if (pkg.listResources().some((resource) => {
|
|
24508
|
-
return (isMiscResource(resource) || isSkeletonResource(resource)) &&
|
|
24914
|
+
return (isMiscResource(resource) || isSkeletonResource(resource)) && exportedResourceIds.has(resource.getId()) || skeletonDependencyImageIds.has(resource.getId());
|
|
24509
24915
|
})) logger.warn(`publish: External resources in package "${pkg.getName()}" were not exported because basePath/readFileRaw is unavailable.`);
|
|
24510
24916
|
return;
|
|
24511
24917
|
}
|
|
24512
24918
|
for (const resource of pkg.listResources()) {
|
|
24513
24919
|
const resourceId = resource.getId();
|
|
24514
|
-
const isSkeletonExternal =
|
|
24920
|
+
const isSkeletonExternal = exportedResourceIds.has(resourceId) && (isMiscResource(resource) || isSkeletonResource(resource));
|
|
24515
24921
|
const isSkeletonImageDependency = skeletonDependencyImageIds.has(resourceId) && isImageResource(resource);
|
|
24516
24922
|
if (!isSkeletonExternal && !isSkeletonImageDependency) continue;
|
|
24517
24923
|
let sourcePath;
|
|
@@ -24557,16 +24963,102 @@ async function exportPackageExternalResources(pkg, outputDir, basePath, fs, read
|
|
|
24557
24963
|
*/
|
|
24558
24964
|
function publish(options) {
|
|
24559
24965
|
return createTransform("publish", async (doc) => {
|
|
24966
|
+
const resolveConfiguredOutputPath = (value, projectBasePath) => {
|
|
24967
|
+
const trimmed = value?.trim();
|
|
24968
|
+
if (!trimmed) return void 0;
|
|
24969
|
+
if (isAbsolutePathLike(trimmed) || !projectBasePath) return trimTrailingSlashes(trimmed);
|
|
24970
|
+
return trimTrailingSlashes(options.fs ? options.fs.join(projectBasePath, trimmed) : joinPathSegments(projectBasePath, trimmed));
|
|
24971
|
+
};
|
|
24972
|
+
const resolveProjectPublishConfig = () => {
|
|
24973
|
+
const publishSettings = (doc.getRoot().getSettings?.() ?? {}).publish ?? {};
|
|
24974
|
+
const resolved = resolvePublishOptions(doc, {
|
|
24975
|
+
compressed: options.compressed,
|
|
24976
|
+
fileExtension: options.fileExtension,
|
|
24977
|
+
packages: options.packages,
|
|
24978
|
+
atlas: options.atlas
|
|
24979
|
+
});
|
|
24980
|
+
const includeBranches = (publishSettings.branchProcessing ?? 0) === 0;
|
|
24981
|
+
return {
|
|
24982
|
+
...resolved,
|
|
24983
|
+
projectType: doc.getRoot().getProjectType(),
|
|
24984
|
+
includeBranches,
|
|
24985
|
+
activeBranch: includeBranches ? "" : options.branch ?? "",
|
|
24986
|
+
includeHighResolution: publishSettings.includeHighResolution ?? 0,
|
|
24987
|
+
separatedAtlasForBranch: includeBranches && publishSettings.seperatedAtlasForBranch === true,
|
|
24988
|
+
globalOutputPath: publishSettings.path?.trim() ?? "",
|
|
24989
|
+
globalBranchOutputPath: publishSettings.branchPath?.trim() ?? ""
|
|
24990
|
+
};
|
|
24991
|
+
};
|
|
24992
|
+
const resolvePackagePublishPlan = (pkg, config, projectBasePath) => {
|
|
24993
|
+
let outputDir;
|
|
24994
|
+
if (options.output) outputDir = trimTrailingSlashes(options.output);
|
|
24995
|
+
else {
|
|
24996
|
+
const candidates = [];
|
|
24997
|
+
if (!config.includeBranches && config.activeBranch) candidates.push(pkg.getPublishBranchPath(), config.globalBranchOutputPath);
|
|
24998
|
+
candidates.push(pkg.getPublishPath(), config.globalOutputPath);
|
|
24999
|
+
for (const candidate of candidates) {
|
|
25000
|
+
const resolved = resolveConfiguredOutputPath(candidate, projectBasePath);
|
|
25001
|
+
if (!resolved) continue;
|
|
25002
|
+
outputDir = resolved;
|
|
25003
|
+
break;
|
|
25004
|
+
}
|
|
25005
|
+
}
|
|
25006
|
+
const publishName = pkg.getPublishName() || pkg.getName();
|
|
25007
|
+
return {
|
|
25008
|
+
pkg,
|
|
25009
|
+
outputDir,
|
|
25010
|
+
publishName,
|
|
25011
|
+
fileName: resolvePublishFileName(publishName, config.fileExtension),
|
|
25012
|
+
compressed: config.compressed,
|
|
25013
|
+
fileExtension: config.fileExtension,
|
|
25014
|
+
includeBranches: config.includeBranches,
|
|
25015
|
+
activeBranch: config.activeBranch,
|
|
25016
|
+
includeHighResolution: config.includeHighResolution,
|
|
25017
|
+
separatedAtlasForBranch: config.separatedAtlasForBranch,
|
|
25018
|
+
atlas: config.atlas
|
|
25019
|
+
};
|
|
25020
|
+
};
|
|
25021
|
+
const createNoopPublishFs = () => ({
|
|
25022
|
+
async writeFileRaw() {},
|
|
25023
|
+
async mkdir() {},
|
|
25024
|
+
join(...paths) {
|
|
25025
|
+
return paths.join("/");
|
|
25026
|
+
}
|
|
25027
|
+
});
|
|
25028
|
+
const publishPackage = async (plan, writerFs, packageIndex) => {
|
|
25029
|
+
const atlasRuntimeOptions = resolvePublishAtlasRuntimeOptions(plan.fileExtension);
|
|
25030
|
+
await atlas({
|
|
25031
|
+
...plan.atlas,
|
|
25032
|
+
...options.atlas ?? {},
|
|
25033
|
+
separatedAtlasForBranch: plan.separatedAtlasForBranch,
|
|
25034
|
+
encoder: options.encoder,
|
|
25035
|
+
basePath: options.basePath,
|
|
25036
|
+
outputPath: options.fs ? plan.outputDir : void 0,
|
|
25037
|
+
mkdir: options.fs ? options.fs.mkdir : void 0,
|
|
25038
|
+
readFileRaw: options.atlas?.readFileRaw ?? options.fs?.readFileRaw,
|
|
25039
|
+
packages: [plan.pkg.getName()],
|
|
25040
|
+
...atlasRuntimeOptions
|
|
25041
|
+
})(doc);
|
|
25042
|
+
if (!options.fs) return;
|
|
25043
|
+
if (!plan.outputDir) throw new Error("publish: no output directory resolved. Provide --output, or configure global publish.path / package publishPath.");
|
|
25044
|
+
await options.fs.mkdir(plan.outputDir);
|
|
25045
|
+
const filePath = options.fs.join(plan.outputDir, plan.fileName);
|
|
25046
|
+
const bwOptions = {
|
|
25047
|
+
compressed: plan.compressed,
|
|
25048
|
+
packageIndex
|
|
25049
|
+
};
|
|
25050
|
+
await new BinaryWriter(writerFs).write(doc, filePath, bwOptions);
|
|
25051
|
+
await exportPackageSounds(plan.pkg, plan.outputDir, options.basePath, options.fs, options.atlas?.readFileRaw ?? options.fs.readFileRaw, logger);
|
|
25052
|
+
await exportPackageExternalResources(plan.pkg, plan.outputDir, options.basePath, options.fs, options.atlas?.readFileRaw ?? options.fs.readFileRaw, logger);
|
|
25053
|
+
logger.info(`publish: Written ${plan.fileName}`);
|
|
25054
|
+
};
|
|
24560
25055
|
const root = doc.getRoot();
|
|
24561
25056
|
const logger = doc.getLogger();
|
|
24562
|
-
const
|
|
24563
|
-
const
|
|
24564
|
-
|
|
24565
|
-
|
|
24566
|
-
|
|
24567
|
-
atlas: options.atlas
|
|
24568
|
-
});
|
|
24569
|
-
const ext = resolved.fileExtension;
|
|
25057
|
+
const projectBasePath = resolveProjectBasePath(options.basePath) || doc.getProjectDir?.() || "";
|
|
25058
|
+
const pluginsDir = resolvePublishPluginsDir(doc, options);
|
|
25059
|
+
const plugins = pluginsDir ? await loadPlugins(doc, pluginsDir) : [];
|
|
25060
|
+
await runPublishPluginHook(plugins, "onPublishStart", doc, options);
|
|
25061
|
+
const resolved = resolveProjectPublishConfig();
|
|
24570
25062
|
let allPackages = root.listPackages();
|
|
24571
25063
|
if (resolved.packages && resolved.packages.length > 0) {
|
|
24572
25064
|
const names = new Set(resolved.packages);
|
|
@@ -24574,59 +25066,42 @@ function publish(options) {
|
|
|
24574
25066
|
}
|
|
24575
25067
|
if (allPackages.length === 0) {
|
|
24576
25068
|
logger.warn("publish: No packages to publish.");
|
|
25069
|
+
await runPublishPluginHook(plugins, "onPublishEnd", doc, options);
|
|
24577
25070
|
return;
|
|
24578
25071
|
}
|
|
24579
|
-
const includeBranches = (publishSettings.branchProcessing ?? 0) === 0;
|
|
24580
|
-
const activeBranch = includeBranches ? "" : options.branch ?? "";
|
|
24581
|
-
const includeHighResolution = publishSettings.includeHighResolution ?? 0;
|
|
24582
|
-
const atlasRuntimeOptions = resolvePublishAtlasRuntimeOptions(ext);
|
|
24583
25072
|
const allDocPackages = root.listPackages();
|
|
24584
25073
|
const pkgMap = /* @__PURE__ */ new Map();
|
|
24585
25074
|
for (const p of allDocPackages) pkgMap.set(p.getId(), p);
|
|
24586
25075
|
for (const pkg of allPackages) {
|
|
24587
|
-
_computeDependencies(pkg, pkgMap);
|
|
25076
|
+
_computeDependencies(doc, pkg, pkgMap);
|
|
24588
25077
|
await annotatePackagePublishArtifacts(pkg, options.basePath, options.encoder, {
|
|
24589
|
-
|
|
24590
|
-
|
|
24591
|
-
|
|
25078
|
+
projectType: resolved.projectType,
|
|
25079
|
+
includeBranches: resolved.includeBranches,
|
|
25080
|
+
activeBranch: resolved.activeBranch,
|
|
25081
|
+
includeHighResolution: resolved.includeHighResolution
|
|
24592
25082
|
});
|
|
24593
25083
|
}
|
|
24594
|
-
|
|
24595
|
-
...resolved.atlas,
|
|
24596
|
-
...options.atlas ?? {},
|
|
24597
|
-
separatedAtlasForBranch: includeBranches && publishSettings.seperatedAtlasForBranch === true,
|
|
24598
|
-
encoder: options.encoder,
|
|
24599
|
-
basePath: options.basePath,
|
|
24600
|
-
outputPath: options.fs ? options.output : void 0,
|
|
24601
|
-
mkdir: options.fs ? options.fs.mkdir : void 0,
|
|
24602
|
-
readFileRaw: options.atlas?.readFileRaw ?? options.fs?.readFileRaw,
|
|
24603
|
-
...atlasRuntimeOptions
|
|
24604
|
-
})(doc);
|
|
25084
|
+
const plans = allPackages.map((pkg) => resolvePackagePublishPlan(pkg, resolved, projectBasePath));
|
|
24605
25085
|
if (!options.fs) {
|
|
24606
25086
|
logger.info(`publish: No fs provided — layout computed for ${allPackages.length} package(s), skipping file output.`);
|
|
25087
|
+
const noopWriterFs = toBinaryWriterFileSystem(createNoopPublishFs());
|
|
25088
|
+
for (const plan of plans) await publishPackage(plan, noopWriterFs, allDocPackages.indexOf(plan.pkg));
|
|
25089
|
+
await runPublishPluginHook(plugins, "onPublishEnd", doc, options);
|
|
24607
25090
|
return;
|
|
24608
25091
|
}
|
|
24609
|
-
|
|
25092
|
+
const unresolvedPlan = plans.find((plan) => !plan.outputDir);
|
|
25093
|
+
if (unresolvedPlan) throw new Error(`publish: no output directory resolved for package "${unresolvedPlan.pkg.getName()}". Provide --output, or configure global publish.path / package publishPath.`);
|
|
24610
25094
|
const writerFs = toBinaryWriterFileSystem(options.fs);
|
|
24611
|
-
for (const
|
|
24612
|
-
const pkgIndex = allDocPackages.indexOf(pkg);
|
|
24613
|
-
const fileName = resolvePublishFileName(pkg.getPublishName() || pkg.getName(), ext);
|
|
24614
|
-
const filePath = options.fs.join(options.output, fileName);
|
|
24615
|
-
const bwOptions = {
|
|
24616
|
-
compressed: resolved.compressed,
|
|
24617
|
-
packageIndex: pkgIndex
|
|
24618
|
-
};
|
|
24619
|
-
await new BinaryWriter(writerFs).write(doc, filePath, bwOptions);
|
|
24620
|
-
await exportPackageSounds(pkg, options.output, options.basePath, options.fs, options.atlas?.readFileRaw ?? options.fs.readFileRaw, logger);
|
|
24621
|
-
await exportPackageExternalResources(pkg, options.output, options.basePath, options.fs, options.atlas?.readFileRaw ?? options.fs.readFileRaw, logger);
|
|
24622
|
-
logger.info(`publish: Written ${fileName}`);
|
|
24623
|
-
}
|
|
25095
|
+
for (const plan of plans) await publishPackage(plan, writerFs, allDocPackages.indexOf(plan.pkg));
|
|
24624
25096
|
await publishCodeGeneration(doc, {
|
|
24625
25097
|
basePath: options.basePath,
|
|
24626
25098
|
fs: options.fs,
|
|
24627
|
-
packages: allPackages
|
|
25099
|
+
packages: allPackages,
|
|
25100
|
+
plugins
|
|
24628
25101
|
});
|
|
24629
|
-
|
|
25102
|
+
const publishedTargets = [...new Set(plans.map((plan) => plan.outputDir).filter((value) => Boolean(value)))];
|
|
25103
|
+
logger.info(publishedTargets.length > 0 ? `publish: Published ${allPackages.length} package(s) to ${publishedTargets.join(", ")}` : `publish: Published ${allPackages.length} package(s)`);
|
|
25104
|
+
await runPublishPluginHook(plugins, "onPublishEnd", doc, options);
|
|
24630
25105
|
});
|
|
24631
25106
|
}
|
|
24632
25107
|
/**
|
|
@@ -24634,25 +25109,104 @@ function publish(options) {
|
|
|
24634
25109
|
* The editor only adds dependencies for packages referenced via bitmap font URLs.
|
|
24635
25110
|
* @internal
|
|
24636
25111
|
*/
|
|
24637
|
-
function _computeDependencies(pkg, pkgMap) {
|
|
25112
|
+
function _computeDependencies(doc, pkg, pkgMap) {
|
|
24638
25113
|
const referencedPkgIds = /* @__PURE__ */ new Set();
|
|
24639
|
-
|
|
24640
|
-
|
|
24641
|
-
|
|
24642
|
-
|
|
24643
|
-
|
|
24644
|
-
|
|
24645
|
-
|
|
24646
|
-
|
|
25114
|
+
const pkgId = pkg.getId();
|
|
25115
|
+
const packageOrder = new Map(doc.getRoot().listPackages().map((entry, index) => [entry.getId(), index]));
|
|
25116
|
+
const addDependencyPackageId = (dependencyPkgId) => {
|
|
25117
|
+
const normalized = dependencyPkgId?.trim() ?? "";
|
|
25118
|
+
if (!normalized || normalized === pkgId) return;
|
|
25119
|
+
referencedPkgIds.add(normalized);
|
|
25120
|
+
};
|
|
25121
|
+
const extractPackageIdFromUiUrl = (value) => {
|
|
25122
|
+
if (!value.startsWith("ui://")) return null;
|
|
25123
|
+
const rest = value.slice(5);
|
|
25124
|
+
if (!rest) return null;
|
|
25125
|
+
const slashIndex = rest.indexOf("/");
|
|
25126
|
+
if (slashIndex >= 0) return rest.slice(0, slashIndex) || null;
|
|
25127
|
+
if (rest.length >= 8) return rest.slice(0, 8);
|
|
25128
|
+
return null;
|
|
25129
|
+
};
|
|
25130
|
+
const addDependencyPackageIdFromUiValue = (value) => {
|
|
25131
|
+
if (!value || typeof value !== "string") return;
|
|
25132
|
+
addDependencyPackageId(extractPackageIdFromUiUrl(value));
|
|
25133
|
+
};
|
|
25134
|
+
const addDependencyPackageIdsFromText = (value) => {
|
|
25135
|
+
if (!value || typeof value !== "string") return;
|
|
25136
|
+
const matches = value.matchAll(/ui:\/\/([0-9a-z]{8})/giu);
|
|
25137
|
+
for (const match of matches) addDependencyPackageId(match[1] ?? "");
|
|
25138
|
+
};
|
|
25139
|
+
const addDependencyPackageIdsFromUnknown = (value) => {
|
|
25140
|
+
if (Array.isArray(value)) {
|
|
25141
|
+
for (const entry of value) addDependencyPackageIdsFromUnknown(entry);
|
|
25142
|
+
return;
|
|
24647
25143
|
}
|
|
24648
|
-
|
|
25144
|
+
if (typeof value === "string") {
|
|
25145
|
+
addDependencyPackageIdFromUiValue(value);
|
|
25146
|
+
addDependencyPackageIdsFromText(value);
|
|
25147
|
+
}
|
|
25148
|
+
};
|
|
25149
|
+
const addDependencyFontRef = (value) => {
|
|
25150
|
+
if (Array.isArray(value)) {
|
|
25151
|
+
for (const entry of value) addDependencyPackageIdFromUiValue(entry);
|
|
25152
|
+
return;
|
|
25153
|
+
}
|
|
25154
|
+
addDependencyPackageIdFromUiValue(value ?? void 0);
|
|
25155
|
+
};
|
|
24649
25156
|
for (const res of pkg.listResources()) {
|
|
24650
25157
|
if (res.propertyType !== "Component") continue;
|
|
24651
|
-
|
|
25158
|
+
const component = res;
|
|
25159
|
+
for (const child of component.listChildren?.() ?? []) {
|
|
25160
|
+
addDependencyPackageId(child.getPackageId?.());
|
|
25161
|
+
addDependencyFontRef(child.getFont?.());
|
|
25162
|
+
addDependencyPackageIdsFromText(child.getText?.());
|
|
25163
|
+
for (const ref of [
|
|
25164
|
+
child.getUrl?.(),
|
|
25165
|
+
child.getDefaultItem?.(),
|
|
25166
|
+
child.getIcon?.(),
|
|
25167
|
+
child.getSelectedIcon?.(),
|
|
25168
|
+
child.getDropdown?.(),
|
|
25169
|
+
child.getSound?.(),
|
|
25170
|
+
child.getInstanceSound?.(),
|
|
25171
|
+
child.getInstanceIcon?.(),
|
|
25172
|
+
child.getInstanceSelectedIcon?.(),
|
|
25173
|
+
child.getVtScrollBarRes?.(),
|
|
25174
|
+
child.getHzScrollBarRes?.(),
|
|
25175
|
+
child.getHeaderRes?.(),
|
|
25176
|
+
child.getFooterRes?.()
|
|
25177
|
+
]) addDependencyPackageIdFromUiValue(ref);
|
|
25178
|
+
for (const item of child.getInstanceComboItems?.() ?? []) addDependencyPackageIdFromUiValue(item.icon ?? void 0);
|
|
25179
|
+
for (const item of child.getListItems?.() ?? []) {
|
|
25180
|
+
addDependencyPackageIdFromUiValue(item.icon ?? void 0);
|
|
25181
|
+
addDependencyPackageIdFromUiValue(item.url ?? void 0);
|
|
25182
|
+
}
|
|
25183
|
+
for (const gear of child.listGears?.() ?? []) {
|
|
25184
|
+
addDependencyPackageIdsFromUnknown(gear.getValues?.());
|
|
25185
|
+
addDependencyPackageIdsFromUnknown(gear.getDefaultValue?.());
|
|
25186
|
+
}
|
|
25187
|
+
}
|
|
25188
|
+
addDependencyFontRef(component.getFont?.());
|
|
25189
|
+
for (const ref of [
|
|
25190
|
+
component.getDropdown?.(),
|
|
25191
|
+
component.getHeaderRes?.(),
|
|
25192
|
+
component.getFooterRes?.(),
|
|
25193
|
+
component.getVtScrollBarRes?.(),
|
|
25194
|
+
component.getHzScrollBarRes?.(),
|
|
25195
|
+
component.getSound?.()
|
|
25196
|
+
]) addDependencyPackageIdFromUiValue(ref);
|
|
25197
|
+
for (const transition of component.listTransitions?.() ?? []) for (const item of transition.listItems?.() ?? []) {
|
|
25198
|
+
addDependencyPackageIdsFromUnknown(item.getStartValue?.());
|
|
25199
|
+
addDependencyPackageIdsFromUnknown(item.getEndValue?.());
|
|
25200
|
+
}
|
|
24652
25201
|
}
|
|
24653
25202
|
for (const dep of pkg.listDependencies()) pkg.removeDependency(dep);
|
|
24654
25203
|
if (referencedPkgIds.size > 0) {
|
|
24655
|
-
const sortedIds = [...referencedPkgIds].sort((a, b) =>
|
|
25204
|
+
const sortedIds = [...referencedPkgIds].sort((a, b) => {
|
|
25205
|
+
const orderA = packageOrder.get(a) ?? Number.MAX_SAFE_INTEGER;
|
|
25206
|
+
const orderB = packageOrder.get(b) ?? Number.MAX_SAFE_INTEGER;
|
|
25207
|
+
if (orderA !== orderB) return orderA - orderB;
|
|
25208
|
+
return a.localeCompare(b);
|
|
25209
|
+
});
|
|
24656
25210
|
for (const refId of sortedIds) {
|
|
24657
25211
|
const depPkg = pkgMap.get(refId);
|
|
24658
25212
|
if (depPkg) pkg.addDependency(depPkg);
|
|
@@ -24660,98 +25214,238 @@ function _computeDependencies(pkg, pkgMap) {
|
|
|
24660
25214
|
}
|
|
24661
25215
|
}
|
|
24662
25216
|
//#endregion
|
|
24663
|
-
//#region src/
|
|
24664
|
-
|
|
24665
|
-
|
|
24666
|
-
|
|
24667
|
-
|
|
24668
|
-
|
|
24669
|
-
|
|
24670
|
-
|
|
24671
|
-
|
|
24672
|
-
|
|
24673
|
-
|
|
24674
|
-
|
|
24675
|
-
|
|
24676
|
-
|
|
24677
|
-
|
|
24678
|
-
|
|
24679
|
-
|
|
24680
|
-
|
|
24681
|
-
|
|
24682
|
-
|
|
24683
|
-
|
|
24684
|
-
|
|
24685
|
-
|
|
24686
|
-
|
|
24687
|
-
|
|
24688
|
-
|
|
24689
|
-
|
|
24690
|
-
|
|
24691
|
-
|
|
24692
|
-
|
|
24693
|
-
|
|
24694
|
-
|
|
24695
|
-
|
|
24696
|
-
|
|
24697
|
-
|
|
24698
|
-
|
|
24699
|
-
|
|
24700
|
-
}
|
|
24701
|
-
|
|
24702
|
-
|
|
24703
|
-
|
|
24704
|
-
|
|
24705
|
-
|
|
24706
|
-
|
|
24707
|
-
|
|
24708
|
-
|
|
24709
|
-
}
|
|
24710
|
-
|
|
25217
|
+
//#region ../core/src/io/node-io.ts
|
|
25218
|
+
/**
|
|
25219
|
+
* Node.js I/O implementation for reading and writing FairyGUI projects.
|
|
25220
|
+
*
|
|
25221
|
+
* Usage:
|
|
25222
|
+
*
|
|
25223
|
+
* ```ts
|
|
25224
|
+
* import { NodeIO } from '@openfairygui/core/node';
|
|
25225
|
+
*
|
|
25226
|
+
* const io = new NodeIO();
|
|
25227
|
+
* const doc = await io.readProject('./path/to/project.fairy');
|
|
25228
|
+
* await io.writeProject(doc, './path/to/output.fairy');
|
|
25229
|
+
* const doc2 = await io.readBinary('./path/to/package_fui.bytes');
|
|
25230
|
+
* ```
|
|
25231
|
+
*
|
|
25232
|
+
* @category I/O
|
|
25233
|
+
*/
|
|
25234
|
+
var NodeIO = class extends PlatformIO {
|
|
25235
|
+
createFileSystem() {
|
|
25236
|
+
return {
|
|
25237
|
+
async readFile(filePath) {
|
|
25238
|
+
return fs$1.readFile(filePath, "utf-8");
|
|
25239
|
+
},
|
|
25240
|
+
async readFileRaw(filePath) {
|
|
25241
|
+
const buf = await fs$1.readFile(filePath);
|
|
25242
|
+
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
25243
|
+
},
|
|
25244
|
+
async writeFile(filePath, content) {
|
|
25245
|
+
await fs$1.writeFile(filePath, content, "utf-8");
|
|
25246
|
+
},
|
|
25247
|
+
async writeFileRaw(filePath, data) {
|
|
25248
|
+
await fs$1.writeFile(filePath, data);
|
|
25249
|
+
},
|
|
25250
|
+
async mkdir(dirPath) {
|
|
25251
|
+
await fs$1.mkdir(dirPath, { recursive: true });
|
|
25252
|
+
},
|
|
25253
|
+
async readdir(dirPath) {
|
|
25254
|
+
const entries = await fs$1.readdir(dirPath, { withFileTypes: true });
|
|
25255
|
+
return (await Promise.all(entries.map(async (entry) => {
|
|
25256
|
+
if (entry.isDirectory()) return entry.name;
|
|
25257
|
+
if (!entry.isSymbolicLink()) return null;
|
|
25258
|
+
try {
|
|
25259
|
+
return (await fs$1.stat(path$1.join(dirPath, entry.name))).isDirectory() ? entry.name : null;
|
|
25260
|
+
} catch {
|
|
25261
|
+
return null;
|
|
25262
|
+
}
|
|
25263
|
+
}))).filter((entry) => entry !== null);
|
|
25264
|
+
},
|
|
25265
|
+
async exists(filePath) {
|
|
25266
|
+
try {
|
|
25267
|
+
await fs$1.access(filePath);
|
|
25268
|
+
return true;
|
|
25269
|
+
} catch {
|
|
25270
|
+
return false;
|
|
25271
|
+
}
|
|
25272
|
+
},
|
|
25273
|
+
join(...paths) {
|
|
25274
|
+
return path$1.join(...paths);
|
|
25275
|
+
},
|
|
25276
|
+
dirname(filePath) {
|
|
25277
|
+
return path$1.dirname(filePath);
|
|
25278
|
+
}
|
|
25279
|
+
};
|
|
25280
|
+
}
|
|
25281
|
+
};
|
|
25282
|
+
//#endregion
|
|
25283
|
+
//#region src/utils/project-input.ts
|
|
24711
25284
|
/** Resolve input to a .fairy file path. Accepts a directory or a .fairy file. */
|
|
24712
25285
|
async function resolveFairyPath(input) {
|
|
24713
25286
|
const resolved = path.resolve(input);
|
|
24714
25287
|
const stat = await fs.stat(resolved);
|
|
24715
25288
|
if (stat.isFile() && resolved.endsWith(".fairy")) return resolved;
|
|
24716
25289
|
if (stat.isDirectory()) {
|
|
24717
|
-
const fairyFiles = (await fs.readdir(resolved)).filter((
|
|
25290
|
+
const fairyFiles = (await fs.readdir(resolved)).filter((entry) => entry.endsWith(".fairy"));
|
|
24718
25291
|
if (fairyFiles.length === 1) return path.join(resolved, fairyFiles[0]);
|
|
24719
25292
|
if (fairyFiles.length > 1) throw new Error(`Multiple .fairy files found in ${resolved}: ${fairyFiles.join(", ")}. Please specify one.`);
|
|
24720
25293
|
throw new Error(`No .fairy file found in ${resolved}`);
|
|
24721
25294
|
}
|
|
24722
25295
|
throw new Error(`Input is not a .fairy file or directory: ${resolved}`);
|
|
24723
25296
|
}
|
|
24724
|
-
|
|
24725
|
-
|
|
24726
|
-
|
|
24727
|
-
|
|
24728
|
-
|
|
24729
|
-
|
|
24730
|
-
|
|
24731
|
-
|
|
24732
|
-
|
|
24733
|
-
|
|
24734
|
-
|
|
24735
|
-
|
|
24736
|
-
|
|
24737
|
-
|
|
24738
|
-
|
|
24739
|
-
|
|
24740
|
-
|
|
24741
|
-
|
|
24742
|
-
|
|
24743
|
-
|
|
24744
|
-
|
|
24745
|
-
|
|
24746
|
-
|
|
24747
|
-
|
|
24748
|
-
|
|
24749
|
-
|
|
24750
|
-
console.error(`Unknown command: ${command}\n`);
|
|
24751
|
-
console.log(HELP);
|
|
24752
|
-
process.exit(1);
|
|
25297
|
+
//#endregion
|
|
25298
|
+
//#region src/commands/inspect.ts
|
|
25299
|
+
function registerInspectCommand(program) {
|
|
25300
|
+
program.command("inspect").description("Show project contents report").argument("<project-dir>", "Project root directory or .fairy file").action(async (projectDir) => {
|
|
25301
|
+
const fairyPath = await resolveFairyPath(projectDir);
|
|
25302
|
+
console.log(`Project: ${fairyPath}\n`);
|
|
25303
|
+
printReport(inspect(await new NodeIO().readProject(fairyPath)));
|
|
25304
|
+
});
|
|
25305
|
+
}
|
|
25306
|
+
function printReport(report) {
|
|
25307
|
+
console.log(`ID: ${report.projectId}`);
|
|
25308
|
+
console.log(`Type: ${report.projectType}, Version: ${report.version}`);
|
|
25309
|
+
console.log(`\nPackages: ${report.totals.packages}`);
|
|
25310
|
+
console.log(` Images: ${report.totals.images}`);
|
|
25311
|
+
console.log(` Sounds: ${report.totals.sounds}`);
|
|
25312
|
+
console.log(` Fonts: ${report.totals.fonts}`);
|
|
25313
|
+
console.log(` MovieClips: ${report.totals.movieClips}`);
|
|
25314
|
+
console.log(` Components: ${report.totals.components}`);
|
|
25315
|
+
console.log(` DisplayObjs: ${report.totals.displayObjects}`);
|
|
25316
|
+
console.log(` Gears: ${report.totals.gears}`);
|
|
25317
|
+
console.log(` Controllers: ${report.totals.controllers}`);
|
|
25318
|
+
console.log(` Transitions: ${report.totals.transitions}`);
|
|
25319
|
+
console.log("\nPackage details:");
|
|
25320
|
+
for (const pkg of report.packages) {
|
|
25321
|
+
const res = pkg.resources;
|
|
25322
|
+
console.log(` ${pkg.name} (${pkg.id}): ${res.images.count} img, ${res.sounds.count} snd, ${res.fonts.count} font, ${res.components.count} comp`);
|
|
24753
25323
|
}
|
|
24754
25324
|
}
|
|
25325
|
+
//#endregion
|
|
25326
|
+
//#region src/utils/project-type.ts
|
|
25327
|
+
function parseProjectType(value) {
|
|
25328
|
+
if (!value) return void 0;
|
|
25329
|
+
const trimmed = value.trim();
|
|
25330
|
+
if (trimmed === "") return void 0;
|
|
25331
|
+
if (/^\d+$/u.test(trimmed)) return Number(trimmed);
|
|
25332
|
+
const normalized = trimmed.toLowerCase();
|
|
25333
|
+
const map = {
|
|
25334
|
+
unity: ProjectType.Unity,
|
|
25335
|
+
flash: ProjectType.Flash,
|
|
25336
|
+
starling: ProjectType.Starling,
|
|
25337
|
+
cocoscreator: ProjectType.CocosCreator,
|
|
25338
|
+
cocos: ProjectType.CocosCreator,
|
|
25339
|
+
layabox: ProjectType.LayaBox,
|
|
25340
|
+
laya: ProjectType.LayaBox,
|
|
25341
|
+
egret: ProjectType.Egret,
|
|
25342
|
+
haxe: ProjectType.Haxe,
|
|
25343
|
+
pixi: ProjectType.Pixi,
|
|
25344
|
+
libgdx: ProjectType.LibGDX,
|
|
25345
|
+
unreal: ProjectType.Unreal,
|
|
25346
|
+
cryengine: ProjectType.CryEngine,
|
|
25347
|
+
monogame: ProjectType.MonoGame,
|
|
25348
|
+
vision: ProjectType.Vision
|
|
25349
|
+
};
|
|
25350
|
+
const resolved = map[normalized];
|
|
25351
|
+
if (resolved === void 0) throw new Error(`Unknown project type: ${value}. Use a numeric id or one of: ${Object.keys(map).join(", ")}`);
|
|
25352
|
+
return resolved;
|
|
25353
|
+
}
|
|
25354
|
+
//#endregion
|
|
25355
|
+
//#region src/commands/publish.ts
|
|
25356
|
+
function registerPublishCommand(program) {
|
|
25357
|
+
program.command("publish").description("Publish project to binary outputs and configured generated code").argument("<project-dir>", "Project root directory or .fairy file").option("-o, --output <dir>", "Override project or package publish output directory").option("-c, --compressed", "Compress binary data (overrides project setting)").option("-p, --packages <a,b,c>", "Only publish specific packages (comma-separated)").option("-b, --branch <name>", "Active branch used by \"主干合并活跃分支\"; omit for main branch").option("-t, --project-type <name|id>", "Override project type (for example: unity, layabox, cocoscreator, 0, 4, 3)").action(async (projectDir, options) => {
|
|
25358
|
+
const fairyPath = await resolveFairyPath(projectDir);
|
|
25359
|
+
const projectRootDir = path.dirname(fairyPath);
|
|
25360
|
+
const outputDir = options.output ? path.resolve(options.output) : void 0;
|
|
25361
|
+
console.log(`Reading project: ${fairyPath}`);
|
|
25362
|
+
const doc = await new NodeIO().readProject(fairyPath);
|
|
25363
|
+
const projectType = parseProjectType(options.projectType);
|
|
25364
|
+
if (projectType !== void 0) doc.getRoot().setProjectType(projectType);
|
|
25365
|
+
const pkgFilter = options.packages?.split(",").map((value) => value.trim());
|
|
25366
|
+
const resolved = resolvePublishOptions(doc, {
|
|
25367
|
+
compressed: options.compressed,
|
|
25368
|
+
packages: pkgFilter
|
|
25369
|
+
});
|
|
25370
|
+
console.log(`Settings: ext=${resolved.fileExtension}, compressed=${resolved.compressed}`);
|
|
25371
|
+
if (options.branch) console.log(`Active branch: ${options.branch}`);
|
|
25372
|
+
const atlasConfig = {
|
|
25373
|
+
...resolved.atlas,
|
|
25374
|
+
readFileRaw: async (filePath) => {
|
|
25375
|
+
const buf = await fs.readFile(filePath);
|
|
25376
|
+
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
25377
|
+
}
|
|
25378
|
+
};
|
|
25379
|
+
let encoder;
|
|
25380
|
+
try {
|
|
25381
|
+
const sharp = await import("sharp");
|
|
25382
|
+
encoder = sharp.default ?? sharp;
|
|
25383
|
+
console.log("Sharp loaded — atlas PNGs will be generated.");
|
|
25384
|
+
} catch {
|
|
25385
|
+
console.log("Sharp not available — atlas PNGs will NOT be generated (layout only).");
|
|
25386
|
+
console.log(" Install sharp to enable: pnpm add sharp");
|
|
25387
|
+
}
|
|
25388
|
+
await doc.transform(publish({
|
|
25389
|
+
output: outputDir,
|
|
25390
|
+
compressed: resolved.compressed,
|
|
25391
|
+
fileExtension: resolved.fileExtension,
|
|
25392
|
+
packages: resolved.packages,
|
|
25393
|
+
fs: {
|
|
25394
|
+
async readFileRaw(filePath) {
|
|
25395
|
+
const buf = await fs.readFile(filePath);
|
|
25396
|
+
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
25397
|
+
},
|
|
25398
|
+
async writeFileRaw(filePath, data) {
|
|
25399
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
25400
|
+
await fs.writeFile(filePath, data);
|
|
25401
|
+
},
|
|
25402
|
+
async mkdir(dirPath) {
|
|
25403
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
25404
|
+
},
|
|
25405
|
+
async readdir(dirPath) {
|
|
25406
|
+
return fs.readdir(dirPath);
|
|
25407
|
+
},
|
|
25408
|
+
async deleteFile(filePath) {
|
|
25409
|
+
await fs.rm(filePath, { force: true });
|
|
25410
|
+
},
|
|
25411
|
+
join(...paths) {
|
|
25412
|
+
return path.join(...paths);
|
|
25413
|
+
}
|
|
25414
|
+
},
|
|
25415
|
+
encoder,
|
|
25416
|
+
basePath: path.join(projectRootDir, "assets"),
|
|
25417
|
+
atlas: atlasConfig,
|
|
25418
|
+
branch: options.branch
|
|
25419
|
+
}));
|
|
25420
|
+
console.log(`\nDone!${outputDir ? ` Output override: ${outputDir}` : ""}`);
|
|
25421
|
+
});
|
|
25422
|
+
}
|
|
25423
|
+
//#endregion
|
|
25424
|
+
//#region src/commands/restore.ts
|
|
25425
|
+
function registerRestoreCommand(program) {
|
|
25426
|
+
program.command("restore").description("Restore a FairyGUI project from published binaries").argument("<release-dir>", "Published release directory").requiredOption("-o, --output <dir>", "Output project directory").option("-p, --packages <a,b,c>", "Only restore specific packages (comma-separated)").option("-f, --force", "Overwrite a non-empty output directory").option("-t, --project-type <name|id>", "Override restored project type; default is unity").action(async (releaseDir, options) => {
|
|
25427
|
+
const inputDir = path.resolve(releaseDir);
|
|
25428
|
+
const outputDir = path.resolve(options.output);
|
|
25429
|
+
const pkgFilter = options.packages ? options.packages.split(",").map((value) => value.trim()).filter(Boolean) : void 0;
|
|
25430
|
+
const projectType = parseProjectType(options.projectType);
|
|
25431
|
+
const { cropImage, extractImage } = await createRestoreImageProcessors();
|
|
25432
|
+
console.log(`Restoring published FairyGUI project: ${inputDir}`);
|
|
25433
|
+
const result = await restore({
|
|
25434
|
+
inputDir,
|
|
25435
|
+
output: outputDir,
|
|
25436
|
+
fs: createNodeRestoreFs(),
|
|
25437
|
+
packages: pkgFilter,
|
|
25438
|
+
force: options.force,
|
|
25439
|
+
projectType,
|
|
25440
|
+
cropImage,
|
|
25441
|
+
extractImage
|
|
25442
|
+
});
|
|
25443
|
+
const packages = result.document.getRoot().listPackages();
|
|
25444
|
+
console.log(`\nDone! Output: ${result.projectPath}`);
|
|
25445
|
+
console.log(`Packages: ${packages.map((pkg) => pkg.getName()).join(", ")}`);
|
|
25446
|
+
for (const warning of result.warnings) console.warn(`Warning: ${warning}`);
|
|
25447
|
+
});
|
|
25448
|
+
}
|
|
24755
25449
|
function createNodeRestoreFs() {
|
|
24756
25450
|
return {
|
|
24757
25451
|
async readFile(filePath) {
|
|
@@ -24860,214 +25554,47 @@ async function createRestoreImageProcessors() {
|
|
|
24860
25554
|
}
|
|
24861
25555
|
};
|
|
24862
25556
|
}
|
|
24863
|
-
|
|
24864
|
-
|
|
24865
|
-
|
|
24866
|
-
|
|
24867
|
-
|
|
24868
|
-
|
|
24869
|
-
console.log(`Project: ${fairyPath}\n`);
|
|
24870
|
-
printReport(inspect(await new NodeIO().readProject(fairyPath)));
|
|
25557
|
+
//#endregion
|
|
25558
|
+
//#region src/utils/package-version.ts
|
|
25559
|
+
const require = createRequire(import.meta.url);
|
|
25560
|
+
function getInjectedPackageVersion() {
|
|
25561
|
+
const version = import.meta.env?.PACKAGE_VERSION;
|
|
25562
|
+
return typeof version === "string" && version.length > 0 ? version : null;
|
|
24871
25563
|
}
|
|
24872
|
-
function
|
|
24873
|
-
|
|
24874
|
-
|
|
24875
|
-
|
|
24876
|
-
|
|
24877
|
-
|
|
24878
|
-
|
|
24879
|
-
|
|
24880
|
-
console.log(` Components: ${report.totals.components}`);
|
|
24881
|
-
console.log(` DisplayObjs: ${report.totals.displayObjects}`);
|
|
24882
|
-
console.log(` Gears: ${report.totals.gears}`);
|
|
24883
|
-
console.log(` Controllers: ${report.totals.controllers}`);
|
|
24884
|
-
console.log(` Transitions: ${report.totals.transitions}`);
|
|
24885
|
-
console.log("\nPackage details:");
|
|
24886
|
-
for (const pkg of report.packages) {
|
|
24887
|
-
const res = pkg.resources;
|
|
24888
|
-
console.log(` ${pkg.name} (${pkg.id}): ${res.images.count} img, ${res.sounds.count} snd, ${res.fonts.count} font, ${res.components.count} comp`);
|
|
24889
|
-
}
|
|
25564
|
+
function readPackageVersion() {
|
|
25565
|
+
const injectedVersion = getInjectedPackageVersion();
|
|
25566
|
+
if (injectedVersion) return injectedVersion;
|
|
25567
|
+
try {
|
|
25568
|
+
const pkg = require("../../package.json");
|
|
25569
|
+
if (typeof pkg.version === "string" && pkg.version.length > 0) return pkg.version;
|
|
25570
|
+
} catch {}
|
|
25571
|
+
return "0.0.0-dev";
|
|
24890
25572
|
}
|
|
24891
|
-
|
|
24892
|
-
|
|
24893
|
-
|
|
24894
|
-
|
|
24895
|
-
|
|
24896
|
-
|
|
24897
|
-
|
|
24898
|
-
|
|
24899
|
-
|
|
24900
|
-
|
|
24901
|
-
|
|
24902
|
-
|
|
24903
|
-
|
|
24904
|
-
|
|
24905
|
-
|
|
24906
|
-
|
|
24907
|
-
|
|
24908
|
-
|
|
24909
|
-
|
|
24910
|
-
cryengine: ProjectType.CryEngine,
|
|
24911
|
-
monogame: ProjectType.MonoGame,
|
|
24912
|
-
vision: ProjectType.Vision
|
|
24913
|
-
};
|
|
24914
|
-
const resolved = map[normalized];
|
|
24915
|
-
if (resolved === void 0) throw new Error(`Unknown project type: ${value}. Use a numeric id or one of: ${Object.keys(map).join(", ")}`);
|
|
24916
|
-
return resolved;
|
|
25573
|
+
//#endregion
|
|
25574
|
+
//#region src/cli.ts
|
|
25575
|
+
const PACKAGE_VERSION = readPackageVersion();
|
|
25576
|
+
function createProgram() {
|
|
25577
|
+
const program = new Command("ofgui");
|
|
25578
|
+
program.description("FairyGUI Headless Authoring CLI").version(PACKAGE_VERSION).showHelpAfterError();
|
|
25579
|
+
registerInspectCommand(program);
|
|
25580
|
+
registerPublishCommand(program);
|
|
25581
|
+
registerRestoreCommand(program);
|
|
25582
|
+
registerBackendCapabilitiesCommand(program);
|
|
25583
|
+
program.addHelpText("after", [
|
|
25584
|
+
"",
|
|
25585
|
+
"Alias:",
|
|
25586
|
+
" openfairygui",
|
|
25587
|
+
"",
|
|
25588
|
+
"Input can be a .fairy file or a project root directory (auto-discovers .fairy file).",
|
|
25589
|
+
"File extension and binary format are read from project settings."
|
|
25590
|
+
].join("\n"));
|
|
25591
|
+
return program;
|
|
24917
25592
|
}
|
|
24918
|
-
async function
|
|
24919
|
-
|
|
24920
|
-
args,
|
|
24921
|
-
options: {
|
|
24922
|
-
output: {
|
|
24923
|
-
type: "string",
|
|
24924
|
-
short: "o"
|
|
24925
|
-
},
|
|
24926
|
-
packages: { type: "string" },
|
|
24927
|
-
force: { type: "boolean" },
|
|
24928
|
-
"project-type": { type: "string" }
|
|
24929
|
-
},
|
|
24930
|
-
allowPositionals: true
|
|
24931
|
-
});
|
|
24932
|
-
if (positionals.length === 0 || !values.output) {
|
|
24933
|
-
console.error("Usage: ofgui restore <release-dir> --output <dir> [--packages a,b,c] [--force]");
|
|
24934
|
-
process.exit(1);
|
|
24935
|
-
}
|
|
24936
|
-
const releaseDir = path.resolve(positionals[0]);
|
|
24937
|
-
const outputDir = path.resolve(values.output);
|
|
24938
|
-
const pkgFilter = values.packages ? values.packages.split(",").map((s) => s.trim()).filter(Boolean) : void 0;
|
|
24939
|
-
const projectType = parseProjectType(values["project-type"]);
|
|
24940
|
-
const { cropImage, extractImage } = await createRestoreImageProcessors();
|
|
24941
|
-
console.log(`Restoring published FairyGUI project: ${releaseDir}`);
|
|
24942
|
-
const result = await restore({
|
|
24943
|
-
inputDir: releaseDir,
|
|
24944
|
-
output: outputDir,
|
|
24945
|
-
fs: createNodeRestoreFs(),
|
|
24946
|
-
packages: pkgFilter,
|
|
24947
|
-
force: values.force,
|
|
24948
|
-
projectType,
|
|
24949
|
-
cropImage,
|
|
24950
|
-
extractImage
|
|
24951
|
-
});
|
|
24952
|
-
const packages = result.document.getRoot().listPackages();
|
|
24953
|
-
console.log(`\nDone! Output: ${result.projectPath}`);
|
|
24954
|
-
console.log(`Packages: ${packages.map((pkg) => pkg.getName()).join(", ")}`);
|
|
24955
|
-
for (const warning of result.warnings) console.warn(`Warning: ${warning}`);
|
|
24956
|
-
}
|
|
24957
|
-
async function cmdPublish(args) {
|
|
24958
|
-
const { values, positionals } = parseArgs({
|
|
24959
|
-
args,
|
|
24960
|
-
options: {
|
|
24961
|
-
output: {
|
|
24962
|
-
type: "string",
|
|
24963
|
-
short: "o"
|
|
24964
|
-
},
|
|
24965
|
-
compressed: { type: "boolean" },
|
|
24966
|
-
packages: { type: "string" },
|
|
24967
|
-
branch: { type: "string" },
|
|
24968
|
-
"project-type": { type: "string" }
|
|
24969
|
-
},
|
|
24970
|
-
allowPositionals: true
|
|
24971
|
-
});
|
|
24972
|
-
if (positionals.length === 0 || !values.output) {
|
|
24973
|
-
console.error("Usage: ofgui publish <project-dir> --output <dir> [--compressed] [--packages a,b,c] [--branch name]");
|
|
24974
|
-
process.exit(1);
|
|
24975
|
-
}
|
|
24976
|
-
const fairyPath = await resolveFairyPath(positionals[0]);
|
|
24977
|
-
const projectDir = path.dirname(fairyPath);
|
|
24978
|
-
const outputDir = path.resolve(values.output);
|
|
24979
|
-
console.log(`Reading project: ${fairyPath}`);
|
|
24980
|
-
const doc = await new NodeIO().readProject(fairyPath);
|
|
24981
|
-
const projectType = parseProjectType(values["project-type"]);
|
|
24982
|
-
if (projectType !== void 0) doc.getRoot().setProjectType(projectType);
|
|
24983
|
-
const pkgFilter = values.packages ? values.packages.split(",").map((s) => s.trim()) : void 0;
|
|
24984
|
-
const resolved = resolvePublishOptions(doc, {
|
|
24985
|
-
compressed: values.compressed,
|
|
24986
|
-
packages: pkgFilter
|
|
24987
|
-
});
|
|
24988
|
-
console.log(`Settings: ext=${resolved.fileExtension}, compressed=${resolved.compressed}`);
|
|
24989
|
-
if (values.branch) console.log(`Active branch: ${values.branch}`);
|
|
24990
|
-
const atlasConfig = {
|
|
24991
|
-
...resolved.atlas,
|
|
24992
|
-
readFileRaw: async (filePath) => {
|
|
24993
|
-
const buf = await fs.readFile(filePath);
|
|
24994
|
-
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
24995
|
-
}
|
|
24996
|
-
};
|
|
24997
|
-
let encoder;
|
|
24998
|
-
try {
|
|
24999
|
-
const sharp = await import("sharp");
|
|
25000
|
-
encoder = sharp.default ?? sharp;
|
|
25001
|
-
console.log("Sharp loaded — atlas PNGs will be generated.");
|
|
25002
|
-
} catch {
|
|
25003
|
-
console.log("Sharp not available — atlas PNGs will NOT be generated (layout only).");
|
|
25004
|
-
console.log(" Install sharp to enable: pnpm add sharp");
|
|
25005
|
-
}
|
|
25006
|
-
await doc.transform(publish({
|
|
25007
|
-
output: outputDir,
|
|
25008
|
-
compressed: resolved.compressed,
|
|
25009
|
-
fileExtension: resolved.fileExtension,
|
|
25010
|
-
packages: resolved.packages,
|
|
25011
|
-
fs: {
|
|
25012
|
-
async readFileRaw(filePath) {
|
|
25013
|
-
const buf = await fs.readFile(filePath);
|
|
25014
|
-
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
25015
|
-
},
|
|
25016
|
-
async writeFileRaw(filePath, data) {
|
|
25017
|
-
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
25018
|
-
await fs.writeFile(filePath, data);
|
|
25019
|
-
},
|
|
25020
|
-
async mkdir(dirPath) {
|
|
25021
|
-
await fs.mkdir(dirPath, { recursive: true });
|
|
25022
|
-
},
|
|
25023
|
-
async readdir(dirPath) {
|
|
25024
|
-
return fs.readdir(dirPath);
|
|
25025
|
-
},
|
|
25026
|
-
async deleteFile(filePath) {
|
|
25027
|
-
await fs.rm(filePath, { force: true });
|
|
25028
|
-
},
|
|
25029
|
-
join(...paths) {
|
|
25030
|
-
return path.join(...paths);
|
|
25031
|
-
}
|
|
25032
|
-
},
|
|
25033
|
-
encoder,
|
|
25034
|
-
basePath: path.join(projectDir, "assets"),
|
|
25035
|
-
atlas: atlasConfig,
|
|
25036
|
-
branch: values.branch
|
|
25037
|
-
}));
|
|
25038
|
-
console.log(`\nDone! Output: ${outputDir}`);
|
|
25039
|
-
}
|
|
25040
|
-
async function cmdBackendCapabilities(args) {
|
|
25041
|
-
if (args.length === 0) {
|
|
25042
|
-
console.error("Usage: ofgui backend-capabilities <project-dir>");
|
|
25043
|
-
process.exit(1);
|
|
25044
|
-
}
|
|
25045
|
-
const runtime = createNodeBackendRuntime();
|
|
25046
|
-
const opened = await runtime.openSession({ projectPath: path.resolve(args[0]) });
|
|
25047
|
-
if (!opened.ok) {
|
|
25048
|
-
console.error(`backend-capabilities: ${opened.error.message}`);
|
|
25049
|
-
process.exit(1);
|
|
25050
|
-
}
|
|
25051
|
-
const capabilities = runtime.getCapabilities();
|
|
25052
|
-
if (!capabilities.ok) {
|
|
25053
|
-
console.error("backend-capabilities: failed to read capabilities");
|
|
25054
|
-
await runtime.closeSession({ sessionId: opened.data.sessionId });
|
|
25055
|
-
process.exit(1);
|
|
25056
|
-
}
|
|
25057
|
-
console.log(`Session: ${opened.data.sessionId}`);
|
|
25058
|
-
console.log(`Project: ${opened.data.canonicalProjectPath}`);
|
|
25059
|
-
console.log(`Revision: ${opened.data.revision}`);
|
|
25060
|
-
console.log(`Runtime owner: ${capabilities.data.runtimeOwner}`);
|
|
25061
|
-
console.log(`Transaction owner: ${capabilities.data.transactionKernelOwner}`);
|
|
25062
|
-
console.log(`App seam owner: ${capabilities.data.appSeamOwner}`);
|
|
25063
|
-
const closed = await runtime.closeSession({ sessionId: opened.data.sessionId });
|
|
25064
|
-
if (!closed.ok) {
|
|
25065
|
-
console.error(`backend-capabilities: ${closed.error.message}`);
|
|
25066
|
-
process.exit(1);
|
|
25067
|
-
}
|
|
25593
|
+
async function main() {
|
|
25594
|
+
await createProgram().parseAsync(process.argv);
|
|
25068
25595
|
}
|
|
25069
25596
|
main().catch((err) => {
|
|
25070
|
-
console.error(err);
|
|
25597
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
25071
25598
|
process.exit(1);
|
|
25072
25599
|
});
|
|
25073
25600
|
//#endregion
|