@openfairygui/functions 0.2.0-alpha.19 → 0.2.0-alpha.20
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/README.md +7 -2
- package/dist/index.cjs +3 -920
- package/dist/index.d.cts +2 -46
- package/dist/index.d.ts +3 -47
- package/dist/index.js +2 -919
- package/dist/node.cjs +138 -10
- package/dist/node.d.cts +7 -2
- package/dist/node.d.ts +8 -3
- package/dist/node.js +138 -11
- package/dist/{publish-DsPK0SJ1.js → publish-BJ_eelME.js} +1973 -2070
- package/dist/{publish-D7268_u4.cjs → publish-xFWT9Slz.cjs} +1973 -2070
- package/dist/restore-BW2xacB3.cjs +936 -0
- package/dist/{codegen-B8ZM1F4j.d.cts → restore-BeWaJNjR.d.cts} +49 -3
- package/dist/restore-Clk62n0O.js +931 -0
- package/dist/{codegen-CfbDHuFt.d.ts → restore-Dh0-Nvms.d.ts} +50 -4
- package/dist/web.cjs +4 -2
- package/dist/web.d.ts +1 -1
- package/dist/web.js +4 -2
- package/package.json +5 -2
- package/src/adapters/node/restore.ts +187 -0
- package/src/adapters/web/publish.ts +1 -247
- package/src/adapters/web/raster.ts +251 -0
- package/src/atlas/font.ts +95 -0
- package/src/atlas/inputs.ts +515 -0
- package/src/atlas/jta.ts +211 -0
- package/src/atlas/packing.ts +767 -0
- package/src/atlas.ts +23 -1639
- package/src/node.ts +4 -0
- package/src/publish/external-resources.ts +117 -0
- package/src/publish/options.ts +180 -0
- package/src/publish/package-context.ts +608 -0
- package/src/publish/resource-references.ts +210 -0
- package/src/publish.ts +21 -1130
- package/src/restore-internals/font.ts +100 -0
- package/src/restore-internals/movie-clip.ts +104 -0
- package/src/restore-internals/output-transaction.ts +164 -0
- package/src/restore.ts +14 -329
- /package/dist/{atlas-CDn6TirX.d.ts → atlas-C6tbl7nn.d.ts} +0 -0
package/src/publish.ts
CHANGED
|
@@ -1,127 +1,35 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BinaryWriter,
|
|
3
3
|
type BinaryWriterOptions,
|
|
4
|
-
type Component,
|
|
5
4
|
type Document,
|
|
6
|
-
type DragonBonesResource,
|
|
7
5
|
type FileSystem,
|
|
8
|
-
type FontResource,
|
|
9
|
-
type ImageResource,
|
|
10
|
-
type MiscResource,
|
|
11
|
-
type MovieClipResource,
|
|
12
6
|
type Package,
|
|
13
|
-
ProjectType,
|
|
14
|
-
type SoundResource,
|
|
15
|
-
type SpineResource,
|
|
16
7
|
type Transform,
|
|
17
8
|
} from '@openfairygui/core';
|
|
18
|
-
import {
|
|
9
|
+
import { atlas } from './atlas.js';
|
|
19
10
|
import { publishCodeGeneration, resolveProjectBasePath } from './codegen.js';
|
|
20
11
|
import { formatPluginError, type LoadedPlugin } from './plugins/types.js';
|
|
21
|
-
import type {
|
|
22
|
-
import
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
12
|
+
import type { PublishFileSystem } from './publish/contracts.js';
|
|
13
|
+
import {
|
|
14
|
+
annotatePackagePublishArtifacts,
|
|
15
|
+
} from './publish/package-context.js';
|
|
16
|
+
import {
|
|
17
|
+
exportPackageExternalResources,
|
|
18
|
+
exportPackageSounds,
|
|
19
|
+
} from './publish/external-resources.js';
|
|
20
|
+
import {
|
|
21
|
+
resolvePublishAtlasRuntimeOptions,
|
|
22
|
+
resolvePublishFileName,
|
|
23
|
+
resolvePublishOptions,
|
|
24
|
+
type PublishOptions,
|
|
25
|
+
type ResolvedPublishAtlasOptions,
|
|
26
|
+
type ResolvedPublishOptions,
|
|
27
|
+
} from './publish/options.js';
|
|
28
|
+
import { collectPackageResourceReferences } from './publish/resource-references.js';
|
|
29
|
+
import type { CliPublishSettings, RootProjectSettings } from './shared-types.js';
|
|
28
30
|
import { createTransform } from './utils.js';
|
|
29
31
|
|
|
30
|
-
export
|
|
31
|
-
/**
|
|
32
|
-
* Output directory override for published files (.fui + atlas PNGs).
|
|
33
|
-
* When omitted, publish uses package-level or project-level publish paths.
|
|
34
|
-
*/
|
|
35
|
-
output?: string;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Compress the binary data with zlib raw deflate. Default: false.
|
|
39
|
-
*/
|
|
40
|
-
compressed?: boolean;
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* File extension for the binary output. Default: 'fui'.
|
|
44
|
-
* Unity projects typically use 'bytes'.
|
|
45
|
-
*/
|
|
46
|
-
fileExtension?: string;
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Raster backend for atlas image compositing.
|
|
50
|
-
* Required when a filesystem-backed publish has packable resources.
|
|
51
|
-
* Without a filesystem, publish remains an explicit layout-only transform.
|
|
52
|
-
*/
|
|
53
|
-
encoder?: AtlasRasterBackend;
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Base path for reading source images (project assets root).
|
|
57
|
-
* Required when encoder is provided.
|
|
58
|
-
*/
|
|
59
|
-
basePath?: string;
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Atlas packing options.
|
|
63
|
-
*/
|
|
64
|
-
atlas?: Omit<AtlasOptions, 'encoder' | 'basePath' | 'outputPath'>;
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Filter which packages to publish by name. If not set, all packages are published.
|
|
68
|
-
*/
|
|
69
|
-
packages?: string[];
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* FileSystem abstraction for writing output files.
|
|
73
|
-
* Required for actual file output. Calling publish with a resolved output
|
|
74
|
-
* directory but no filesystem is rejected; omit output entirely for a
|
|
75
|
-
* layout-only transform.
|
|
76
|
-
*/
|
|
77
|
-
fs?: PublishFileSystem;
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Active branch name used when branchProcessing is "主干合并活跃分支".
|
|
81
|
-
* Empty or omitted means publishing the main branch.
|
|
82
|
-
*/
|
|
83
|
-
branch?: string;
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Publish hooks supplied by the host adapter.
|
|
87
|
-
*
|
|
88
|
-
* Node adapters load project plugins. Browser adapters pass an empty list.
|
|
89
|
-
*/
|
|
90
|
-
plugins?: LoadedPlugin[];
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Run generic code generation after runtime artifacts. Default: true.
|
|
94
|
-
*/
|
|
95
|
-
codeGeneration?: boolean;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export interface ResolvedPublishAtlasOptions
|
|
99
|
-
extends Pick<
|
|
100
|
-
AtlasOptions,
|
|
101
|
-
| 'maxSize'
|
|
102
|
-
| 'fast'
|
|
103
|
-
| 'allowRotation'
|
|
104
|
-
| 'padding'
|
|
105
|
-
| 'powerOfTwo'
|
|
106
|
-
| 'square'
|
|
107
|
-
| 'multiPage'
|
|
108
|
-
| 'trimImage'
|
|
109
|
-
| 'extractAlpha'
|
|
110
|
-
> {}
|
|
111
|
-
|
|
112
|
-
export interface ResolvePublishOptionsOverrides {
|
|
113
|
-
compressed?: boolean;
|
|
114
|
-
fileExtension?: string;
|
|
115
|
-
packages?: string[];
|
|
116
|
-
atlas?: Partial<ResolvedPublishAtlasOptions>;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export interface ResolvedPublishOptions {
|
|
120
|
-
compressed: boolean;
|
|
121
|
-
fileExtension: string;
|
|
122
|
-
packages?: string[];
|
|
123
|
-
atlas: ResolvedPublishAtlasOptions;
|
|
124
|
-
}
|
|
32
|
+
export * from './publish/options.js';
|
|
125
33
|
|
|
126
34
|
interface ResolvedProjectPublishConfig extends ResolvedPublishOptions {
|
|
127
35
|
projectType: number;
|
|
@@ -165,165 +73,6 @@ async function runPublishPluginHook(
|
|
|
165
73
|
}
|
|
166
74
|
}
|
|
167
75
|
|
|
168
|
-
interface ImageResourceExtras extends Record<string, unknown> {
|
|
169
|
-
_fileName?: string;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
interface PublishFileExtras extends Record<string, unknown> {
|
|
173
|
-
_publishedFile?: string;
|
|
174
|
-
_publishedId?: string;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
interface BranchAwarePublishedResource {
|
|
178
|
-
getBranch?(): string;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
interface PackagePublishContext {
|
|
182
|
-
referencedIds: Set<string>;
|
|
183
|
-
publishedResourceIds: Set<string>;
|
|
184
|
-
exportedResourceIds: Set<string>;
|
|
185
|
-
pixelHitTestImageIds: Set<string>;
|
|
186
|
-
highResolutionItemIds: Map<string, Array<string | null>>;
|
|
187
|
-
effectiveResourceIds: Map<string, string>;
|
|
188
|
-
includeBranches: boolean;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
interface ChildReferenceItem {
|
|
192
|
-
icon?: string | null;
|
|
193
|
-
url?: string | null;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
interface GearWithPublishRefs {
|
|
197
|
-
getValues?(): string;
|
|
198
|
-
getDefaultValue?(): unknown;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
interface TransitionItemWithPublishRefs {
|
|
202
|
-
getStartValue?(): unknown;
|
|
203
|
-
getEndValue?(): unknown;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
interface TransitionWithPublishRefs {
|
|
207
|
-
listItems?(): TransitionItemWithPublishRefs[];
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
interface ChildWithPublishRefs extends HasOptionalFont {
|
|
211
|
-
getId?(): string;
|
|
212
|
-
getPackageId?(): string;
|
|
213
|
-
getSrc?(): string;
|
|
214
|
-
getUrl?(): string;
|
|
215
|
-
getInstanceSound?(): string;
|
|
216
|
-
getDefaultItem?(): string;
|
|
217
|
-
getIcon?(): string;
|
|
218
|
-
getSelectedIcon?(): string;
|
|
219
|
-
getDropdown?(): string;
|
|
220
|
-
getSound?(): string;
|
|
221
|
-
getText?(): string;
|
|
222
|
-
getInstanceIcon?(): string;
|
|
223
|
-
getInstanceSelectedIcon?(): string;
|
|
224
|
-
getVtScrollBarRes?(): string;
|
|
225
|
-
getHzScrollBarRes?(): string;
|
|
226
|
-
getHeaderRes?(): string;
|
|
227
|
-
getFooterRes?(): string;
|
|
228
|
-
getInstanceComboItems?(): Array<{ icon: string | null }>;
|
|
229
|
-
getListItems?(): ChildReferenceItem[];
|
|
230
|
-
listGears?(): GearWithPublishRefs[];
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
interface ComponentWithPublishRefs {
|
|
234
|
-
getId(): string;
|
|
235
|
-
getExported(): boolean;
|
|
236
|
-
listChildren(): ChildWithPublishRefs[];
|
|
237
|
-
getHitTest?(): string;
|
|
238
|
-
getDropdown?(): string;
|
|
239
|
-
getHeaderRes?(): string;
|
|
240
|
-
getFooterRes?(): string;
|
|
241
|
-
getVtScrollBarRes?(): string;
|
|
242
|
-
getHzScrollBarRes?(): string;
|
|
243
|
-
getSound?(): string;
|
|
244
|
-
getFont?(): string | string[] | null | undefined;
|
|
245
|
-
listTransitions?(): TransitionWithPublishRefs[];
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
const UNITY_PROJECT_TYPE = ProjectType.Unity;
|
|
249
|
-
const COCOS_CREATOR_PROJECT_TYPE = ProjectType.CocosCreator;
|
|
250
|
-
|
|
251
|
-
function resolveDefaultPublishFileExtension(projectType: number, publishSettings: CliPublishSettings): string {
|
|
252
|
-
if (projectType === UNITY_PROJECT_TYPE) {
|
|
253
|
-
return 'bytes';
|
|
254
|
-
}
|
|
255
|
-
if (projectType === COCOS_CREATOR_PROJECT_TYPE) {
|
|
256
|
-
return publishSettings.fileExtension || 'bin';
|
|
257
|
-
}
|
|
258
|
-
// publish() is currently a binary forward-publish path. For non-Unity projects,
|
|
259
|
-
// keep the emitted contract driven by the configured extension, falling back to
|
|
260
|
-
// `fui`, which intentionally covers the shared generic binary contract outside
|
|
261
|
-
// Unity and the Creator-specific default-to-bin rule.
|
|
262
|
-
return publishSettings.fileExtension || 'fui';
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
export interface PublishAtlasRuntimeOptions {
|
|
266
|
-
preserveInputOrderOnTie: boolean;
|
|
267
|
-
directSingleImageOutput: boolean;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
export function resolvePublishAtlasRuntimeOptions(fileExtension: string): PublishAtlasRuntimeOptions {
|
|
271
|
-
return {
|
|
272
|
-
preserveInputOrderOnTie: fileExtension === 'fui',
|
|
273
|
-
directSingleImageOutput: fileExtension === 'bytes',
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
function resolvePublishFileName(publishName: string, fileExtension: string): string {
|
|
278
|
-
if (fileExtension === 'bytes') {
|
|
279
|
-
return `${publishName}_fui.bytes`;
|
|
280
|
-
}
|
|
281
|
-
return `${publishName}.${fileExtension}`;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
/**
|
|
285
|
-
* Resolve publish defaults from the document's project settings.
|
|
286
|
-
*
|
|
287
|
-
* This keeps the editor-aligned publish rules reusable across environments,
|
|
288
|
-
* while callers still provide environment-specific concerns such as fs/encoder/basePath.
|
|
289
|
-
*/
|
|
290
|
-
export function resolvePublishOptions(
|
|
291
|
-
doc: Document,
|
|
292
|
-
overrides: ResolvePublishOptionsOverrides = {},
|
|
293
|
-
): ResolvedPublishOptions {
|
|
294
|
-
const root = doc.getRoot();
|
|
295
|
-
const settings = (root.getSettings?.() ?? {}) as RootProjectSettings;
|
|
296
|
-
const publishSettings: CliPublishSettings = settings.publish ?? {};
|
|
297
|
-
const atlasSetting = publishSettings.atlasSetting ?? {};
|
|
298
|
-
const projectType = root.getProjectType();
|
|
299
|
-
|
|
300
|
-
const fileExtension = overrides.fileExtension ?? resolveDefaultPublishFileExtension(projectType, publishSettings);
|
|
301
|
-
|
|
302
|
-
let compressed = overrides.compressed ?? publishSettings.compressDesc ?? false;
|
|
303
|
-
if (projectType === UNITY_PROJECT_TYPE) {
|
|
304
|
-
compressed = overrides.compressed ?? false;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
const atlasOptions: ResolvedPublishAtlasOptions = {
|
|
308
|
-
maxSize: overrides.atlas?.maxSize ?? atlasSetting.maxSize ?? 2048,
|
|
309
|
-
fast: overrides.atlas?.fast ?? atlasSetting.fast ?? true,
|
|
310
|
-
allowRotation: overrides.atlas?.allowRotation ?? atlasSetting.allowRotation ?? false,
|
|
311
|
-
padding: overrides.atlas?.padding ?? atlasSetting.padding ?? 2,
|
|
312
|
-
powerOfTwo: overrides.atlas?.powerOfTwo ?? atlasSetting.sizeOption === 'pot',
|
|
313
|
-
square: overrides.atlas?.square ?? atlasSetting.forceSquare ?? false,
|
|
314
|
-
multiPage: overrides.atlas?.multiPage ?? atlasSetting.paging ?? true,
|
|
315
|
-
trimImage: overrides.atlas?.trimImage ?? atlasSetting.trimImage ?? false,
|
|
316
|
-
extractAlpha: overrides.atlas?.extractAlpha ?? atlasSetting.extractAlpha ?? false,
|
|
317
|
-
};
|
|
318
|
-
|
|
319
|
-
return {
|
|
320
|
-
compressed,
|
|
321
|
-
fileExtension,
|
|
322
|
-
packages: overrides.packages,
|
|
323
|
-
atlas: atlasOptions,
|
|
324
|
-
};
|
|
325
|
-
}
|
|
326
|
-
|
|
327
76
|
function trimTrailingSlashes(value: string): string {
|
|
328
77
|
return value.replace(/[/\\]+$/, '');
|
|
329
78
|
}
|
|
@@ -367,761 +116,6 @@ function toBinaryWriterFileSystem(fs: PublishFileSystem): FileSystem {
|
|
|
367
116
|
};
|
|
368
117
|
}
|
|
369
118
|
|
|
370
|
-
function isComponentResource(resource: ReturnType<Package['listResources']>[number]): resource is Component {
|
|
371
|
-
return resource.propertyType === 'Component';
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
function isImageResource(resource: ReturnType<Package['listResources']>[number]): resource is ImageResource {
|
|
375
|
-
return resource.propertyType === 'ImageResource';
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
function isMovieClipResource(resource: ReturnType<Package['listResources']>[number]): resource is MovieClipResource {
|
|
379
|
-
return resource.propertyType === 'MovieClipResource';
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
function isHighResolutionResource(
|
|
383
|
-
resource: ReturnType<Package['listResources']>[number],
|
|
384
|
-
): resource is ImageResource | MovieClipResource {
|
|
385
|
-
return isImageResource(resource) || isMovieClipResource(resource);
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
function isMiscResource(resource: ReturnType<Package['listResources']>[number]): resource is MiscResource {
|
|
389
|
-
return resource.propertyType === 'MiscResource';
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
function isFontResource(resource: ReturnType<Package['listResources']>[number]): resource is FontResource {
|
|
393
|
-
return resource.propertyType === 'FontResource';
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
function isSoundResource(resource: ReturnType<Package['listResources']>[number]): resource is SoundResource {
|
|
397
|
-
return resource.propertyType === 'SoundResource';
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
function isSpineResource(resource: ReturnType<Package['listResources']>[number]): resource is SpineResource {
|
|
401
|
-
return resource.propertyType === 'SpineResource';
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
function isDragonBonesResource(
|
|
405
|
-
resource: ReturnType<Package['listResources']>[number],
|
|
406
|
-
): resource is DragonBonesResource {
|
|
407
|
-
return resource.propertyType === 'DragonBonesResource';
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
function isSkeletonResource(
|
|
411
|
-
resource: ReturnType<Package['listResources']>[number],
|
|
412
|
-
): resource is SpineResource | DragonBonesResource {
|
|
413
|
-
return isSpineResource(resource) || isDragonBonesResource(resource);
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
function addLocalUiResourceRef(target: Set<string>, pkgId: string, value: string | null | undefined): void {
|
|
417
|
-
if (!value || typeof value !== 'string' || !value.startsWith(`ui://${pkgId}`) || value.length <= 13) return;
|
|
418
|
-
target.add(value.slice(13));
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
function addLocalUiResourceRefsFromText(target: Set<string>, pkgId: string, value: string | null | undefined): void {
|
|
422
|
-
if (!value || typeof value !== 'string') return;
|
|
423
|
-
const prefix = `ui://${pkgId}`;
|
|
424
|
-
let index = value.indexOf(prefix);
|
|
425
|
-
while (index !== -1) {
|
|
426
|
-
const start = index + prefix.length;
|
|
427
|
-
let end = start;
|
|
428
|
-
while (end < value.length && /[0-9a-z]/i.test(value[end] ?? '')) end++;
|
|
429
|
-
if (end > start) target.add(value.slice(start, end));
|
|
430
|
-
index = value.indexOf(prefix, end);
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
function addLocalUiResourceRefsFromUnknown(target: Set<string>, pkgId: string, value: unknown): void {
|
|
435
|
-
if (Array.isArray(value)) {
|
|
436
|
-
for (const entry of value) addLocalUiResourceRefsFromUnknown(target, pkgId, entry);
|
|
437
|
-
return;
|
|
438
|
-
}
|
|
439
|
-
if (typeof value === 'string') {
|
|
440
|
-
addLocalUiResourceRef(target, pkgId, value);
|
|
441
|
-
addLocalUiResourceRefsFromText(target, pkgId, value);
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
function addLocalFontRef(target: Set<string>, pkgId: string, value: string | string[] | null | undefined): void {
|
|
446
|
-
if (Array.isArray(value)) {
|
|
447
|
-
for (const entry of value) addLocalUiResourceRef(target, pkgId, entry);
|
|
448
|
-
return;
|
|
449
|
-
}
|
|
450
|
-
addLocalUiResourceRef(target, pkgId, value ?? undefined);
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
function resolvePackageAssetsBasePath(basePath: string, resource: BranchAwarePublishedResource | undefined): string {
|
|
454
|
-
const branchName = resource?.getBranch?.() ?? '';
|
|
455
|
-
if (!branchName) return basePath;
|
|
456
|
-
const normalized = basePath.replace(/[/\\]+$/, '');
|
|
457
|
-
if (/[\\/]assets$/i.test(normalized)) {
|
|
458
|
-
return normalized.replace(/([\\/])assets$/i, `$1assets_${branchName}`);
|
|
459
|
-
}
|
|
460
|
-
return `${normalized}_${branchName}`;
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
function resolveImagePath(resource: ImageResource, pkg: Package, basePath: string): string {
|
|
464
|
-
const fileName = resolveImageFileName(resource);
|
|
465
|
-
const resourcePath = resource.getPath() ?? '/';
|
|
466
|
-
const packageBasePath = resolvePackageAssetsBasePath(basePath, resource);
|
|
467
|
-
return `${packageBasePath}/${pkg.getName()}${resourcePath}${fileName}`;
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
function resolveImageFileName(resource: ImageResource): string {
|
|
471
|
-
const extras = (resource.getExtras() as ImageResourceExtras | undefined) ?? {};
|
|
472
|
-
return resource.getFileName() || extras._fileName || resource.getName();
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
function resolveSoundPath(resource: SoundResource, pkg: Package, basePath: string): string {
|
|
476
|
-
const resourcePath = resource.getPath() ?? '/';
|
|
477
|
-
const packageBasePath = resolvePackageAssetsBasePath(basePath, resource);
|
|
478
|
-
return `${packageBasePath}/${pkg.getName()}${resourcePath}${resource.getFile()}`;
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
function resolveGenericResourcePath(
|
|
482
|
-
resource: { getPath(): string; getFile(): string; getBranch?(): string },
|
|
483
|
-
pkg: Package,
|
|
484
|
-
basePath: string,
|
|
485
|
-
): string {
|
|
486
|
-
const resourcePath = resource.getPath() ?? '/';
|
|
487
|
-
const packageBasePath = resolvePackageAssetsBasePath(basePath, resource);
|
|
488
|
-
return `${packageBasePath}/${pkg.getName()}${resourcePath}${resource.getFile()}`;
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
function extname(fileName: string): string {
|
|
492
|
-
const normalized = fileName.replace(/\\/g, '/');
|
|
493
|
-
const lastSlash = normalized.lastIndexOf('/');
|
|
494
|
-
const lastDot = normalized.lastIndexOf('.');
|
|
495
|
-
if (lastDot <= lastSlash) return '';
|
|
496
|
-
return normalized.slice(lastDot);
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
function resolvePublishedMiscFileName(resource: MiscResource, projectType: number): string {
|
|
500
|
-
const file = resource.getFile();
|
|
501
|
-
if (projectType !== UNITY_PROJECT_TYPE) return file;
|
|
502
|
-
if (file.toLowerCase().endsWith('.atlas')) return `${file}.txt`;
|
|
503
|
-
return file;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
function resolvePublishedSkeletonFileName(resource: SpineResource | DragonBonesResource, projectType: number): string {
|
|
507
|
-
if (
|
|
508
|
-
projectType === UNITY_PROJECT_TYPE &&
|
|
509
|
-
isSpineResource(resource) &&
|
|
510
|
-
resource.getFile().toLowerCase().endsWith('.skel')
|
|
511
|
-
) {
|
|
512
|
-
return `${resource.getFile()}.bytes`;
|
|
513
|
-
}
|
|
514
|
-
return resource.getFile();
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
function setPublishedFileExtra(
|
|
518
|
-
resource: { getExtras(): Record<string, unknown> | undefined; setExtras(value: Record<string, unknown>): unknown },
|
|
519
|
-
fileName: string,
|
|
520
|
-
): void {
|
|
521
|
-
const extras = (resource.getExtras() as PublishFileExtras | undefined) ?? {};
|
|
522
|
-
resource.setExtras({
|
|
523
|
-
...extras,
|
|
524
|
-
_publishedFile: fileName,
|
|
525
|
-
});
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
function setPublishedIdExtra(
|
|
529
|
-
resource: {
|
|
530
|
-
getId(): string;
|
|
531
|
-
getExtras(): Record<string, unknown> | undefined;
|
|
532
|
-
setExtras(value: Record<string, unknown>): unknown;
|
|
533
|
-
},
|
|
534
|
-
effectiveId: string | null,
|
|
535
|
-
): void {
|
|
536
|
-
const extras = (resource.getExtras() as PublishFileExtras | undefined) ?? {};
|
|
537
|
-
if (!effectiveId || effectiveId === resource.getId()) {
|
|
538
|
-
if (!('_publishedId' in extras)) return;
|
|
539
|
-
const { _publishedId: _ignored, ...rest } = extras;
|
|
540
|
-
resource.setExtras(rest);
|
|
541
|
-
return;
|
|
542
|
-
}
|
|
543
|
-
resource.setExtras({
|
|
544
|
-
...extras,
|
|
545
|
-
_publishedId: effectiveId,
|
|
546
|
-
});
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
function getPublishedId(resource: { getId(): string; getExtras(): Record<string, unknown> | undefined }): string {
|
|
550
|
-
const extras = (resource.getExtras() as PublishFileExtras | undefined) ?? {};
|
|
551
|
-
return extras._publishedId ?? resource.getId();
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
function getBranchName(resource: BranchAwarePublishedResource | undefined): string {
|
|
555
|
-
return resource?.getBranch?.() ?? '';
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
function buildBranchResourceKey(resource: { propertyType: string; getPath(): string; getName(): string }): string {
|
|
559
|
-
return `${resource.propertyType}|${resource.getPath() ?? ''}|${resource.getName() ?? ''}`;
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
const HIGH_RESOLUTION_LEVELS = [
|
|
563
|
-
{ scale: 2, bit: 1, slot: 0 },
|
|
564
|
-
{ scale: 3, bit: 2, slot: 1 },
|
|
565
|
-
{ scale: 4, bit: 4, slot: 2 },
|
|
566
|
-
] as const;
|
|
567
|
-
|
|
568
|
-
function buildHighResolutionResourceKey(
|
|
569
|
-
resource: {
|
|
570
|
-
propertyType: string;
|
|
571
|
-
getPath(): string;
|
|
572
|
-
getName(): string;
|
|
573
|
-
getBranch?(): string;
|
|
574
|
-
},
|
|
575
|
-
name = resource.getName(),
|
|
576
|
-
): string {
|
|
577
|
-
return `${resource.propertyType}|${resource.getBranch?.() ?? ''}|${resource.getPath() ?? ''}|${name}`;
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
function isHighResolutionVariantName(name: string): boolean {
|
|
581
|
-
return /@(?:2|3|4)x(?:\.[^./\\]+)?$/iu.test(name);
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
function appendHighResolutionScaleToName(name: string, scale: number): string {
|
|
585
|
-
const extensionIndex = name.lastIndexOf('.');
|
|
586
|
-
if (extensionIndex > 0) {
|
|
587
|
-
return `${name.slice(0, extensionIndex)}@${scale}x${name.slice(extensionIndex)}`;
|
|
588
|
-
}
|
|
589
|
-
return `${name}@${scale}x`;
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
function trimTrailingMissingHighResolutionIds(ids: Array<string | null>): Array<string | null> {
|
|
593
|
-
while (ids.length > 0 && !ids[ids.length - 1]) {
|
|
594
|
-
ids.pop();
|
|
595
|
-
}
|
|
596
|
-
return ids;
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
function collectHighResolutionItemIds(
|
|
600
|
-
resources: ReturnType<Package['listResources']>,
|
|
601
|
-
publishedResourceIds: Set<string>,
|
|
602
|
-
includeHighResolution: number,
|
|
603
|
-
): Map<string, Array<string | null>> {
|
|
604
|
-
const result = new Map<string, Array<string | null>>();
|
|
605
|
-
if (includeHighResolution <= 0) return result;
|
|
606
|
-
|
|
607
|
-
const highResolutionResourceByKey = new Map<string, ImageResource | MovieClipResource>();
|
|
608
|
-
for (const resource of resources) {
|
|
609
|
-
if (!isHighResolutionResource(resource)) continue;
|
|
610
|
-
highResolutionResourceByKey.set(buildHighResolutionResourceKey(resource), resource);
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
for (const resource of resources) {
|
|
614
|
-
if (!isHighResolutionResource(resource)) continue;
|
|
615
|
-
if (!publishedResourceIds.has(resource.getId())) continue;
|
|
616
|
-
if (isHighResolutionVariantName(resource.getName())) continue;
|
|
617
|
-
|
|
618
|
-
const ids: Array<string | null> = [];
|
|
619
|
-
for (const level of HIGH_RESOLUTION_LEVELS) {
|
|
620
|
-
if ((includeHighResolution & level.bit) === 0) {
|
|
621
|
-
ids[level.slot] = null;
|
|
622
|
-
continue;
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
const highResolutionResource = highResolutionResourceByKey.get(
|
|
626
|
-
buildHighResolutionResourceKey(
|
|
627
|
-
resource,
|
|
628
|
-
appendHighResolutionScaleToName(resource.getName(), level.scale),
|
|
629
|
-
),
|
|
630
|
-
);
|
|
631
|
-
if (!highResolutionResource) {
|
|
632
|
-
ids[level.slot] = null;
|
|
633
|
-
continue;
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
const highResolutionId = highResolutionResource.getId();
|
|
637
|
-
publishedResourceIds.add(highResolutionId);
|
|
638
|
-
ids[level.slot] = highResolutionId;
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
trimTrailingMissingHighResolutionIds(ids);
|
|
642
|
-
if (ids.length > 0) result.set(resource.getId(), ids);
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
return result;
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
function collectPackagePublishContext(
|
|
649
|
-
pkg: Package,
|
|
650
|
-
options: {
|
|
651
|
-
projectType: number;
|
|
652
|
-
includeBranches: boolean;
|
|
653
|
-
activeBranch: string;
|
|
654
|
-
includeHighResolution: number;
|
|
655
|
-
},
|
|
656
|
-
): PackagePublishContext {
|
|
657
|
-
const pkgId = pkg.getId();
|
|
658
|
-
const resources = pkg.listResources();
|
|
659
|
-
const resourceMap = new Map(resources.map((resource) => [resource.getId(), resource]));
|
|
660
|
-
const referencedIds = new Set<string>();
|
|
661
|
-
const pixelHitTestImageIds = new Set<string>();
|
|
662
|
-
const spriteItemIds = new Set<string>();
|
|
663
|
-
const collectExportedResourceIds = (
|
|
664
|
-
sourceResources: ReturnType<Package['listResources']>,
|
|
665
|
-
sourcePublishedResourceIds: Set<string>,
|
|
666
|
-
): Set<string> => {
|
|
667
|
-
const exportedResourceIds = new Set<string>(sourcePublishedResourceIds);
|
|
668
|
-
const resourcesById = new Map(sourceResources.map((resource) => [resource.getId(), resource] as const));
|
|
669
|
-
let changed = true;
|
|
670
|
-
while (changed) {
|
|
671
|
-
changed = false;
|
|
672
|
-
for (const resourceId of [...exportedResourceIds]) {
|
|
673
|
-
const resource = resourcesById.get(resourceId);
|
|
674
|
-
if (!resource || !isSkeletonResource(resource)) continue;
|
|
675
|
-
for (const requiredId of resource.getRequireIds()) {
|
|
676
|
-
if (!requiredId || exportedResourceIds.has(requiredId)) continue;
|
|
677
|
-
exportedResourceIds.add(requiredId);
|
|
678
|
-
changed = true;
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
return exportedResourceIds;
|
|
683
|
-
};
|
|
684
|
-
|
|
685
|
-
for (const atlas of pkg.listAtlases()) {
|
|
686
|
-
for (const sprite of atlas.listSprites()) {
|
|
687
|
-
spriteItemIds.add(sprite.getItemId());
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
for (const resource of resources) {
|
|
692
|
-
if (!isComponentResource(resource)) continue;
|
|
693
|
-
const component = resource as ComponentWithPublishRefs;
|
|
694
|
-
const children = component.listChildren();
|
|
695
|
-
const childMap = new Map(children.map((child) => [child.getId?.() ?? '', child]));
|
|
696
|
-
|
|
697
|
-
const hitTest = component.getHitTest?.()?.trim();
|
|
698
|
-
if (hitTest && !hitTest.includes(',')) {
|
|
699
|
-
const targetChild = childMap.get(hitTest);
|
|
700
|
-
const sourceId = targetChild?.getSrc?.();
|
|
701
|
-
if (sourceId) {
|
|
702
|
-
const sourceResource = resourceMap.get(sourceId);
|
|
703
|
-
if (sourceResource && isImageResource(sourceResource)) {
|
|
704
|
-
pixelHitTestImageIds.add(sourceId);
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
for (const child of children) {
|
|
710
|
-
const src = child.getSrc?.();
|
|
711
|
-
if (src) referencedIds.add(src);
|
|
712
|
-
addLocalFontRef(referencedIds, pkgId, child.getFont?.());
|
|
713
|
-
addLocalUiResourceRefsFromText(referencedIds, pkgId, child.getText?.());
|
|
714
|
-
for (const ref of [
|
|
715
|
-
child.getUrl?.(),
|
|
716
|
-
child.getDefaultItem?.(),
|
|
717
|
-
child.getIcon?.(),
|
|
718
|
-
child.getSelectedIcon?.(),
|
|
719
|
-
child.getDropdown?.(),
|
|
720
|
-
child.getSound?.(),
|
|
721
|
-
child.getInstanceSound?.(),
|
|
722
|
-
child.getInstanceIcon?.(),
|
|
723
|
-
child.getInstanceSelectedIcon?.(),
|
|
724
|
-
child.getVtScrollBarRes?.(),
|
|
725
|
-
child.getHzScrollBarRes?.(),
|
|
726
|
-
child.getHeaderRes?.(),
|
|
727
|
-
child.getFooterRes?.(),
|
|
728
|
-
]) {
|
|
729
|
-
addLocalUiResourceRef(referencedIds, pkgId, ref);
|
|
730
|
-
}
|
|
731
|
-
for (const item of child.getInstanceComboItems?.() ?? []) {
|
|
732
|
-
addLocalUiResourceRef(referencedIds, pkgId, item.icon ?? undefined);
|
|
733
|
-
}
|
|
734
|
-
for (const item of child.getListItems?.() ?? []) {
|
|
735
|
-
addLocalUiResourceRef(referencedIds, pkgId, item.icon ?? undefined);
|
|
736
|
-
addLocalUiResourceRef(referencedIds, pkgId, item.url ?? undefined);
|
|
737
|
-
}
|
|
738
|
-
for (const gear of child.listGears?.() ?? []) {
|
|
739
|
-
addLocalUiResourceRefsFromUnknown(referencedIds, pkgId, gear.getValues?.());
|
|
740
|
-
addLocalUiResourceRefsFromUnknown(referencedIds, pkgId, gear.getDefaultValue?.());
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
addLocalFontRef(referencedIds, pkgId, component.getFont?.());
|
|
745
|
-
for (const ref of [
|
|
746
|
-
component.getDropdown?.(),
|
|
747
|
-
component.getHeaderRes?.(),
|
|
748
|
-
component.getFooterRes?.(),
|
|
749
|
-
component.getVtScrollBarRes?.(),
|
|
750
|
-
component.getHzScrollBarRes?.(),
|
|
751
|
-
component.getSound?.(),
|
|
752
|
-
]) {
|
|
753
|
-
addLocalUiResourceRef(referencedIds, pkgId, ref);
|
|
754
|
-
}
|
|
755
|
-
for (const transition of component.listTransitions?.() ?? []) {
|
|
756
|
-
for (const item of transition.listItems?.() ?? []) {
|
|
757
|
-
addLocalUiResourceRefsFromUnknown(referencedIds, pkgId, item.getStartValue?.());
|
|
758
|
-
addLocalUiResourceRefsFromUnknown(referencedIds, pkgId, item.getEndValue?.());
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
const publishedResourceIds = new Set<string>(spriteItemIds);
|
|
764
|
-
for (const resource of resources) {
|
|
765
|
-
const resourceId = resource.getId();
|
|
766
|
-
if (!resourceId) continue;
|
|
767
|
-
if (isComponentResource(resource)) {
|
|
768
|
-
if (resource.getExported() || referencedIds.has(resourceId)) {
|
|
769
|
-
publishedResourceIds.add(resourceId);
|
|
770
|
-
}
|
|
771
|
-
continue;
|
|
772
|
-
}
|
|
773
|
-
if (isImageResource(resource)) {
|
|
774
|
-
if (
|
|
775
|
-
resource.getExported() ||
|
|
776
|
-
referencedIds.has(resourceId) ||
|
|
777
|
-
spriteItemIds.has(resourceId) ||
|
|
778
|
-
pixelHitTestImageIds.has(resourceId)
|
|
779
|
-
) {
|
|
780
|
-
publishedResourceIds.add(resourceId);
|
|
781
|
-
}
|
|
782
|
-
continue;
|
|
783
|
-
}
|
|
784
|
-
if (isMovieClipResource(resource) || isSoundResource(resource)) {
|
|
785
|
-
if (resource.getExported() || referencedIds.has(resourceId)) publishedResourceIds.add(resourceId);
|
|
786
|
-
continue;
|
|
787
|
-
}
|
|
788
|
-
if (isMiscResource(resource) || isSkeletonResource(resource)) {
|
|
789
|
-
if (resource.getExported() || referencedIds.has(resourceId)) publishedResourceIds.add(resourceId);
|
|
790
|
-
continue;
|
|
791
|
-
}
|
|
792
|
-
if (isFontResource(resource)) {
|
|
793
|
-
if (resource.getExported() || referencedIds.has(resourceId)) {
|
|
794
|
-
publishedResourceIds.add(resourceId);
|
|
795
|
-
}
|
|
796
|
-
continue;
|
|
797
|
-
}
|
|
798
|
-
const genericResource = resource as ReturnType<Package['listResources']>[number];
|
|
799
|
-
if (genericResource.getExported() || referencedIds.has(resourceId)) {
|
|
800
|
-
publishedResourceIds.add(resourceId);
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
for (const resourceId of collectExportedResourceIds(resources, publishedResourceIds)) {
|
|
805
|
-
publishedResourceIds.add(resourceId);
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
const highResolutionItemIds = collectHighResolutionItemIds(
|
|
809
|
-
resources,
|
|
810
|
-
publishedResourceIds,
|
|
811
|
-
options.includeHighResolution,
|
|
812
|
-
);
|
|
813
|
-
|
|
814
|
-
if (!options.includeBranches) {
|
|
815
|
-
const mainByKey = new Map<string, ReturnType<Package['listResources']>[number]>();
|
|
816
|
-
const activeBranchByKey = new Map<string, ReturnType<Package['listResources']>[number]>();
|
|
817
|
-
for (const resource of resources) {
|
|
818
|
-
const branchName = getBranchName(resource);
|
|
819
|
-
const key = buildBranchResourceKey(resource);
|
|
820
|
-
if (!branchName) {
|
|
821
|
-
mainByKey.set(key, resource);
|
|
822
|
-
} else if (branchName === options.activeBranch) {
|
|
823
|
-
activeBranchByKey.set(key, resource);
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
const mergedPublishedResourceIds = new Set<string>();
|
|
828
|
-
const effectiveResourceIds = new Map<string, string>();
|
|
829
|
-
for (const resource of resources) {
|
|
830
|
-
const resourceId = resource.getId();
|
|
831
|
-
if (!publishedResourceIds.has(resourceId)) continue;
|
|
832
|
-
|
|
833
|
-
const branchName = getBranchName(resource);
|
|
834
|
-
const key = buildBranchResourceKey(resource);
|
|
835
|
-
if (branchName) {
|
|
836
|
-
if (branchName !== options.activeBranch) continue;
|
|
837
|
-
const mainResource = mainByKey.get(key);
|
|
838
|
-
mergedPublishedResourceIds.add(resourceId);
|
|
839
|
-
effectiveResourceIds.set(resourceId, mainResource?.getId() ?? resourceId);
|
|
840
|
-
continue;
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
const override = activeBranchByKey.get(key);
|
|
844
|
-
if (override) {
|
|
845
|
-
mergedPublishedResourceIds.add(override.getId());
|
|
846
|
-
effectiveResourceIds.set(override.getId(), resourceId);
|
|
847
|
-
continue;
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
mergedPublishedResourceIds.add(resourceId);
|
|
851
|
-
effectiveResourceIds.set(resourceId, resourceId);
|
|
852
|
-
}
|
|
853
|
-
|
|
854
|
-
publishedResourceIds.clear();
|
|
855
|
-
for (const resourceId of mergedPublishedResourceIds) {
|
|
856
|
-
publishedResourceIds.add(resourceId);
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
const mergedPixelHitTestImageIds = new Set<string>();
|
|
860
|
-
for (const resource of resources) {
|
|
861
|
-
if (!isImageResource(resource)) continue;
|
|
862
|
-
const resourceId = resource.getId();
|
|
863
|
-
if (!publishedResourceIds.has(resourceId)) continue;
|
|
864
|
-
const effectiveId = effectiveResourceIds.get(resourceId) ?? resourceId;
|
|
865
|
-
if (pixelHitTestImageIds.has(effectiveId)) {
|
|
866
|
-
mergedPixelHitTestImageIds.add(resourceId);
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
pixelHitTestImageIds.clear();
|
|
870
|
-
for (const resourceId of mergedPixelHitTestImageIds) {
|
|
871
|
-
pixelHitTestImageIds.add(resourceId);
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
return {
|
|
875
|
-
referencedIds,
|
|
876
|
-
publishedResourceIds,
|
|
877
|
-
exportedResourceIds: collectExportedResourceIds(resources, publishedResourceIds),
|
|
878
|
-
pixelHitTestImageIds,
|
|
879
|
-
highResolutionItemIds,
|
|
880
|
-
effectiveResourceIds,
|
|
881
|
-
includeBranches: false,
|
|
882
|
-
};
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
return {
|
|
886
|
-
referencedIds,
|
|
887
|
-
publishedResourceIds,
|
|
888
|
-
exportedResourceIds: collectExportedResourceIds(resources, publishedResourceIds),
|
|
889
|
-
pixelHitTestImageIds,
|
|
890
|
-
highResolutionItemIds,
|
|
891
|
-
effectiveResourceIds: new Map([...publishedResourceIds].map((resourceId) => [resourceId, resourceId])),
|
|
892
|
-
includeBranches: true,
|
|
893
|
-
};
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
async function applyPixelHitTests(
|
|
897
|
-
pkg: Package,
|
|
898
|
-
imageIds: Set<string>,
|
|
899
|
-
basePath: string | undefined,
|
|
900
|
-
encoder: AtlasRasterBackend | undefined,
|
|
901
|
-
): Promise<void> {
|
|
902
|
-
const images = pkg.listImageResources();
|
|
903
|
-
for (const image of images) {
|
|
904
|
-
image.setPixelHitTestData(null);
|
|
905
|
-
}
|
|
906
|
-
if (!basePath || !encoder || imageIds.size === 0) return;
|
|
907
|
-
|
|
908
|
-
for (const image of images) {
|
|
909
|
-
const imageId = image.getId();
|
|
910
|
-
if (!imageIds.has(imageId)) continue;
|
|
911
|
-
try {
|
|
912
|
-
const sourcePath = resolveImagePath(image, pkg, basePath);
|
|
913
|
-
const metadata = await encoder(sourcePath).metadata();
|
|
914
|
-
if (!metadata.width || !metadata.height) continue;
|
|
915
|
-
|
|
916
|
-
const resizedWidth = Math.max(1, Math.floor(metadata.width / 2));
|
|
917
|
-
const resizedHeight = Math.max(1, Math.floor(metadata.height / 2));
|
|
918
|
-
const { data, info } = await encoder(sourcePath)
|
|
919
|
-
.ensureAlpha()
|
|
920
|
-
.resize({
|
|
921
|
-
width: resizedWidth,
|
|
922
|
-
height: resizedHeight,
|
|
923
|
-
fit: 'fill',
|
|
924
|
-
})
|
|
925
|
-
.raw()
|
|
926
|
-
.toBuffer({ resolveWithObject: true });
|
|
927
|
-
|
|
928
|
-
const pixelCount = info.width * info.height;
|
|
929
|
-
const maskBytes = new Uint8Array(Math.ceil(pixelCount / 8));
|
|
930
|
-
let byteValue = 0;
|
|
931
|
-
let bitIndex = 0;
|
|
932
|
-
let maskIndex = 0;
|
|
933
|
-
|
|
934
|
-
for (let pixel = 0; pixel < pixelCount; pixel++) {
|
|
935
|
-
const alpha = data[pixel * info.channels + 3];
|
|
936
|
-
if (alpha > 10) byteValue |= 1 << bitIndex;
|
|
937
|
-
bitIndex++;
|
|
938
|
-
if (bitIndex === 8) {
|
|
939
|
-
maskBytes[maskIndex++] = byteValue;
|
|
940
|
-
bitIndex = 0;
|
|
941
|
-
byteValue = 0;
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
if (bitIndex !== 0) {
|
|
945
|
-
maskBytes[maskIndex] = byteValue;
|
|
946
|
-
}
|
|
947
|
-
|
|
948
|
-
image.setPixelHitTestData({
|
|
949
|
-
pixelWidth: info.width,
|
|
950
|
-
scaleDenominator: 2,
|
|
951
|
-
pixels: maskBytes,
|
|
952
|
-
});
|
|
953
|
-
} catch {
|
|
954
|
-
image.setPixelHitTestData(null);
|
|
955
|
-
}
|
|
956
|
-
}
|
|
957
|
-
}
|
|
958
|
-
|
|
959
|
-
async function annotatePackagePublishArtifacts(
|
|
960
|
-
pkg: Package,
|
|
961
|
-
basePath: string | undefined,
|
|
962
|
-
encoder: AtlasRasterBackend | undefined,
|
|
963
|
-
options: {
|
|
964
|
-
projectType: number;
|
|
965
|
-
includeBranches: boolean;
|
|
966
|
-
activeBranch: string;
|
|
967
|
-
includeHighResolution: number;
|
|
968
|
-
},
|
|
969
|
-
): Promise<void> {
|
|
970
|
-
const {
|
|
971
|
-
publishedResourceIds,
|
|
972
|
-
exportedResourceIds,
|
|
973
|
-
pixelHitTestImageIds,
|
|
974
|
-
highResolutionItemIds,
|
|
975
|
-
effectiveResourceIds,
|
|
976
|
-
includeBranches,
|
|
977
|
-
} = collectPackagePublishContext(pkg, options);
|
|
978
|
-
for (const resource of pkg.listResources()) {
|
|
979
|
-
setPublishedIdExtra(resource, effectiveResourceIds.get(resource.getId()) ?? null);
|
|
980
|
-
if (isHighResolutionResource(resource)) {
|
|
981
|
-
resource.setHighResolutionItemIds(highResolutionItemIds.get(resource.getId()) ?? []);
|
|
982
|
-
}
|
|
983
|
-
}
|
|
984
|
-
await applyPixelHitTests(pkg, pixelHitTestImageIds, basePath, encoder);
|
|
985
|
-
const extras = (pkg.getExtras() as PackagePublishArtifactsExtras | undefined) ?? {};
|
|
986
|
-
pkg.setExtras({
|
|
987
|
-
...extras,
|
|
988
|
-
publishedResourceIds: [...publishedResourceIds].sort((a, b) => a.localeCompare(b)),
|
|
989
|
-
exportedResourceIds: [...exportedResourceIds].sort((a, b) => a.localeCompare(b)),
|
|
990
|
-
publishedIncludeBranches: includeBranches,
|
|
991
|
-
publishedEffectiveResourceIds: Object.fromEntries(effectiveResourceIds),
|
|
992
|
-
});
|
|
993
|
-
for (const resource of pkg.listResources()) {
|
|
994
|
-
if (isMiscResource(resource)) {
|
|
995
|
-
setPublishedFileExtra(resource, resolvePublishedMiscFileName(resource, options.projectType));
|
|
996
|
-
continue;
|
|
997
|
-
}
|
|
998
|
-
if (isSkeletonResource(resource)) {
|
|
999
|
-
setPublishedFileExtra(resource, resolvePublishedSkeletonFileName(resource, options.projectType));
|
|
1000
|
-
}
|
|
1001
|
-
}
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
function getAnnotatedPublishedResourceIds(pkg: Package): Set<string> {
|
|
1005
|
-
const extras = (pkg.getExtras() as PackagePublishArtifactsExtras | undefined) ?? {};
|
|
1006
|
-
return new Set(extras.publishedResourceIds ?? []);
|
|
1007
|
-
}
|
|
1008
|
-
|
|
1009
|
-
function getAnnotatedExportedResourceIds(pkg: Package): Set<string> {
|
|
1010
|
-
const extras = (pkg.getExtras() as PackagePublishArtifactsExtras | undefined) ?? {};
|
|
1011
|
-
return new Set(extras.exportedResourceIds ?? []);
|
|
1012
|
-
}
|
|
1013
|
-
|
|
1014
|
-
function getPublishedSkeletonDependencyImageIds(pkg: Package, publishedResourceIds: Set<string>): Set<string> {
|
|
1015
|
-
const imageIds = new Set<string>();
|
|
1016
|
-
const resourcesById = new Map(pkg.listResources().map((resource) => [resource.getId(), resource] as const));
|
|
1017
|
-
for (const resource of pkg.listResources()) {
|
|
1018
|
-
if (!isSkeletonResource(resource)) continue;
|
|
1019
|
-
if (!publishedResourceIds.has(resource.getId())) continue;
|
|
1020
|
-
for (const requiredId of resource.getRequireIds()) {
|
|
1021
|
-
if (!requiredId) continue;
|
|
1022
|
-
const required = resourcesById.get(requiredId);
|
|
1023
|
-
if (required && isImageResource(required)) imageIds.add(requiredId);
|
|
1024
|
-
}
|
|
1025
|
-
}
|
|
1026
|
-
return imageIds;
|
|
1027
|
-
}
|
|
1028
|
-
|
|
1029
|
-
async function exportPackageSounds(
|
|
1030
|
-
pkg: Package,
|
|
1031
|
-
outputDir: string,
|
|
1032
|
-
basePath: string | undefined,
|
|
1033
|
-
fs: PublishFileSystem,
|
|
1034
|
-
readFileRaw: PublishFileSystem['readFileRaw'] | undefined,
|
|
1035
|
-
): Promise<void> {
|
|
1036
|
-
const publishedResourceIds = getAnnotatedPublishedResourceIds(pkg);
|
|
1037
|
-
if (publishedResourceIds.size === 0) return;
|
|
1038
|
-
if (!basePath || !readFileRaw) {
|
|
1039
|
-
const hasPublishedSound = pkg.listResources().some((resource) => {
|
|
1040
|
-
return isSoundResource(resource) && publishedResourceIds.has(resource.getId());
|
|
1041
|
-
});
|
|
1042
|
-
if (hasPublishedSound) {
|
|
1043
|
-
throw new Error(
|
|
1044
|
-
`publish: Sound resources in package "${pkg.getName()}" require basePath and readFileRaw for output.`,
|
|
1045
|
-
);
|
|
1046
|
-
}
|
|
1047
|
-
return;
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
|
-
for (const resource of pkg.listResources()) {
|
|
1051
|
-
if (!isSoundResource(resource)) continue;
|
|
1052
|
-
if (!publishedResourceIds.has(resource.getId())) continue;
|
|
1053
|
-
|
|
1054
|
-
const sourcePath = resolveSoundPath(resource, pkg, basePath);
|
|
1055
|
-
const targetName = `${pkg.getPublishName() || pkg.getName()}_${getPublishedId(resource)}${extname(resource.getFile() || '')}`;
|
|
1056
|
-
const targetPath = fs.join(outputDir, targetName);
|
|
1057
|
-
|
|
1058
|
-
try {
|
|
1059
|
-
const data = await readFileRaw(sourcePath);
|
|
1060
|
-
await fs.writeFileRaw(targetPath, data);
|
|
1061
|
-
} catch {
|
|
1062
|
-
throw new Error(`publish: Could not export sound "${resource.getId()}" from package "${pkg.getName()}".`);
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
|
|
1067
|
-
async function exportPackageExternalResources(
|
|
1068
|
-
pkg: Package,
|
|
1069
|
-
outputDir: string,
|
|
1070
|
-
basePath: string | undefined,
|
|
1071
|
-
fs: PublishFileSystem,
|
|
1072
|
-
readFileRaw: PublishFileSystem['readFileRaw'] | undefined,
|
|
1073
|
-
): Promise<void> {
|
|
1074
|
-
const exportedResourceIds = getAnnotatedExportedResourceIds(pkg);
|
|
1075
|
-
const skeletonDependencyImageIds = getPublishedSkeletonDependencyImageIds(pkg, exportedResourceIds);
|
|
1076
|
-
if (exportedResourceIds.size === 0) return;
|
|
1077
|
-
if (!basePath || !readFileRaw) {
|
|
1078
|
-
const hasPublishedExternal = pkg.listResources().some((resource) => {
|
|
1079
|
-
return (
|
|
1080
|
-
((isMiscResource(resource) || isSkeletonResource(resource)) &&
|
|
1081
|
-
exportedResourceIds.has(resource.getId())) ||
|
|
1082
|
-
skeletonDependencyImageIds.has(resource.getId())
|
|
1083
|
-
);
|
|
1084
|
-
});
|
|
1085
|
-
if (hasPublishedExternal) {
|
|
1086
|
-
throw new Error(
|
|
1087
|
-
`publish: External resources in package "${pkg.getName()}" require basePath and readFileRaw for output.`,
|
|
1088
|
-
);
|
|
1089
|
-
}
|
|
1090
|
-
return;
|
|
1091
|
-
}
|
|
1092
|
-
|
|
1093
|
-
for (const resource of pkg.listResources()) {
|
|
1094
|
-
const resourceId = resource.getId();
|
|
1095
|
-
const isSkeletonExternal =
|
|
1096
|
-
exportedResourceIds.has(resourceId) && (isMiscResource(resource) || isSkeletonResource(resource));
|
|
1097
|
-
const isSkeletonImageDependency = skeletonDependencyImageIds.has(resourceId) && isImageResource(resource);
|
|
1098
|
-
if (!isSkeletonExternal && !isSkeletonImageDependency) continue;
|
|
1099
|
-
|
|
1100
|
-
let sourcePath: string;
|
|
1101
|
-
let targetName: string;
|
|
1102
|
-
if (isSkeletonImageDependency) {
|
|
1103
|
-
sourcePath = resolveImagePath(resource, pkg, basePath);
|
|
1104
|
-
targetName = resolveImageFileName(resource);
|
|
1105
|
-
} else if (isMiscResource(resource) || isSkeletonResource(resource)) {
|
|
1106
|
-
sourcePath = resolveGenericResourcePath(resource, pkg, basePath);
|
|
1107
|
-
targetName =
|
|
1108
|
-
((resource.getExtras() as PublishFileExtras | undefined) ?? {})._publishedFile ?? resource.getFile();
|
|
1109
|
-
} else {
|
|
1110
|
-
continue;
|
|
1111
|
-
}
|
|
1112
|
-
const targetPath = fs.join(outputDir, targetName);
|
|
1113
|
-
|
|
1114
|
-
try {
|
|
1115
|
-
const data = await readFileRaw(sourcePath);
|
|
1116
|
-
await fs.writeFileRaw(targetPath, data);
|
|
1117
|
-
} catch {
|
|
1118
|
-
throw new Error(
|
|
1119
|
-
`publish: Could not export external resource "${resource.getId()}" from package "${pkg.getName()}".`,
|
|
1120
|
-
);
|
|
1121
|
-
}
|
|
1122
|
-
}
|
|
1123
|
-
}
|
|
1124
|
-
|
|
1125
119
|
/**
|
|
1126
120
|
* Publishes a FairyGUI project.
|
|
1127
121
|
*
|
|
@@ -1393,116 +387,13 @@ export function publish(options: PublishOptions): Transform {
|
|
|
1393
387
|
* @internal
|
|
1394
388
|
*/
|
|
1395
389
|
function _computeDependencies(doc: Document, pkg: Package, pkgMap: Map<string, Package>): void {
|
|
1396
|
-
const referencedPkgIds =
|
|
1397
|
-
const pkgId = pkg.getId();
|
|
390
|
+
const referencedPkgIds = collectPackageResourceReferences(pkg).packageIds;
|
|
1398
391
|
const packageOrder = new Map(
|
|
1399
392
|
doc
|
|
1400
393
|
.getRoot()
|
|
1401
394
|
.listPackages()
|
|
1402
395
|
.map((entry, index) => [entry.getId(), index] as const),
|
|
1403
396
|
);
|
|
1404
|
-
const addDependencyPackageId = (dependencyPkgId: string | null | undefined): void => {
|
|
1405
|
-
const normalized = dependencyPkgId?.trim() ?? '';
|
|
1406
|
-
if (!normalized || normalized === pkgId) return;
|
|
1407
|
-
referencedPkgIds.add(normalized);
|
|
1408
|
-
};
|
|
1409
|
-
const extractPackageIdFromUiUrl = (value: string): string | null => {
|
|
1410
|
-
if (!value.startsWith('ui://')) return null;
|
|
1411
|
-
const rest = value.slice(5);
|
|
1412
|
-
if (!rest) return null;
|
|
1413
|
-
const slashIndex = rest.indexOf('/');
|
|
1414
|
-
if (slashIndex >= 0) {
|
|
1415
|
-
return rest.slice(0, slashIndex) || null;
|
|
1416
|
-
}
|
|
1417
|
-
if (rest.length >= 8) {
|
|
1418
|
-
return rest.slice(0, 8);
|
|
1419
|
-
}
|
|
1420
|
-
return null;
|
|
1421
|
-
};
|
|
1422
|
-
const addDependencyPackageIdFromUiValue = (value: string | null | undefined): void => {
|
|
1423
|
-
if (!value || typeof value !== 'string') return;
|
|
1424
|
-
addDependencyPackageId(extractPackageIdFromUiUrl(value));
|
|
1425
|
-
};
|
|
1426
|
-
const addDependencyPackageIdsFromText = (value: string | null | undefined): void => {
|
|
1427
|
-
if (!value || typeof value !== 'string') return;
|
|
1428
|
-
const matches = value.matchAll(/ui:\/\/([0-9a-z]{8})/giu);
|
|
1429
|
-
for (const match of matches) {
|
|
1430
|
-
addDependencyPackageId(match[1] ?? '');
|
|
1431
|
-
}
|
|
1432
|
-
};
|
|
1433
|
-
const addDependencyPackageIdsFromUnknown = (value: unknown): void => {
|
|
1434
|
-
if (Array.isArray(value)) {
|
|
1435
|
-
for (const entry of value) addDependencyPackageIdsFromUnknown(entry);
|
|
1436
|
-
return;
|
|
1437
|
-
}
|
|
1438
|
-
if (typeof value === 'string') {
|
|
1439
|
-
addDependencyPackageIdFromUiValue(value);
|
|
1440
|
-
addDependencyPackageIdsFromText(value);
|
|
1441
|
-
}
|
|
1442
|
-
};
|
|
1443
|
-
const addDependencyFontRef = (value: string | string[] | null | undefined): void => {
|
|
1444
|
-
if (Array.isArray(value)) {
|
|
1445
|
-
for (const entry of value) addDependencyPackageIdFromUiValue(entry);
|
|
1446
|
-
return;
|
|
1447
|
-
}
|
|
1448
|
-
addDependencyPackageIdFromUiValue(value ?? undefined);
|
|
1449
|
-
};
|
|
1450
|
-
|
|
1451
|
-
for (const res of pkg.listResources()) {
|
|
1452
|
-
if (res.propertyType !== 'Component') continue;
|
|
1453
|
-
const component = res as ComponentWithPublishRefs;
|
|
1454
|
-
for (const child of component.listChildren?.() ?? []) {
|
|
1455
|
-
addDependencyPackageId(child.getPackageId?.());
|
|
1456
|
-
addDependencyFontRef(child.getFont?.());
|
|
1457
|
-
addDependencyPackageIdsFromText(child.getText?.());
|
|
1458
|
-
for (const ref of [
|
|
1459
|
-
child.getUrl?.(),
|
|
1460
|
-
child.getDefaultItem?.(),
|
|
1461
|
-
child.getIcon?.(),
|
|
1462
|
-
child.getSelectedIcon?.(),
|
|
1463
|
-
child.getDropdown?.(),
|
|
1464
|
-
child.getSound?.(),
|
|
1465
|
-
child.getInstanceSound?.(),
|
|
1466
|
-
child.getInstanceIcon?.(),
|
|
1467
|
-
child.getInstanceSelectedIcon?.(),
|
|
1468
|
-
child.getVtScrollBarRes?.(),
|
|
1469
|
-
child.getHzScrollBarRes?.(),
|
|
1470
|
-
child.getHeaderRes?.(),
|
|
1471
|
-
child.getFooterRes?.(),
|
|
1472
|
-
]) {
|
|
1473
|
-
addDependencyPackageIdFromUiValue(ref);
|
|
1474
|
-
}
|
|
1475
|
-
for (const item of child.getInstanceComboItems?.() ?? []) {
|
|
1476
|
-
addDependencyPackageIdFromUiValue(item.icon ?? undefined);
|
|
1477
|
-
}
|
|
1478
|
-
for (const item of child.getListItems?.() ?? []) {
|
|
1479
|
-
addDependencyPackageIdFromUiValue(item.icon ?? undefined);
|
|
1480
|
-
addDependencyPackageIdFromUiValue(item.url ?? undefined);
|
|
1481
|
-
}
|
|
1482
|
-
for (const gear of child.listGears?.() ?? []) {
|
|
1483
|
-
addDependencyPackageIdsFromUnknown(gear.getValues?.());
|
|
1484
|
-
addDependencyPackageIdsFromUnknown(gear.getDefaultValue?.());
|
|
1485
|
-
}
|
|
1486
|
-
}
|
|
1487
|
-
addDependencyFontRef(component.getFont?.());
|
|
1488
|
-
for (const ref of [
|
|
1489
|
-
component.getDropdown?.(),
|
|
1490
|
-
component.getHeaderRes?.(),
|
|
1491
|
-
component.getFooterRes?.(),
|
|
1492
|
-
component.getVtScrollBarRes?.(),
|
|
1493
|
-
component.getHzScrollBarRes?.(),
|
|
1494
|
-
component.getSound?.(),
|
|
1495
|
-
]) {
|
|
1496
|
-
addDependencyPackageIdFromUiValue(ref);
|
|
1497
|
-
}
|
|
1498
|
-
for (const transition of component.listTransitions?.() ?? []) {
|
|
1499
|
-
for (const item of transition.listItems?.() ?? []) {
|
|
1500
|
-
addDependencyPackageIdsFromUnknown(item.getStartValue?.());
|
|
1501
|
-
addDependencyPackageIdsFromUnknown(item.getEndValue?.());
|
|
1502
|
-
}
|
|
1503
|
-
}
|
|
1504
|
-
}
|
|
1505
|
-
|
|
1506
397
|
for (const dep of pkg.listDependencies()) {
|
|
1507
398
|
pkg.removeDependency(dep);
|
|
1508
399
|
}
|