@openfairygui/functions 0.2.4 → 0.2.6

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.
@@ -7,7 +7,7 @@ function createTransform(name, fn) {
7
7
  Object.defineProperty(fn, "name", { value: name });
8
8
  return fn;
9
9
  }
10
- function parseTextureSetMode(value) {
10
+ function parseTextureSetMode(value, maxAtlasIndex = 10) {
11
11
  const raw = value?.trim() ?? "";
12
12
  if (!raw) return {
13
13
  kind: "auto",
@@ -30,7 +30,7 @@ function parseTextureSetMode(value) {
30
30
  };
31
31
  if (/^\d+$/.test(raw)) {
32
32
  const pageIndex = Number(raw);
33
- if (pageIndex >= 0 && pageIndex <= 10) return {
33
+ if (pageIndex >= 0 && pageIndex <= maxAtlasIndex) return {
34
34
  kind: "page",
35
35
  raw,
36
36
  pageIndex
@@ -88,9 +88,9 @@ function collectComponentReferences(target, ownerPackageId, component) {
88
88
  const sourcePackageId = child.getPackageId?.()?.trim();
89
89
  if (sourcePackageId && sourcePackageId !== ownerPackageId) target.packageIds.add(sourcePackageId);
90
90
  addFontReferences(target, ownerPackageId, child.getFont?.());
91
- addTextReferences(target, ownerPackageId, child.getText?.());
91
+ if (!child.getAutoClearText?.()) addTextReferences(target, ownerPackageId, child.getText?.());
92
92
  for (const reference of [
93
- child.getUrl?.(),
93
+ child.getClearOnPublish?.() ? void 0 : child.getUrl?.(),
94
94
  child.getDefaultItem?.(),
95
95
  child.getIcon?.(),
96
96
  child.getSelectedIcon?.(),
@@ -104,11 +104,14 @@ function collectComponentReferences(target, ownerPackageId, component) {
104
104
  child.getHeaderRes?.(),
105
105
  child.getFooterRes?.()
106
106
  ]) addUiReference(target, ownerPackageId, reference);
107
- for (const item of child.getInstanceComboItems?.() ?? []) addUiReference(target, ownerPackageId, item.icon);
108
- for (const item of child.getListItems?.() ?? []) {
107
+ for (const item of child.getInstanceAutoClearItems?.() ? [] : child.getInstanceComboItems?.() ?? []) addUiReference(target, ownerPackageId, item.icon);
108
+ for (const item of child.getAutoClearItems?.() ? [] : child.getListItems?.() ?? []) {
109
109
  addUiReference(target, ownerPackageId, item.icon);
110
+ addUiReference(target, ownerPackageId, item.selectedIcon);
110
111
  addUiReference(target, ownerPackageId, item.url);
112
+ addUnknownReferences(target, ownerPackageId, item.propertyOverrides?.map((property) => property.value));
111
113
  }
114
+ addUnknownReferences(target, ownerPackageId, child.getPropertyOverrides?.().map((property) => property.value));
112
115
  for (const gear of child.listGears?.() ?? []) {
113
116
  addUnknownReferences(target, ownerPackageId, gear.getValues?.());
114
117
  addUnknownReferences(target, ownerPackageId, gear.getDefaultValue?.());
@@ -138,7 +141,8 @@ function collectPackageResourceReferences(pkg) {
138
141
  localResourceIds: /* @__PURE__ */ new Set(),
139
142
  packageIds: /* @__PURE__ */ new Set()
140
143
  };
141
- for (const resource of pkg.listResources()) if (resource.propertyType === "Component") collectComponentReferences(references, pkg.getId(), resource);
144
+ const excludedResourceIds = new Set(pkg.getSourceAtlasSettings().excludedResourceIds);
145
+ for (const resource of pkg.listResources()) if (resource.propertyType === "Component" && !excludedResourceIds.has(resource.getId())) collectComponentReferences(references, pkg.getId(), resource);
142
146
  return references;
143
147
  }
144
148
  //#endregion
@@ -165,6 +169,9 @@ function isFontResource(resource) {
165
169
  function isSoundResource(resource) {
166
170
  return resource.propertyType === "SoundResource";
167
171
  }
172
+ function isSwfResource(resource) {
173
+ return resource.propertyType === "SwfResource";
174
+ }
168
175
  function isSpineResource(resource) {
169
176
  return resource.propertyType === "SpineResource";
170
177
  }
@@ -206,10 +213,12 @@ function extname(fileName) {
206
213
  return normalized.slice(lastDot);
207
214
  }
208
215
  function resolvePublishedMiscFileName(resource, projectType) {
209
- const file = resource.getFile();
210
- if (projectType !== UNITY_PROJECT_TYPE$1) return file;
211
- if (file.toLowerCase().endsWith(".atlas")) return `${file}.txt`;
212
- return file;
216
+ const fileName = `${getPublishedId(resource)}${extname(resource.getFile())}`;
217
+ if (projectType === UNITY_PROJECT_TYPE$1 && fileName.toLowerCase().endsWith(".atlas")) return `${fileName}.txt`;
218
+ return fileName;
219
+ }
220
+ function resolvePublishedSwfFileName(resource) {
221
+ return `${getPublishedId(resource)}${extname(resource.getFile()) || ".swf"}`;
213
222
  }
214
223
  function resolvePublishedSkeletonFileName(resource, projectType) {
215
224
  if (projectType === UNITY_PROJECT_TYPE$1 && isSpineResource(resource) && resource.getFile().toLowerCase().endsWith(".skel")) return `${resource.getFile()}.bytes`;
@@ -276,16 +285,16 @@ function trimTrailingMissingHighResolutionIds(ids) {
276
285
  while (ids.length > 0 && !ids[ids.length - 1]) ids.pop();
277
286
  return ids;
278
287
  }
279
- function collectHighResolutionItemIds(resources, publishedResourceIds, includeHighResolution) {
288
+ function collectHighResolutionItemIds(resources, publishedResourceIds, includeHighResolution, excludedResourceIds) {
280
289
  const result = /* @__PURE__ */ new Map();
281
290
  if (includeHighResolution <= 0) return result;
282
291
  const highResolutionResourceByKey = /* @__PURE__ */ new Map();
283
292
  for (const resource of resources) {
284
- if (!isHighResolutionResource(resource)) continue;
293
+ if (!isHighResolutionResource(resource) || excludedResourceIds.has(resource.getId())) continue;
285
294
  highResolutionResourceByKey.set(buildHighResolutionResourceKey(resource), resource);
286
295
  }
287
296
  for (const resource of resources) {
288
- if (!isHighResolutionResource(resource)) continue;
297
+ if (!isHighResolutionResource(resource) || excludedResourceIds.has(resource.getId())) continue;
289
298
  if (!publishedResourceIds.has(resource.getId())) continue;
290
299
  if (isHighResolutionVariantName(resource.getName())) continue;
291
300
  const ids = [];
@@ -310,6 +319,7 @@ function collectHighResolutionItemIds(resources, publishedResourceIds, includeHi
310
319
  }
311
320
  function collectPackagePublishContext(pkg, options) {
312
321
  const resources = pkg.listResources();
322
+ const excludedResourceIds = new Set(pkg.getSourceAtlasSettings().excludedResourceIds);
313
323
  const resourceMap = new Map(resources.map((resource) => [resource.getId(), resource]));
314
324
  const referencedIds = collectPackageResourceReferences(pkg).localResourceIds;
315
325
  const pixelHitTestImageIds = /* @__PURE__ */ new Set();
@@ -321,10 +331,15 @@ function collectPackagePublishContext(pkg, options) {
321
331
  while (changed) {
322
332
  changed = false;
323
333
  for (const resourceId of [...exportedResourceIds]) {
334
+ if (excludedResourceIds.has(resourceId)) {
335
+ exportedResourceIds.delete(resourceId);
336
+ changed = true;
337
+ continue;
338
+ }
324
339
  const resource = resourcesById.get(resourceId);
325
340
  if (!resource || !isSkeletonResource(resource)) continue;
326
341
  for (const requiredId of resource.getRequireIds()) {
327
- if (!requiredId || exportedResourceIds.has(requiredId)) continue;
342
+ if (!requiredId || excludedResourceIds.has(requiredId) || exportedResourceIds.has(requiredId)) continue;
328
343
  exportedResourceIds.add(requiredId);
329
344
  changed = true;
330
345
  }
@@ -332,7 +347,7 @@ function collectPackagePublishContext(pkg, options) {
332
347
  }
333
348
  return exportedResourceIds;
334
349
  };
335
- for (const atlas of pkg.listAtlases()) for (const sprite of atlas.listSprites()) spriteItemIds.add(sprite.getItemId());
350
+ for (const atlas of pkg.listAtlases()) for (const sprite of atlas.listSprites()) if (!excludedResourceIds.has(sprite.getItemId())) spriteItemIds.add(sprite.getItemId());
336
351
  for (const resource of resources) {
337
352
  if (!isComponentResource(resource)) continue;
338
353
  const component = resource;
@@ -341,7 +356,7 @@ function collectPackagePublishContext(pkg, options) {
341
356
  const hitTest = component.getHitTest?.()?.trim();
342
357
  if (hitTest && !hitTest.includes(",")) {
343
358
  const sourceId = childMap.get(hitTest)?.getSrc?.();
344
- if (sourceId) {
359
+ if (sourceId && !excludedResourceIds.has(sourceId)) {
345
360
  const sourceResource = resourceMap.get(sourceId);
346
361
  if (sourceResource && isImageResource(sourceResource)) pixelHitTestImageIds.add(sourceId);
347
362
  }
@@ -350,7 +365,7 @@ function collectPackagePublishContext(pkg, options) {
350
365
  const publishedResourceIds = new Set(spriteItemIds);
351
366
  for (const resource of resources) {
352
367
  const resourceId = resource.getId();
353
- if (!resourceId) continue;
368
+ if (!resourceId || excludedResourceIds.has(resourceId)) continue;
354
369
  if (isComponentResource(resource)) {
355
370
  if (resource.getExported() || referencedIds.has(resourceId)) publishedResourceIds.add(resourceId);
356
371
  continue;
@@ -374,7 +389,7 @@ function collectPackagePublishContext(pkg, options) {
374
389
  if (resource.getExported() || referencedIds.has(resourceId)) publishedResourceIds.add(resourceId);
375
390
  }
376
391
  for (const resourceId of collectExportedResourceIds(resources, publishedResourceIds)) publishedResourceIds.add(resourceId);
377
- const highResolutionItemIds = collectHighResolutionItemIds(resources, publishedResourceIds, options.includeHighResolution);
392
+ const highResolutionItemIds = collectHighResolutionItemIds(resources, publishedResourceIds, options.includeHighResolution, excludedResourceIds);
378
393
  if (!options.includeBranches) {
379
394
  const mainByKey = /* @__PURE__ */ new Map();
380
395
  const activeBranchByKey = /* @__PURE__ */ new Map();
@@ -502,6 +517,10 @@ async function annotatePackagePublishArtifacts(pkg, basePath, encoder, options)
502
517
  setPublishedFileExtra(resource, resolvePublishedMiscFileName(resource, options.projectType));
503
518
  continue;
504
519
  }
520
+ if (isSwfResource(resource)) {
521
+ setPublishedFileExtra(resource, resolvePublishedSwfFileName(resource));
522
+ continue;
523
+ }
505
524
  if (isSkeletonResource(resource)) setPublishedFileExtra(resource, resolvePublishedSkeletonFileName(resource, options.projectType));
506
525
  }
507
526
  }
@@ -1760,7 +1779,7 @@ function packAtlasPages(inputs, options, forceSinglePage, sizeOverrides) {
1760
1779
  });
1761
1780
  return new MaxRectsPackerCompat({
1762
1781
  pot: sizeOverrides?.powerOfTwo ?? options.powerOfTwo,
1763
- mof: sizeOverrides?.multipleOfFour ?? !options.powerOfTwo,
1782
+ mof: sizeOverrides?.multipleOfFour ?? options.multipleOfFour,
1764
1783
  padding: options.padding,
1765
1784
  rotation: options.allowRotation,
1766
1785
  minWidth: 16,
@@ -1860,7 +1879,7 @@ async function writeAtlasPageImage(pkg, inputs, page, atlasFileName, encoder, op
1860
1879
  }
1861
1880
  }
1862
1881
  const outputFile = `${options.outputPath}/${atlasFileName}`;
1863
- await encoder({ create: {
1882
+ const atlasPipeline = encoder({ create: {
1864
1883
  width: page.width,
1865
1884
  height: page.height,
1866
1885
  channels: 4,
@@ -1870,7 +1889,13 @@ async function writeAtlasPageImage(pkg, inputs, page, atlasFileName, encoder, op
1870
1889
  b: 0,
1871
1890
  alpha: 0
1872
1891
  }
1873
- } }).composite(compositeInputs).toFile(outputFile);
1892
+ } }).composite(compositeInputs);
1893
+ if (options.extractAlpha) {
1894
+ const atlasBuffer = await atlasPipeline.png().toBuffer();
1895
+ await encoder(atlasBuffer).removeAlpha().png().toFile(outputFile);
1896
+ const alphaBuffer = await encoder(atlasBuffer).extractChannel("alpha").png().toBuffer();
1897
+ await encoder(alphaBuffer).joinChannel([alphaBuffer, alphaBuffer]).png().toFile(`${options.outputPath}/${insertFileNameSuffix(atlasFileName, "!a")}`);
1898
+ } else await atlasPipeline.toFile(outputFile);
1874
1899
  logger.info(`atlas: Generated ${atlasFileName} (${page.width}x${page.height}, ${page.outputRects.length} sprites)`);
1875
1900
  }
1876
1901
  function inputToCompatRect(input, index) {
@@ -1920,6 +1945,9 @@ function resolveDirectOutputAtlasSize(width, height, options) {
1920
1945
  if (options.powerOfTwo) {
1921
1946
  resolvedWidth = nextPow2(resolvedWidth);
1922
1947
  resolvedHeight = nextPow2(resolvedHeight);
1948
+ } else if (options.multipleOfFour) {
1949
+ resolvedWidth = roundUpToMultiple(resolvedWidth, 4);
1950
+ resolvedHeight = roundUpToMultiple(resolvedHeight, 4);
1923
1951
  }
1924
1952
  return {
1925
1953
  width: resolvedWidth,
@@ -2034,9 +2062,8 @@ function sortResourcesByOrder(resources, orderMap, inputOrderMap) {
2034
2062
  });
2035
2063
  return ordered;
2036
2064
  }
2037
- function getResourceTextureSetMode(resource) {
2038
- if (isImageResource(resource)) return parseTextureSetMode(resource.getTextureSetMode?.());
2039
- return parseTextureSetMode(resource.getTextureSetMode?.());
2065
+ function getResourceTextureSetMode(resource, maxAtlasIndex) {
2066
+ return parseTextureSetMode(resource.getTextureSetMode?.(), maxAtlasIndex);
2040
2067
  }
2041
2068
  function groupStandaloneInputs(doc, inputs, options) {
2042
2069
  const autoInputs = [];
@@ -2055,7 +2082,7 @@ function groupStandaloneInputs(doc, inputs, options) {
2055
2082
  for (const input of inputs) {
2056
2083
  const branchName = getInputBranchName(input);
2057
2084
  const branchOrdinal = branchOrdinalByName.get(branchName) ?? 0;
2058
- const mode = getResourceTextureSetMode(input.resource);
2085
+ const mode = getResourceTextureSetMode(input.resource, options.maxAtlasIndex ?? 10);
2059
2086
  if (mode.kind === "standalone") {
2060
2087
  const key = `${branchName}\u0000${getPublishedItemId(input.resource)}`;
2061
2088
  const existing = standaloneGroups.get(key);
@@ -2099,6 +2126,8 @@ const ATLAS_DEFAULTS = {
2099
2126
  allowRotation: true,
2100
2127
  padding: 1,
2101
2128
  powerOfTwo: false,
2129
+ maxAtlasIndex: 10,
2130
+ multipleOfFour: false,
2102
2131
  square: false,
2103
2132
  multiPage: true,
2104
2133
  trimImage: false,
@@ -2182,7 +2211,7 @@ async function resolveEditorCompatibleResourceOrder(pkg, allResources, options)
2182
2211
  const refChild = child;
2183
2212
  await addResource(resourceMap.get(refChild.getSrc?.() ?? ""));
2184
2213
  for (const ref of [
2185
- refChild.getUrl?.(),
2214
+ refChild.getClearOnPublish?.() ? void 0 : refChild.getUrl?.(),
2186
2215
  refChild.getDefaultItem?.(),
2187
2216
  refChild.getIcon?.(),
2188
2217
  refChild.getSelectedIcon?.(),
@@ -2196,11 +2225,14 @@ async function resolveEditorCompatibleResourceOrder(pkg, allResources, options)
2196
2225
  refChild.getInstanceIcon?.(),
2197
2226
  refChild.getInstanceSelectedIcon?.()
2198
2227
  ]) await addResourceByLocalUiUrl(ref);
2199
- for (const item of refChild.getInstanceComboItems?.() ?? []) await addResourceByLocalUiUrl(item.icon ?? void 0);
2200
- for (const item of refChild.getListItems?.() ?? []) {
2228
+ for (const item of refChild.getInstanceAutoClearItems?.() ? [] : refChild.getInstanceComboItems?.() ?? []) await addResourceByLocalUiUrl(item.icon ?? void 0);
2229
+ for (const item of refChild.getAutoClearItems?.() ? [] : refChild.getListItems?.() ?? []) {
2201
2230
  await addResourceByLocalUiUrl(item.icon ?? void 0);
2231
+ await addResourceByLocalUiUrl(item.selectedIcon ?? void 0);
2202
2232
  await addResourceByLocalUiUrl(item.url ?? void 0);
2233
+ for (const property of item.propertyOverrides ?? []) await addResourceByLocalUiUrl(property.value);
2203
2234
  }
2235
+ for (const property of refChild.getPropertyOverrides?.() ?? []) await addResourceByLocalUiUrl(property.value);
2204
2236
  for (const gear of refChild.listGears?.() ?? []) await addGearIconResources(gear);
2205
2237
  }
2206
2238
  for (const ref of [
@@ -2451,23 +2483,32 @@ const FGUI_TYPESCRIPT_RUNTIME_TYPES = new Set([
2451
2483
  "GTree",
2452
2484
  "Transition"
2453
2485
  ]);
2454
- const SHARED_FGUI_TYPESCRIPT_VARIANT = {
2486
+ const LAYABOX_TYPESCRIPT_VARIANT = {
2455
2487
  binderMethod: "setExtension",
2456
- runtimeNamespace: "fgui"
2488
+ runtimeNamespace: "fgui",
2489
+ runtimeImport: ""
2490
+ };
2491
+ const COCOS_CREATOR_TYPESCRIPT_VARIANT = {
2492
+ ...LAYABOX_TYPESCRIPT_VARIANT,
2493
+ runtimeImport: "import * as fgui from \"fairygui-cc\";"
2457
2494
  };
2458
2495
  async function publishCodeGeneration(doc, options) {
2459
2496
  const logger = doc.getLogger();
2460
2497
  const settings = resolveCodeGenerationSettings(doc);
2461
2498
  if (!settings.allowGenCode) return;
2462
- const plugins = options.plugins?.filter((plugin) => typeof plugin.plugin.genCode === "function") ?? [];
2499
+ const plugins = options.plugins ?? [];
2463
2500
  if (plugins.length > 0) {
2464
2501
  let handled = false;
2465
- for (const plugin of plugins) try {
2466
- await plugin.plugin.genCode(doc, settings, options);
2467
- handled = true;
2468
- logger.info(`publish: Generated code using plugin "${plugin.name}"`);
2469
- } catch (error) {
2470
- logger.warn(`publish: Code generation plugin "${plugin.name}" failed: ${formatPluginError(error)}`);
2502
+ for (const plugin of plugins) {
2503
+ const genCode = plugin.plugin.genCode;
2504
+ if (!genCode) continue;
2505
+ try {
2506
+ await genCode(doc, settings, options);
2507
+ handled = true;
2508
+ logger.info(`publish: Generated code using plugin "${plugin.name}"`);
2509
+ } catch (error) {
2510
+ logger.warn(`publish: Code generation plugin "${plugin.name}" failed: ${formatPluginError(error)}`);
2511
+ }
2471
2512
  }
2472
2513
  if (handled) return;
2473
2514
  }
@@ -2531,8 +2572,9 @@ function supportsCodeGenerationLane(doc, codeType) {
2531
2572
  }
2532
2573
  function resolveFguiTypescriptVariant(doc) {
2533
2574
  const projectType = doc.getRoot().getProjectType();
2534
- if (projectType !== _openfairygui_core.ProjectType.LayaBox && projectType !== _openfairygui_core.ProjectType.CocosCreator) return null;
2535
- return SHARED_FGUI_TYPESCRIPT_VARIANT;
2575
+ if (projectType === _openfairygui_core.ProjectType.LayaBox) return LAYABOX_TYPESCRIPT_VARIANT;
2576
+ if (projectType === _openfairygui_core.ProjectType.CocosCreator) return COCOS_CREATOR_TYPESCRIPT_VARIANT;
2577
+ return null;
2536
2578
  }
2537
2579
  async function generateUnityCode(doc, pkg, plan, fs) {
2538
2580
  const packageDir = fs.join(plan.outputDir, plan.packageFolderName);
@@ -2715,7 +2757,8 @@ function renderFguiTypescriptComponentClass(classInfo, plan, variant) {
2715
2757
  }
2716
2758
  function renderFguiTypescriptBinder(classes, plan, variant) {
2717
2759
  const bindLines = classes.map((classInfo) => `\t\t${variant.runtimeNamespace}.UIObjectFactory.${variant.binderMethod}(${classInfo.encodedClassName}.URL, ${classInfo.encodedClassName});`).join("\n");
2718
- const importLines = classes.map((classInfo) => `import ${classInfo.encodedClassName} from "./${classInfo.encodedClassName}";`).join("\n");
2760
+ const classImports = classes.map((classInfo) => `import ${classInfo.encodedClassName} from "./${classInfo.encodedClassName}";`).join("\n");
2761
+ const importLines = [variant.runtimeImport, classImports].filter(Boolean).join("\n");
2719
2762
  return renderTemplate(FGUI_TYPESCRIPT_BINDER_TEMPLATE, {
2720
2763
  binderClassName: plan.binderClassName,
2721
2764
  bindLines: bindLines ? `${bindLines}\n` : "",
@@ -2779,6 +2822,7 @@ function normalizeTypeName(value) {
2779
2822
  }
2780
2823
  function collectFguiTypescriptImports(classInfo, variant) {
2781
2824
  const imports = /* @__PURE__ */ new Set();
2825
+ if (variant.runtimeImport) imports.add(variant.runtimeImport);
2782
2826
  for (const member of classInfo.members) {
2783
2827
  if (member.ignored) continue;
2784
2828
  const translated = translateFguiTypescriptType(member.type, variant);
@@ -2841,23 +2885,24 @@ async function exportPackageExternalResources(pkg, outputDir, basePath, fs, read
2841
2885
  if (exportedResourceIds.size === 0) return;
2842
2886
  if (!basePath || !readFileRaw) {
2843
2887
  if (pkg.listResources().some((resource) => {
2844
- return (isMiscResource(resource) || isSkeletonResource(resource)) && exportedResourceIds.has(resource.getId()) || skeletonDependencyImageIds.has(resource.getId());
2888
+ return (isMiscResource(resource) || isSwfResource(resource) || isSkeletonResource(resource)) && exportedResourceIds.has(resource.getId()) || skeletonDependencyImageIds.has(resource.getId());
2845
2889
  })) throw new Error(`publish: External resources in package "${pkg.getName()}" require basePath and readFileRaw for output.`);
2846
2890
  return;
2847
2891
  }
2848
2892
  for (const resource of pkg.listResources()) {
2849
2893
  const resourceId = resource.getId();
2850
- const isSkeletonExternal = exportedResourceIds.has(resourceId) && (isMiscResource(resource) || isSkeletonResource(resource));
2894
+ const isExternal = exportedResourceIds.has(resourceId) && (isMiscResource(resource) || isSwfResource(resource) || isSkeletonResource(resource));
2851
2895
  const isSkeletonImageDependency = skeletonDependencyImageIds.has(resourceId) && isImageResource(resource);
2852
- if (!isSkeletonExternal && !isSkeletonImageDependency) continue;
2896
+ if (!isExternal && !isSkeletonImageDependency) continue;
2853
2897
  let sourcePath;
2854
2898
  let targetName;
2855
2899
  if (isSkeletonImageDependency) {
2856
2900
  sourcePath = resolveImagePath(resource, pkg, basePath);
2857
2901
  targetName = resolveImageFileName(resource);
2858
- } else if (isMiscResource(resource) || isSkeletonResource(resource)) {
2902
+ } else if (isMiscResource(resource) || isSwfResource(resource) || isSkeletonResource(resource)) {
2859
2903
  sourcePath = resolveGenericResourcePath(resource, pkg, basePath);
2860
- targetName = (resource.getExtras() ?? {})._publishedFile ?? resource.getFile();
2904
+ const publishedFile = (resource.getExtras() ?? {})._publishedFile ?? resource.getFile();
2905
+ targetName = isMiscResource(resource) || isSwfResource(resource) ? `${pkg.getPublishName() || pkg.getName()}_${publishedFile}` : publishedFile;
2861
2906
  } else continue;
2862
2907
  const targetPath = fs.join(outputDir, targetName);
2863
2908
  try {
@@ -2900,14 +2945,17 @@ function resolvePublishOptions(doc, overrides = {}) {
2900
2945
  const projectType = overrides.targetProjectType ?? root.getProjectType();
2901
2946
  const explicitLayaboxTarget = overrides.targetProjectType === _openfairygui_core.ProjectType.LayaBox;
2902
2947
  const fileExtension = overrides.fileExtension ?? (explicitLayaboxTarget ? "fui" : resolveDefaultPublishFileExtension(projectType, publishSettings));
2903
- let compressed = overrides.compressed ?? publishSettings.compressDesc ?? false;
2904
- if (projectType === UNITY_PROJECT_TYPE) compressed = overrides.compressed ?? false;
2948
+ const runtimeRejectsCompression = projectType === UNITY_PROJECT_TYPE || projectType === COCOS_CREATOR_PROJECT_TYPE;
2949
+ if (runtimeRejectsCompression && overrides.compressed === true) throw new Error("publish: The selected target runtime does not support compressed package data.");
2950
+ const compressed = runtimeRejectsCompression ? false : overrides.compressed ?? publishSettings.compressDesc ?? false;
2905
2951
  const atlasOptions = {
2906
2952
  maxSize: overrides.atlas?.maxSize ?? atlasSetting.maxSize ?? 2048,
2907
2953
  fast: overrides.atlas?.fast ?? atlasSetting.fast ?? true,
2908
2954
  allowRotation: overrides.atlas?.allowRotation ?? (explicitLayaboxTarget ? false : atlasSetting.allowRotation ?? false),
2909
2955
  padding: overrides.atlas?.padding ?? atlasSetting.padding ?? 2,
2910
2956
  powerOfTwo: overrides.atlas?.powerOfTwo ?? atlasSetting.sizeOption === "pot",
2957
+ maxAtlasIndex: overrides.atlas?.maxAtlasIndex ?? 10,
2958
+ multipleOfFour: overrides.atlas?.multipleOfFour ?? atlasSetting.sizeOption === "mof",
2911
2959
  square: overrides.atlas?.square ?? atlasSetting.forceSquare ?? false,
2912
2960
  multiPage: overrides.atlas?.multiPage ?? atlasSetting.paging ?? true,
2913
2961
  trimImage: overrides.atlas?.trimImage ?? atlasSetting.trimImage ?? false,
@@ -3027,6 +3075,19 @@ function publish(options) {
3027
3075
  }
3028
3076
  }
3029
3077
  const publishName = pkg.getPublishName() || pkg.getName();
3078
+ const sourceAtlas = pkg.getSourceAtlasSettings();
3079
+ const usePackageAtlas = !sourceAtlas.useGlobal;
3080
+ const atlas = {
3081
+ ...config.atlas,
3082
+ maxSize: options.atlas?.maxSize ?? (usePackageAtlas ? sourceAtlas.maxSize : config.atlas.maxSize),
3083
+ allowRotation: config.projectType === _openfairygui_core.ProjectType.LayaBox ? false : options.atlas?.allowRotation ?? (usePackageAtlas ? sourceAtlas.allowRotation : config.atlas.allowRotation),
3084
+ powerOfTwo: options.atlas?.powerOfTwo ?? (usePackageAtlas ? sourceAtlas.sizeOption === "pot" : config.atlas.powerOfTwo),
3085
+ maxAtlasIndex: options.atlas?.maxAtlasIndex ?? sourceAtlas.maxIndex,
3086
+ multipleOfFour: options.atlas?.multipleOfFour ?? (usePackageAtlas ? sourceAtlas.sizeOption === "mof" : config.atlas.multipleOfFour),
3087
+ square: options.atlas?.square ?? (usePackageAtlas ? sourceAtlas.forceSquare : config.atlas.square),
3088
+ multiPage: options.atlas?.multiPage ?? (usePackageAtlas ? sourceAtlas.paging : config.atlas.multiPage),
3089
+ extractAlpha: config.projectType === _openfairygui_core.ProjectType.Unity && (options.atlas?.extractAlpha ?? (usePackageAtlas || sourceAtlas.extractAlpha ? sourceAtlas.extractAlpha : config.atlas.extractAlpha))
3090
+ };
3030
3091
  return {
3031
3092
  pkg,
3032
3093
  outputDir,
@@ -3038,7 +3099,7 @@ function publish(options) {
3038
3099
  activeBranch: config.activeBranch,
3039
3100
  includeHighResolution: config.includeHighResolution,
3040
3101
  separatedAtlasForBranch: config.separatedAtlasForBranch,
3041
- atlas: config.atlas
3102
+ atlas
3042
3103
  };
3043
3104
  };
3044
3105
  const createNoopPublishFs = () => ({
@@ -3058,7 +3119,6 @@ function publish(options) {
3058
3119
  const atlasRuntimeOptions = resolvePublishAtlasRuntimeOptions(plan.fileExtension);
3059
3120
  await atlas({
3060
3121
  ...plan.atlas,
3061
- ...options.atlas ?? {},
3062
3122
  separatedAtlasForBranch: plan.separatedAtlasForBranch,
3063
3123
  encoder: options.encoder,
3064
3124
  basePath: options.basePath,
@@ -1,4 +1,4 @@
1
- import { l as PublishFileSystem, r as AtlasRasterBackend, t as AtlasOptions } from "./atlas-CHsu2Y8i.cjs";
1
+ import { l as PublishFileSystem, r as AtlasRasterBackend, t as AtlasOptions } from "./atlas-BtWa1DwO.js";
2
2
  import { Component, Document, FileSystem, Package, ProjectSettings, PublishSettings, Transform } from "@openfairygui/core";
3
3
 
4
4
  //#region src/publish/options.d.ts
@@ -59,7 +59,7 @@ interface PublishOptions {
59
59
  */
60
60
  codeGeneration?: boolean;
61
61
  }
62
- interface ResolvedPublishAtlasOptions extends Pick<AtlasOptions, 'maxSize' | 'fast' | 'allowRotation' | 'padding' | 'powerOfTwo' | 'square' | 'multiPage' | 'trimImage' | 'extractAlpha'> {}
62
+ interface ResolvedPublishAtlasOptions extends Pick<AtlasOptions, 'maxSize' | 'fast' | 'allowRotation' | 'padding' | 'powerOfTwo' | 'maxAtlasIndex' | 'multipleOfFour' | 'square' | 'multiPage' | 'trimImage' | 'extractAlpha'> {}
63
63
  interface ResolvePublishOptionsOverrides {
64
64
  /** Select a target profile between direct overrides and persisted project settings. */
65
65
  targetProjectType?: number;
@@ -212,7 +212,7 @@ interface ResolvedPackageCodegenPlan {
212
212
  packageFolderName: string;
213
213
  packageNamespace: string;
214
214
  binderClassName: string;
215
- settings: CliCodeGenerationSettings;
215
+ settings: Required<CliCodeGenerationSettings>;
216
216
  }
217
217
  interface CodegenMember {
218
218
  index: number;
@@ -238,7 +238,7 @@ interface CodegenClass {
238
238
  members: CodegenMember[];
239
239
  }
240
240
  declare function publishCodeGeneration(doc: Document, options: PublishCodeGenerationOptions): Promise<void>;
241
- declare function resolvePackageCodegenPlan(pkg: Package, settings: CliCodeGenerationSettings, options: PublishCodeGenerationOptions): ResolvedPackageCodegenPlan | null;
241
+ declare function resolvePackageCodegenPlan(pkg: Package, settings: Required<CliCodeGenerationSettings>, options: PublishCodeGenerationOptions): ResolvedPackageCodegenPlan | null;
242
242
  declare function buildCodegenClasses(doc: Document, pkg: Package, plan: ResolvedPackageCodegenPlan): CodegenClass[];
243
243
  declare function encodeText(value: string): Uint8Array;
244
244
  declare function decodeText(value: Uint8Array): string;
@@ -1,4 +1,4 @@
1
- const require_publish = require("./publish-Cl1b5HtO.cjs");
1
+ const require_publish = require("./publish-BHoaYgPU.cjs");
2
2
  let _openfairygui_core = require("@openfairygui/core");
3
3
  //#region src/restore-internals/output-transaction.ts
4
4
  function isPathWithin(root, candidate) {
@@ -1,4 +1,4 @@
1
- import { l as PublishFileSystem, r as AtlasRasterBackend, t as AtlasOptions } from "./atlas-C6tbl7nn.js";
1
+ import { l as PublishFileSystem, r as AtlasRasterBackend, t as AtlasOptions } from "./atlas-CSqHsG0X.cjs";
2
2
  import { Component, Document, FileSystem, Package, ProjectSettings, PublishSettings, Transform } from "@openfairygui/core";
3
3
 
4
4
  //#region src/publish/options.d.ts
@@ -59,7 +59,7 @@ interface PublishOptions {
59
59
  */
60
60
  codeGeneration?: boolean;
61
61
  }
62
- interface ResolvedPublishAtlasOptions extends Pick<AtlasOptions, 'maxSize' | 'fast' | 'allowRotation' | 'padding' | 'powerOfTwo' | 'square' | 'multiPage' | 'trimImage' | 'extractAlpha'> {}
62
+ interface ResolvedPublishAtlasOptions extends Pick<AtlasOptions, 'maxSize' | 'fast' | 'allowRotation' | 'padding' | 'powerOfTwo' | 'maxAtlasIndex' | 'multipleOfFour' | 'square' | 'multiPage' | 'trimImage' | 'extractAlpha'> {}
63
63
  interface ResolvePublishOptionsOverrides {
64
64
  /** Select a target profile between direct overrides and persisted project settings. */
65
65
  targetProjectType?: number;
@@ -212,7 +212,7 @@ interface ResolvedPackageCodegenPlan {
212
212
  packageFolderName: string;
213
213
  packageNamespace: string;
214
214
  binderClassName: string;
215
- settings: CliCodeGenerationSettings;
215
+ settings: Required<CliCodeGenerationSettings>;
216
216
  }
217
217
  interface CodegenMember {
218
218
  index: number;
@@ -238,7 +238,7 @@ interface CodegenClass {
238
238
  members: CodegenMember[];
239
239
  }
240
240
  declare function publishCodeGeneration(doc: Document, options: PublishCodeGenerationOptions): Promise<void>;
241
- declare function resolvePackageCodegenPlan(pkg: Package, settings: CliCodeGenerationSettings, options: PublishCodeGenerationOptions): ResolvedPackageCodegenPlan | null;
241
+ declare function resolvePackageCodegenPlan(pkg: Package, settings: Required<CliCodeGenerationSettings>, options: PublishCodeGenerationOptions): ResolvedPackageCodegenPlan | null;
242
242
  declare function buildCodegenClasses(doc: Document, pkg: Package, plan: ResolvedPackageCodegenPlan): CodegenClass[];
243
243
  declare function encodeText(value: string): Uint8Array;
244
244
  declare function decodeText(value: Uint8Array): string;
@@ -1,4 +1,4 @@
1
- import { d as basename, f as normalizeComparablePath, p as trimTrailingSlashes } from "./publish-Ni90AtjG.js";
1
+ import { d as basename, f as normalizeComparablePath, p as trimTrailingSlashes } from "./publish-BCzpqNr9.js";
2
2
  import { BinaryReader, ProjectType, ProjectWriter, generateId } from "@openfairygui/core";
3
3
  //#region src/restore-internals/output-transaction.ts
4
4
  function isPathWithin(root, candidate) {
package/dist/web.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_publish = require("./publish-Cl1b5HtO.cjs");
2
+ const require_publish = require("./publish-BHoaYgPU.cjs");
3
3
  let _openfairygui_core = require("@openfairygui/core");
4
4
  let fast_xml_parser = require("fast-xml-parser");
5
5
  //#region src/adapters/web/raster.ts
@@ -216,6 +216,46 @@ var BrowserImagePipeline = class {
216
216
  ensureAlpha() {
217
217
  return this;
218
218
  }
219
+ removeAlpha() {
220
+ this.raster = this.raster.then((source) => {
221
+ const context = getBrowserContext(source.canvas);
222
+ const image = context.getImageData(0, 0, source.width, source.height);
223
+ for (let index = 3; index < image.data.length; index += 4) image.data[index] = 255;
224
+ context.putImageData(image, 0, 0);
225
+ return source;
226
+ });
227
+ return this;
228
+ }
229
+ extractChannel(channel) {
230
+ if (channel !== "alpha") throw new Error(`publishBrowser: Unsupported channel "${channel}".`);
231
+ this.raster = this.raster.then((source) => {
232
+ const context = getBrowserContext(source.canvas);
233
+ const image = context.getImageData(0, 0, source.width, source.height);
234
+ for (let index = 0; index < image.data.length; index += 4) {
235
+ const alpha = image.data[index + 3] ?? 0;
236
+ image.data[index] = alpha;
237
+ image.data[index + 1] = alpha;
238
+ image.data[index + 2] = alpha;
239
+ image.data[index + 3] = 255;
240
+ }
241
+ context.putImageData(image, 0, 0);
242
+ return source;
243
+ });
244
+ return this;
245
+ }
246
+ joinChannel(images) {
247
+ this.raster = Promise.all([this.raster, ...images.map((image) => this.decode(image))]).then(([source, ...channels]) => {
248
+ const context = getBrowserContext(source.canvas);
249
+ const image = context.getImageData(0, 0, source.width, source.height);
250
+ for (const [channelIndex, channel] of channels.slice(0, 2).entries()) {
251
+ const channelData = getBrowserContext(channel.canvas).getImageData(0, 0, channel.width, channel.height).data;
252
+ for (let index = 0; index < image.data.length; index += 4) image.data[index + channelIndex + 1] = channelData[index] ?? 0;
253
+ }
254
+ context.putImageData(image, 0, 0);
255
+ return source;
256
+ });
257
+ return this;
258
+ }
219
259
  resize(options) {
220
260
  this.raster = this.raster.then((source) => {
221
261
  const target = createRaster(options.width, options.height);
package/dist/web.d.cts CHANGED
@@ -1,9 +1,9 @@
1
- import { d as PublishSourceFileSystem, t as AtlasOptions, u as PublishOutputFileSystem } from "./atlas-CHsu2Y8i.cjs";
1
+ import { d as PublishSourceFileSystem, t as AtlasOptions, u as PublishOutputFileSystem } from "./atlas-CSqHsG0X.cjs";
2
2
  import { Document } from "@openfairygui/core";
3
3
 
4
4
  //#region src/adapters/web/publish.d.ts
5
5
  type BrowserPublishProjectType = 'layabox';
6
- type BrowserPublishAtlasOptions = Pick<AtlasOptions, 'maxSize' | 'fast' | 'allowRotation' | 'padding' | 'powerOfTwo' | 'square' | 'multiPage' | 'trimImage' | 'extractAlpha'>;
6
+ type BrowserPublishAtlasOptions = Pick<AtlasOptions, 'maxSize' | 'fast' | 'allowRotation' | 'padding' | 'powerOfTwo' | 'maxAtlasIndex' | 'multipleOfFour' | 'square' | 'multiPage' | 'trimImage' | 'extractAlpha'>;
7
7
  type BrowserPublishSourceFileSystem = PublishSourceFileSystem;
8
8
  type BrowserPublishOutputFileSystem = PublishOutputFileSystem;
9
9
  interface BrowserPublishOptions {
package/dist/web.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { d as PublishSourceFileSystem, t as AtlasOptions, u as PublishOutputFileSystem } from "./atlas-C6tbl7nn.js";
1
+ import { d as PublishSourceFileSystem, t as AtlasOptions, u as PublishOutputFileSystem } from "./atlas-BtWa1DwO.js";
2
2
  import { Document } from "@openfairygui/core";
3
3
 
4
4
  //#region src/adapters/web/publish.d.ts
5
5
  type BrowserPublishProjectType = 'layabox';
6
- type BrowserPublishAtlasOptions = Pick<AtlasOptions, 'maxSize' | 'fast' | 'allowRotation' | 'padding' | 'powerOfTwo' | 'square' | 'multiPage' | 'trimImage' | 'extractAlpha'>;
6
+ type BrowserPublishAtlasOptions = Pick<AtlasOptions, 'maxSize' | 'fast' | 'allowRotation' | 'padding' | 'powerOfTwo' | 'maxAtlasIndex' | 'multipleOfFour' | 'square' | 'multiPage' | 'trimImage' | 'extractAlpha'>;
7
7
  type BrowserPublishSourceFileSystem = PublishSourceFileSystem;
8
8
  type BrowserPublishOutputFileSystem = PublishOutputFileSystem;
9
9
  interface BrowserPublishOptions {
package/dist/web.js CHANGED
@@ -1,4 +1,4 @@
1
- import { c as resolveCodeGenerationSettings, n as resolvePublishOptions, t as publish } from "./publish-Ni90AtjG.js";
1
+ import { c as resolveCodeGenerationSettings, n as resolvePublishOptions, t as publish } from "./publish-BCzpqNr9.js";
2
2
  import { ProjectType } from "@openfairygui/core";
3
3
  import { XMLParser, XMLValidator } from "fast-xml-parser";
4
4
  //#region src/adapters/web/raster.ts
@@ -215,6 +215,46 @@ var BrowserImagePipeline = class {
215
215
  ensureAlpha() {
216
216
  return this;
217
217
  }
218
+ removeAlpha() {
219
+ this.raster = this.raster.then((source) => {
220
+ const context = getBrowserContext(source.canvas);
221
+ const image = context.getImageData(0, 0, source.width, source.height);
222
+ for (let index = 3; index < image.data.length; index += 4) image.data[index] = 255;
223
+ context.putImageData(image, 0, 0);
224
+ return source;
225
+ });
226
+ return this;
227
+ }
228
+ extractChannel(channel) {
229
+ if (channel !== "alpha") throw new Error(`publishBrowser: Unsupported channel "${channel}".`);
230
+ this.raster = this.raster.then((source) => {
231
+ const context = getBrowserContext(source.canvas);
232
+ const image = context.getImageData(0, 0, source.width, source.height);
233
+ for (let index = 0; index < image.data.length; index += 4) {
234
+ const alpha = image.data[index + 3] ?? 0;
235
+ image.data[index] = alpha;
236
+ image.data[index + 1] = alpha;
237
+ image.data[index + 2] = alpha;
238
+ image.data[index + 3] = 255;
239
+ }
240
+ context.putImageData(image, 0, 0);
241
+ return source;
242
+ });
243
+ return this;
244
+ }
245
+ joinChannel(images) {
246
+ this.raster = Promise.all([this.raster, ...images.map((image) => this.decode(image))]).then(([source, ...channels]) => {
247
+ const context = getBrowserContext(source.canvas);
248
+ const image = context.getImageData(0, 0, source.width, source.height);
249
+ for (const [channelIndex, channel] of channels.slice(0, 2).entries()) {
250
+ const channelData = getBrowserContext(channel.canvas).getImageData(0, 0, channel.width, channel.height).data;
251
+ for (let index = 0; index < image.data.length; index += 4) image.data[index + channelIndex + 1] = channelData[index] ?? 0;
252
+ }
253
+ context.putImageData(image, 0, 0);
254
+ return source;
255
+ });
256
+ return this;
257
+ }
218
258
  resize(options) {
219
259
  this.raster = this.raster.then((source) => {
220
260
  const target = createRaster(options.width, options.height);