@series-inc/stowkit-cli 0.6.39 → 0.6.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/disk-project.d.ts +12 -1
- package/dist/app/state.d.ts +10 -2
- package/dist/app/state.js +1 -0
- package/dist/app/stowmeta-io.js +9 -0
- package/dist/app/stowspritesheet-io.d.ts +6 -0
- package/dist/app/stowspritesheet-io.js +40 -0
- package/dist/app/thumbnail-cache.js +1 -1
- package/dist/cleanup.js +7 -6
- package/dist/core/constants.d.ts +2 -0
- package/dist/core/constants.js +2 -0
- package/dist/core/types.d.ts +10 -1
- package/dist/core/types.js +1 -0
- package/dist/format/metadata.d.ts +3 -1
- package/dist/format/metadata.js +23 -1
- package/dist/node-fs.d.ts +1 -0
- package/dist/node-fs.js +11 -4
- package/dist/orchestrator.d.ts +1 -0
- package/dist/orchestrator.js +32 -2
- package/dist/pipeline.js +37 -1
- package/dist/server.js +71 -1
- package/package.json +2 -2
|
@@ -80,6 +80,9 @@ export interface StowMetaAnimationClip extends StowMetaBase {
|
|
|
80
80
|
export interface StowMetaMaterialSchema extends StowMetaBase {
|
|
81
81
|
type: 'materialSchema';
|
|
82
82
|
}
|
|
83
|
+
export interface StowMetaSpriteSheet extends StowMetaBase {
|
|
84
|
+
type: 'spriteSheet';
|
|
85
|
+
}
|
|
83
86
|
export interface StowMetaGlbChild {
|
|
84
87
|
name: string;
|
|
85
88
|
childType: string;
|
|
@@ -108,7 +111,7 @@ export interface StowMetaGlbContainer extends StowMetaBase {
|
|
|
108
111
|
preserveHierarchy?: boolean;
|
|
109
112
|
children: StowMetaGlbChild[];
|
|
110
113
|
}
|
|
111
|
-
export type StowMeta = StowMetaTexture | StowMetaAudio | StowMetaStaticMesh | StowMetaSkinnedMesh | StowMetaAnimationClip | StowMetaMaterialSchema | StowMetaGlbContainer;
|
|
114
|
+
export type StowMeta = StowMetaTexture | StowMetaAudio | StowMetaStaticMesh | StowMetaSkinnedMesh | StowMetaAnimationClip | StowMetaMaterialSchema | StowMetaSpriteSheet | StowMetaGlbContainer;
|
|
112
115
|
export interface StowMatProperty {
|
|
113
116
|
fieldName: string;
|
|
114
117
|
fieldType: string;
|
|
@@ -121,6 +124,14 @@ export interface StowMat {
|
|
|
121
124
|
schemaName: string;
|
|
122
125
|
properties: StowMatProperty[];
|
|
123
126
|
}
|
|
127
|
+
export interface StowSpriteSheet {
|
|
128
|
+
version: 1;
|
|
129
|
+
textureAsset: string | null;
|
|
130
|
+
rows: number;
|
|
131
|
+
columns: number;
|
|
132
|
+
frameCount: number;
|
|
133
|
+
frameRate: number;
|
|
134
|
+
}
|
|
124
135
|
export declare const KTX2_QUALITY_STRINGS: Record<string, KTX2Quality>;
|
|
125
136
|
export declare const KTX2_QUALITY_TO_STRING: Record<number, string>;
|
|
126
137
|
export declare const TEXTURE_RESIZE_STRINGS: Record<string, TextureResize>;
|
package/dist/app/state.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AssetType, TextureMetadata, AudioMetadata, MeshMetadata, AnimationClipMetadata, SkinnedMeshMetadata, KTX2Quality, TextureResize, TextureFilterMode, DracoQualityPreset, AacQuality, AudioSampleRate, MaterialFieldType, PreviewPropertyFlag } from '../core/types.js';
|
|
1
|
+
import type { AssetType, TextureMetadata, AudioMetadata, MeshMetadata, AnimationClipMetadata, SkinnedMeshMetadata, SpriteSheetMetadata, KTX2Quality, TextureResize, TextureFilterMode, DracoQualityPreset, AacQuality, AudioSampleRate, MaterialFieldType, PreviewPropertyFlag } from '../core/types.js';
|
|
2
2
|
export interface MaterialProperty {
|
|
3
3
|
fieldName: string;
|
|
4
4
|
fieldType: MaterialFieldType;
|
|
@@ -10,6 +10,13 @@ export interface MaterialConfig {
|
|
|
10
10
|
schemaId: string;
|
|
11
11
|
properties: MaterialProperty[];
|
|
12
12
|
}
|
|
13
|
+
export interface SpriteSheetConfig {
|
|
14
|
+
textureAssetId: string | null;
|
|
15
|
+
rows: number;
|
|
16
|
+
columns: number;
|
|
17
|
+
frameCount: number;
|
|
18
|
+
frameRate: number;
|
|
19
|
+
}
|
|
13
20
|
export interface AssetSettings {
|
|
14
21
|
quality: KTX2Quality;
|
|
15
22
|
resize: TextureResize;
|
|
@@ -21,6 +28,7 @@ export interface AssetSettings {
|
|
|
21
28
|
audioSampleRate: AudioSampleRate;
|
|
22
29
|
targetMeshId: string | null;
|
|
23
30
|
materialConfig: MaterialConfig;
|
|
31
|
+
spritesheetConfig: SpriteSheetConfig;
|
|
24
32
|
materialOverrides: Record<number, string | null>;
|
|
25
33
|
pack: string;
|
|
26
34
|
excluded: boolean;
|
|
@@ -35,7 +43,7 @@ export interface ProjectAsset {
|
|
|
35
43
|
status: 'loading' | 'pending' | 'processing' | 'ready' | 'error';
|
|
36
44
|
error?: string;
|
|
37
45
|
settings: AssetSettings;
|
|
38
|
-
metadata?: TextureMetadata | AudioMetadata | MeshMetadata | AnimationClipMetadata | SkinnedMeshMetadata;
|
|
46
|
+
metadata?: TextureMetadata | AudioMetadata | MeshMetadata | AnimationClipMetadata | SkinnedMeshMetadata | SpriteSheetMetadata;
|
|
39
47
|
sourceSize: number;
|
|
40
48
|
processedSize: number;
|
|
41
49
|
parentId?: string;
|
package/dist/app/state.js
CHANGED
|
@@ -11,6 +11,7 @@ export function defaultAssetSettings() {
|
|
|
11
11
|
audioSampleRate: ASR.Auto,
|
|
12
12
|
targetMeshId: null,
|
|
13
13
|
materialConfig: { schemaId: '', properties: [] },
|
|
14
|
+
spritesheetConfig: { textureAssetId: null, rows: 1, columns: 1, frameCount: 1, frameRate: 12 },
|
|
14
15
|
materialOverrides: {},
|
|
15
16
|
pack: 'default',
|
|
16
17
|
excluded: false,
|
package/dist/app/stowmeta-io.js
CHANGED
|
@@ -114,6 +114,11 @@ export function stowmetaToAssetSettings(meta) {
|
|
|
114
114
|
type: AssetType.MaterialSchema,
|
|
115
115
|
settings: base,
|
|
116
116
|
};
|
|
117
|
+
case 'spriteSheet':
|
|
118
|
+
return {
|
|
119
|
+
type: AssetType.SpriteSheet,
|
|
120
|
+
settings: base,
|
|
121
|
+
};
|
|
117
122
|
case 'glbContainer':
|
|
118
123
|
return {
|
|
119
124
|
type: AssetType.GlbContainer,
|
|
@@ -185,6 +190,8 @@ export function assetSettingsToStowmeta(asset) {
|
|
|
185
190
|
};
|
|
186
191
|
case AssetType.MaterialSchema:
|
|
187
192
|
return { ...base, type: 'materialSchema' };
|
|
193
|
+
case AssetType.SpriteSheet:
|
|
194
|
+
return { ...base, type: 'spriteSheet' };
|
|
188
195
|
case AssetType.GlbContainer:
|
|
189
196
|
return { ...base, type: 'glbContainer', preserveHierarchy: asset.settings.preserveHierarchy || undefined, children: [] };
|
|
190
197
|
default:
|
|
@@ -250,6 +257,8 @@ export function generateDefaultStowmeta(relativePath, type, projectDefaults, ima
|
|
|
250
257
|
return { ...base, type: 'animationClip', targetMeshId: null };
|
|
251
258
|
case AssetType.MaterialSchema:
|
|
252
259
|
return { ...base, type: 'materialSchema' };
|
|
260
|
+
case AssetType.SpriteSheet:
|
|
261
|
+
return { ...base, type: 'spriteSheet' };
|
|
253
262
|
case AssetType.GlbContainer:
|
|
254
263
|
return { ...base, type: 'glbContainer', children: [] };
|
|
255
264
|
default:
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SpriteSheetConfig } from './state.js';
|
|
2
|
+
import type { StowSpriteSheet } from './disk-project.js';
|
|
3
|
+
export declare function readStowSpriteSheet(srcArtDir: string, relativePath: string): Promise<StowSpriteSheet | null>;
|
|
4
|
+
export declare function writeStowSpriteSheet(srcArtDir: string, relativePath: string, sheet: StowSpriteSheet): Promise<void>;
|
|
5
|
+
export declare function spritesheetConfigToStowSpriteSheet(config: SpriteSheetConfig): StowSpriteSheet;
|
|
6
|
+
export declare function stowSpriteSheetToConfig(sheet: StowSpriteSheet): SpriteSheetConfig;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { readTextFile, writeFile } from '../node-fs.js';
|
|
2
|
+
export async function readStowSpriteSheet(srcArtDir, relativePath) {
|
|
3
|
+
const text = await readTextFile(srcArtDir, relativePath);
|
|
4
|
+
if (!text)
|
|
5
|
+
return null;
|
|
6
|
+
try {
|
|
7
|
+
return JSON.parse(text);
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export async function writeStowSpriteSheet(srcArtDir, relativePath, sheet) {
|
|
14
|
+
try {
|
|
15
|
+
const json = JSON.stringify(sheet, null, 2);
|
|
16
|
+
await writeFile(srcArtDir, relativePath, json);
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
console.warn(`[stowspritesheet] Failed to write ${relativePath}:`, err);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function spritesheetConfigToStowSpriteSheet(config) {
|
|
23
|
+
return {
|
|
24
|
+
version: 1,
|
|
25
|
+
textureAsset: config.textureAssetId,
|
|
26
|
+
rows: config.rows,
|
|
27
|
+
columns: config.columns,
|
|
28
|
+
frameCount: config.frameCount,
|
|
29
|
+
frameRate: config.frameRate,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export function stowSpriteSheetToConfig(sheet) {
|
|
33
|
+
return {
|
|
34
|
+
textureAssetId: sheet.textureAsset ?? null,
|
|
35
|
+
rows: sheet.rows ?? 1,
|
|
36
|
+
columns: sheet.columns ?? 1,
|
|
37
|
+
frameCount: sheet.frameCount ?? 1,
|
|
38
|
+
frameRate: sheet.frameRate ?? 12,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
@@ -36,7 +36,7 @@ export async function writeManifest(srcArtDir, manifest) {
|
|
|
36
36
|
export function computeSettingsHash(settings) {
|
|
37
37
|
// Only include settings that affect visual output
|
|
38
38
|
const relevant = {};
|
|
39
|
-
for (const key of ['quality', 'resize', 'generateMipmaps', 'dracoQuality', 'materialConfig', 'targetMeshId', 'materialOverrides']) {
|
|
39
|
+
for (const key of ['quality', 'resize', 'generateMipmaps', 'dracoQuality', 'materialConfig', 'spritesheetConfig', 'targetMeshId', 'materialOverrides']) {
|
|
40
40
|
if (settings[key] !== undefined)
|
|
41
41
|
relevant[key] = settings[key];
|
|
42
42
|
}
|
package/dist/cleanup.js
CHANGED
|
@@ -9,11 +9,12 @@ export async function cleanupProject(projectDir, opts) {
|
|
|
9
9
|
// Build set of source files that exist
|
|
10
10
|
const sourceFiles = new Set(scan.sourceFiles.map(f => f.relativePath));
|
|
11
11
|
const matFiles = new Set(scan.matFiles.map(f => f.relativePath));
|
|
12
|
+
const spritesheetFiles = new Set(scan.spritesheetFiles.map(f => f.relativePath));
|
|
12
13
|
let deletedCaches = 0;
|
|
13
14
|
let deletedMetas = 0;
|
|
14
15
|
let freedBytes = 0;
|
|
15
16
|
// Walk all files looking for orphaned .stowcache and .stowmeta
|
|
16
|
-
await walkForOrphans(config.srcArtDir, '', sourceFiles, matFiles, async (orphanPath, type, size) => {
|
|
17
|
+
await walkForOrphans(config.srcArtDir, '', sourceFiles, matFiles, spritesheetFiles, async (orphanPath, type, size) => {
|
|
17
18
|
const fullPath = path.join(config.srcArtDir, orphanPath);
|
|
18
19
|
await fs.unlink(fullPath);
|
|
19
20
|
freedBytes += size;
|
|
@@ -43,7 +44,7 @@ export async function cleanupProject(projectDir, opts) {
|
|
|
43
44
|
console.log(`Cleaned up ${deletedCaches} cache(s) and ${deletedMetas} meta(s)${thumbNote} (${(freedBytes / 1024).toFixed(0)} KB freed)`);
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
|
-
async function walkForOrphans(basePath, prefix, sourceFiles, matFiles, onOrphan) {
|
|
47
|
+
async function walkForOrphans(basePath, prefix, sourceFiles, matFiles, spritesheetFiles, onOrphan) {
|
|
47
48
|
const dirPath = prefix ? path.join(basePath, prefix) : basePath;
|
|
48
49
|
let entries;
|
|
49
50
|
try {
|
|
@@ -59,21 +60,21 @@ async function walkForOrphans(basePath, prefix, sourceFiles, matFiles, onOrphan)
|
|
|
59
60
|
continue;
|
|
60
61
|
if (entry.name.endsWith('.children'))
|
|
61
62
|
continue;
|
|
62
|
-
await walkForOrphans(basePath, relativePath, sourceFiles, matFiles, onOrphan);
|
|
63
|
+
await walkForOrphans(basePath, relativePath, sourceFiles, matFiles, spritesheetFiles, onOrphan);
|
|
63
64
|
}
|
|
64
65
|
else if (entry.isFile()) {
|
|
65
66
|
if (entry.name.endsWith('.stowcache')) {
|
|
66
67
|
// Cache orphan: source file doesn't exist
|
|
67
68
|
const sourceId = relativePath.replace(/\.stowcache$/, '');
|
|
68
|
-
if (!sourceFiles.has(sourceId) && !matFiles.has(sourceId)) {
|
|
69
|
+
if (!sourceFiles.has(sourceId) && !matFiles.has(sourceId) && !spritesheetFiles.has(sourceId)) {
|
|
69
70
|
const stat = await fs.stat(path.join(basePath, relativePath));
|
|
70
71
|
await onOrphan(relativePath, 'cache', stat.size);
|
|
71
72
|
}
|
|
72
73
|
}
|
|
73
74
|
else if (entry.name.endsWith('.stowmeta')) {
|
|
74
|
-
// Meta orphan: neither source file nor
|
|
75
|
+
// Meta orphan: neither source file, mat file, nor spritesheet file exists
|
|
75
76
|
const sourceId = relativePath.replace(/\.stowmeta$/, '');
|
|
76
|
-
if (!sourceFiles.has(sourceId) && !matFiles.has(sourceId)) {
|
|
77
|
+
if (!sourceFiles.has(sourceId) && !matFiles.has(sourceId) && !spritesheetFiles.has(sourceId)) {
|
|
77
78
|
const stat = await fs.stat(path.join(basePath, relativePath));
|
|
78
79
|
await onOrphan(relativePath, 'meta', stat.size);
|
|
79
80
|
}
|
package/dist/core/constants.d.ts
CHANGED
|
@@ -69,3 +69,5 @@ export declare const ANIMATION_CLIP_METADATA_FIXED_SIZE = 268;
|
|
|
69
69
|
export declare const TRACK_NAME_SIZE = 64;
|
|
70
70
|
/** Metadata version discriminator for v2 animation clips */
|
|
71
71
|
export declare const ANIMATION_METADATA_VERSION = 2;
|
|
72
|
+
/** Size of SpriteSheetMetadata on disk (bytes) */
|
|
73
|
+
export declare const SPRITESHEET_METADATA_SIZE = 272;
|
package/dist/core/constants.js
CHANGED
|
@@ -70,3 +70,5 @@ export const ANIMATION_CLIP_METADATA_FIXED_SIZE = 268;
|
|
|
70
70
|
export const TRACK_NAME_SIZE = 64;
|
|
71
71
|
/** Metadata version discriminator for v2 animation clips */
|
|
72
72
|
export const ANIMATION_METADATA_VERSION = 2;
|
|
73
|
+
/** Size of SpriteSheetMetadata on disk (bytes) */
|
|
74
|
+
export const SPRITESHEET_METADATA_SIZE = 272;
|
package/dist/core/types.d.ts
CHANGED
|
@@ -6,7 +6,8 @@ export declare enum AssetType {
|
|
|
6
6
|
MaterialSchema = 4,
|
|
7
7
|
SkinnedMesh = 5,
|
|
8
8
|
AnimationClip = 6,
|
|
9
|
-
GlbContainer = 7
|
|
9
|
+
GlbContainer = 7,
|
|
10
|
+
SpriteSheet = 8
|
|
10
11
|
}
|
|
11
12
|
export declare enum KTX2Quality {
|
|
12
13
|
Fastest = 0,
|
|
@@ -142,6 +143,14 @@ export interface MaterialSchemaMetadata {
|
|
|
142
143
|
fieldCount: number;
|
|
143
144
|
fields: MaterialSchemaField[];
|
|
144
145
|
}
|
|
146
|
+
export interface SpriteSheetMetadata {
|
|
147
|
+
stringId: string;
|
|
148
|
+
textureId: string;
|
|
149
|
+
rows: number;
|
|
150
|
+
columns: number;
|
|
151
|
+
frameCount: number;
|
|
152
|
+
frameRate: number;
|
|
153
|
+
}
|
|
145
154
|
export interface MeshMetadata {
|
|
146
155
|
meshGeometryCount: number;
|
|
147
156
|
materialCount: number;
|
package/dist/core/types.js
CHANGED
|
@@ -9,6 +9,7 @@ export var AssetType;
|
|
|
9
9
|
AssetType[AssetType["SkinnedMesh"] = 5] = "SkinnedMesh";
|
|
10
10
|
AssetType[AssetType["AnimationClip"] = 6] = "AnimationClip";
|
|
11
11
|
AssetType[AssetType["GlbContainer"] = 7] = "GlbContainer";
|
|
12
|
+
AssetType[AssetType["SpriteSheet"] = 8] = "SpriteSheet";
|
|
12
13
|
})(AssetType || (AssetType = {}));
|
|
13
14
|
// ─── Texture Enums ──────────────────────────────────────────────────────────
|
|
14
15
|
export var KTX2Quality;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { TextureMetadata, AudioMetadata, MeshMetadata, MaterialSchemaMetadata, AnimationClipMetadata, SkinnedMeshMetadata } from '../core/types.js';
|
|
1
|
+
import type { TextureMetadata, AudioMetadata, MeshMetadata, MaterialSchemaMetadata, AnimationClipMetadata, SkinnedMeshMetadata, SpriteSheetMetadata } from '../core/types.js';
|
|
2
2
|
export declare function serializeTextureMetadata(meta: TextureMetadata): Uint8Array;
|
|
3
3
|
export declare function deserializeTextureMetadata(data: Uint8Array): TextureMetadata;
|
|
4
4
|
export declare function serializeAudioMetadata(meta: AudioMetadata): Uint8Array;
|
|
@@ -11,6 +11,8 @@ export declare function serializeAnimationClipMetadata(meta: AnimationClipMetada
|
|
|
11
11
|
export declare function deserializeAnimationClipMetadata(data: Uint8Array): AnimationClipMetadata;
|
|
12
12
|
export declare function serializeSkinnedMeshMetadata(meta: SkinnedMeshMetadata): Uint8Array;
|
|
13
13
|
export declare function deserializeSkinnedMeshMetadata(data: Uint8Array): SkinnedMeshMetadata;
|
|
14
|
+
export declare function serializeSpriteSheetMetadata(meta: SpriteSheetMetadata): Uint8Array;
|
|
15
|
+
export declare function deserializeSpriteSheetMetadata(data: Uint8Array): SpriteSheetMetadata;
|
|
14
16
|
export declare function wrapMetadata(assetMetadata: Uint8Array, tags: string[]): Uint8Array;
|
|
15
17
|
export declare function unwrapMetadata(wrapped: Uint8Array): {
|
|
16
18
|
tags: string[];
|
package/dist/format/metadata.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BinaryReader, BinaryWriter } from '../core/binary.js';
|
|
2
|
-
import { TEXTURE_METADATA_SIZE, AUDIO_METADATA_SIZE, STRING_ID_SIZE, MESH_GEOMETRY_INFO_SIZE, SCENE_NODE_SIZE, MATERIAL_DATA_FIXED_SIZE, MATERIAL_PROPERTY_VALUE_SIZE, MESH_METADATA_FIXED_SIZE, NODE_NAME_SIZE, MATERIAL_NAME_SIZE, MATERIAL_SCHEMA_ID_SIZE, MATERIAL_FIELD_NAME_SIZE, MATERIAL_SCHEMA_NAME_SIZE, MATERIAL_SCHEMA_DEFAULT_TEXTURE_ID_SIZE, MATERIAL_SCHEMA_METADATA_FIXED_SIZE, MATERIAL_SCHEMA_FIELD_SIZE, BONE_NAME_SIZE, SKINNED_MESH_GEOMETRY_INFO_SIZE, SKINNED_MESH_METADATA_FIXED_SIZE, BONE_SIZE, ANIMATION_TRACK_DESCRIPTOR_SIZE, ANIMATION_CLIP_METADATA_FIXED_SIZE, TRACK_NAME_SIZE, ANIMATION_METADATA_VERSION, } from '../core/constants.js';
|
|
2
|
+
import { TEXTURE_METADATA_SIZE, AUDIO_METADATA_SIZE, STRING_ID_SIZE, MESH_GEOMETRY_INFO_SIZE, SCENE_NODE_SIZE, MATERIAL_DATA_FIXED_SIZE, MATERIAL_PROPERTY_VALUE_SIZE, MESH_METADATA_FIXED_SIZE, NODE_NAME_SIZE, MATERIAL_NAME_SIZE, MATERIAL_SCHEMA_ID_SIZE, MATERIAL_FIELD_NAME_SIZE, MATERIAL_SCHEMA_NAME_SIZE, MATERIAL_SCHEMA_DEFAULT_TEXTURE_ID_SIZE, MATERIAL_SCHEMA_METADATA_FIXED_SIZE, MATERIAL_SCHEMA_FIELD_SIZE, BONE_NAME_SIZE, SKINNED_MESH_GEOMETRY_INFO_SIZE, SKINNED_MESH_METADATA_FIXED_SIZE, BONE_SIZE, ANIMATION_TRACK_DESCRIPTOR_SIZE, ANIMATION_CLIP_METADATA_FIXED_SIZE, TRACK_NAME_SIZE, ANIMATION_METADATA_VERSION, SPRITESHEET_METADATA_SIZE, } from '../core/constants.js';
|
|
3
3
|
import { TextureFilterMode } from '../core/types.js';
|
|
4
4
|
// ─── Texture Metadata ───────────────────────────────────────────────────────
|
|
5
5
|
export function serializeTextureMetadata(meta) {
|
|
@@ -361,6 +361,28 @@ export function deserializeSkinnedMeshMetadata(data) {
|
|
|
361
361
|
bones.push(deserializeBone(r));
|
|
362
362
|
return { meshGeometryCount, materialCount, nodeCount, boneCount, stringId, geometries, materials, nodes, meshIndices, bones };
|
|
363
363
|
}
|
|
364
|
+
// ─── SpriteSheet Metadata ────────────────────────────────────────────────────
|
|
365
|
+
export function serializeSpriteSheetMetadata(meta) {
|
|
366
|
+
const w = new BinaryWriter(SPRITESHEET_METADATA_SIZE);
|
|
367
|
+
w.writeFixedString(meta.stringId, STRING_ID_SIZE);
|
|
368
|
+
w.writeFixedString(meta.textureId, STRING_ID_SIZE);
|
|
369
|
+
w.writeUint32(meta.rows);
|
|
370
|
+
w.writeUint32(meta.columns);
|
|
371
|
+
w.writeUint32(meta.frameCount);
|
|
372
|
+
w.writeFloat32(meta.frameRate);
|
|
373
|
+
return w.getUint8Array();
|
|
374
|
+
}
|
|
375
|
+
export function deserializeSpriteSheetMetadata(data) {
|
|
376
|
+
const r = new BinaryReader(data);
|
|
377
|
+
return {
|
|
378
|
+
stringId: r.readFixedString(STRING_ID_SIZE),
|
|
379
|
+
textureId: r.readFixedString(STRING_ID_SIZE),
|
|
380
|
+
rows: r.readUint32(),
|
|
381
|
+
columns: r.readUint32(),
|
|
382
|
+
frameCount: r.readUint32(),
|
|
383
|
+
frameRate: r.readFloat32(),
|
|
384
|
+
};
|
|
385
|
+
}
|
|
364
386
|
// ─── Metadata Wrapping ──────────────────────────────────────────────────────
|
|
365
387
|
export function wrapMetadata(assetMetadata, tags) {
|
|
366
388
|
const tagCsv = tags.length > 0 ? tags.join(',') + '\0' : '\0';
|
package/dist/node-fs.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export interface ScanResult {
|
|
|
14
14
|
sourceFiles: FileSnapshot[];
|
|
15
15
|
metaFiles: FileSnapshot[];
|
|
16
16
|
matFiles: FileSnapshot[];
|
|
17
|
+
spritesheetFiles: FileSnapshot[];
|
|
17
18
|
folders: string[];
|
|
18
19
|
}
|
|
19
20
|
export declare function scanDirectory(basePath: string): Promise<ScanResult>;
|
package/dist/node-fs.js
CHANGED
|
@@ -98,15 +98,19 @@ function isMetaFile(name) {
|
|
|
98
98
|
function isMatFile(name) {
|
|
99
99
|
return name.endsWith('.stowmat');
|
|
100
100
|
}
|
|
101
|
+
function isSpritesheetFile(name) {
|
|
102
|
+
return name.endsWith('.stowspritesheet');
|
|
103
|
+
}
|
|
101
104
|
export async function scanDirectory(basePath) {
|
|
102
105
|
const sourceFiles = [];
|
|
103
106
|
const metaFiles = [];
|
|
104
107
|
const matFiles = [];
|
|
108
|
+
const spritesheetFiles = [];
|
|
105
109
|
const folders = [];
|
|
106
|
-
await walkDirectory(basePath, '', sourceFiles, metaFiles, matFiles, folders);
|
|
107
|
-
return { sourceFiles, metaFiles, matFiles, folders };
|
|
110
|
+
await walkDirectory(basePath, '', sourceFiles, metaFiles, matFiles, spritesheetFiles, folders);
|
|
111
|
+
return { sourceFiles, metaFiles, matFiles, spritesheetFiles, folders };
|
|
108
112
|
}
|
|
109
|
-
async function walkDirectory(basePath, prefix, sourceFiles, metaFiles, matFiles, folders) {
|
|
113
|
+
async function walkDirectory(basePath, prefix, sourceFiles, metaFiles, matFiles, spritesheetFiles, folders) {
|
|
110
114
|
const dirPath = prefix ? path.join(basePath, prefix) : basePath;
|
|
111
115
|
let entries;
|
|
112
116
|
try {
|
|
@@ -123,7 +127,7 @@ async function walkDirectory(basePath, prefix, sourceFiles, metaFiles, matFiles,
|
|
|
123
127
|
if (entry.name.endsWith('.children'))
|
|
124
128
|
continue;
|
|
125
129
|
folders.push(relativePath);
|
|
126
|
-
await walkDirectory(basePath, relativePath, sourceFiles, metaFiles, matFiles, folders);
|
|
130
|
+
await walkDirectory(basePath, relativePath, sourceFiles, metaFiles, matFiles, spritesheetFiles, folders);
|
|
127
131
|
}
|
|
128
132
|
else if (entry.isFile()) {
|
|
129
133
|
const fullPath = path.join(basePath, relativePath);
|
|
@@ -145,6 +149,9 @@ async function walkDirectory(basePath, prefix, sourceFiles, metaFiles, matFiles,
|
|
|
145
149
|
else if (isMatFile(entry.name)) {
|
|
146
150
|
matFiles.push(snapshot);
|
|
147
151
|
}
|
|
152
|
+
else if (isSpritesheetFile(entry.name)) {
|
|
153
|
+
spritesheetFiles.push(snapshot);
|
|
154
|
+
}
|
|
148
155
|
else if (isSourceFile(entry.name)) {
|
|
149
156
|
sourceFiles.push(snapshot);
|
|
150
157
|
}
|
package/dist/orchestrator.d.ts
CHANGED
package/dist/orchestrator.js
CHANGED
|
@@ -8,6 +8,7 @@ import { readProjectConfig, scanDirectory, readFile, getFileSnapshot, probeImage
|
|
|
8
8
|
import { detectAssetType, readStowmeta, writeStowmeta, stowmetaToAssetSettings, generateDefaultStowmeta, glbChildToAssetSettings, generateDefaultGlbChild, } from './app/stowmeta-io.js';
|
|
9
9
|
import { parseGlb, pbrToMaterialConfig } from './encoders/glb-loader.js';
|
|
10
10
|
import { readStowmat, stowmatToMaterialConfig } from './app/stowmat-io.js';
|
|
11
|
+
import { readStowSpriteSheet, stowSpriteSheetToConfig } from './app/stowspritesheet-io.js';
|
|
11
12
|
import { readCacheBlobs, writeCacheBlobs, buildCacheStamp, isCacheValid, } from './app/process-cache.js';
|
|
12
13
|
import { buildPack, processExtractedAnimations, validatePackDependencies } from './pipeline.js';
|
|
13
14
|
import { WorkerPool } from './workers/worker-pool.js';
|
|
@@ -37,8 +38,9 @@ export async function scanProject(projectDir, opts) {
|
|
|
37
38
|
sourceFiles: scan.sourceFiles.length,
|
|
38
39
|
metaFiles: scan.metaFiles.length,
|
|
39
40
|
matFiles: scan.matFiles.length,
|
|
41
|
+
spritesheetFiles: scan.spritesheetFiles.length,
|
|
40
42
|
newFiles,
|
|
41
|
-
totalAssets: scan.sourceFiles.length + scan.matFiles.length,
|
|
43
|
+
totalAssets: scan.sourceFiles.length + scan.matFiles.length + scan.spritesheetFiles.length,
|
|
42
44
|
};
|
|
43
45
|
}
|
|
44
46
|
// ─── Full Build ──────────────────────────────────────────────────────────────
|
|
@@ -56,7 +58,7 @@ export async function fullBuild(projectDir, opts) {
|
|
|
56
58
|
// 1. Scan
|
|
57
59
|
const scan = await scanDirectory(config.srcArtDir);
|
|
58
60
|
if (verbose)
|
|
59
|
-
console.log(`Found ${scan.sourceFiles.length} source files, ${scan.matFiles.length} materials`);
|
|
61
|
+
console.log(`Found ${scan.sourceFiles.length} source files, ${scan.matFiles.length} materials, ${scan.spritesheetFiles.length} spritesheets`);
|
|
60
62
|
// 2. Build asset list
|
|
61
63
|
const assets = [];
|
|
62
64
|
const assetsById = new Map();
|
|
@@ -139,6 +141,33 @@ export async function fullBuild(projectDir, opts) {
|
|
|
139
141
|
assets.push(asset);
|
|
140
142
|
assetsById.set(id, asset);
|
|
141
143
|
}
|
|
144
|
+
// SpriteSheets from .stowspritesheet files
|
|
145
|
+
for (const ssFile of scan.spritesheetFiles) {
|
|
146
|
+
const id = ssFile.relativePath;
|
|
147
|
+
const sheet = await readStowSpriteSheet(config.srcArtDir, id);
|
|
148
|
+
if (!sheet)
|
|
149
|
+
continue;
|
|
150
|
+
const spritesheetConfig = stowSpriteSheetToConfig(sheet);
|
|
151
|
+
const fileName = id.split('/').pop() ?? id;
|
|
152
|
+
const baseName = fileName.replace(/\.[^.]+$/, '');
|
|
153
|
+
let meta = await readStowmeta(config.srcArtDir, id);
|
|
154
|
+
if (!meta) {
|
|
155
|
+
meta = generateDefaultStowmeta(id, AssetType.SpriteSheet, config.config.defaults);
|
|
156
|
+
await writeStowmeta(config.srcArtDir, id, meta);
|
|
157
|
+
}
|
|
158
|
+
const asset = {
|
|
159
|
+
id,
|
|
160
|
+
fileName,
|
|
161
|
+
stringId: meta.stringId || baseName,
|
|
162
|
+
type: AssetType.SpriteSheet,
|
|
163
|
+
status: 'ready',
|
|
164
|
+
settings: { ...defaultAssetSettings(), spritesheetConfig, pack: meta.pack ?? 'default', tags: meta.tags ?? [] },
|
|
165
|
+
sourceSize: ssFile.size,
|
|
166
|
+
processedSize: 0,
|
|
167
|
+
};
|
|
168
|
+
assets.push(asset);
|
|
169
|
+
assetsById.set(id, asset);
|
|
170
|
+
}
|
|
142
171
|
// 2b. Extract all GLB containers (always re-parse so preserveHierarchy etc. are reflected)
|
|
143
172
|
const glbExtracts = new Map();
|
|
144
173
|
const glbContainers = assets.filter(a => a.type === AssetType.GlbContainer);
|
|
@@ -480,6 +509,7 @@ export async function showStatus(projectDir) {
|
|
|
480
509
|
console.log(`Source dir: ${config.srcArtDir}`);
|
|
481
510
|
console.log(`Source files: ${scan.sourceFiles.length}`);
|
|
482
511
|
console.log(`Material files: ${scan.matFiles.length}`);
|
|
512
|
+
console.log(`SpriteSheet files: ${scan.spritesheetFiles.length}`);
|
|
483
513
|
console.log(`Meta files: ${scan.metaFiles.length}`);
|
|
484
514
|
const packs = config.config.packs ?? [{ name: 'default' }];
|
|
485
515
|
console.log(`Packs: ${packs.map(p => p.name).join(', ')}`);
|
package/dist/pipeline.js
CHANGED
|
@@ -2,7 +2,7 @@ import { AssetType, TextureChannelFormat, TextureResize, AudioSampleRate } from
|
|
|
2
2
|
import { parseGlb } from './encoders/glb-loader.js';
|
|
3
3
|
import { dracoPresetToSettings } from './encoders/draco-encoder.js';
|
|
4
4
|
import { buildSkinnedMeshData } from './encoders/skinned-mesh-builder.js';
|
|
5
|
-
import { serializeTextureMetadata, serializeAudioMetadata, serializeMeshMetadata, serializeAnimationClipMetadata, serializeSkinnedMeshMetadata, serializeMaterialSchemaMetadata, deserializeSkinnedMeshMetadata, deserializeAnimationClipMetadata, } from './format/metadata.js';
|
|
5
|
+
import { serializeTextureMetadata, serializeAudioMetadata, serializeMeshMetadata, serializeAnimationClipMetadata, serializeSkinnedMeshMetadata, serializeMaterialSchemaMetadata, serializeSpriteSheetMetadata, deserializeSkinnedMeshMetadata, deserializeAnimationClipMetadata, } from './format/metadata.js';
|
|
6
6
|
import { StowPacker } from './format/packer.js';
|
|
7
7
|
import { BlobStore } from './app/blob-store.js';
|
|
8
8
|
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
@@ -267,6 +267,22 @@ export function validatePackDependencies(packAssets, allAssetsById) {
|
|
|
267
267
|
}
|
|
268
268
|
}
|
|
269
269
|
}
|
|
270
|
+
// SpriteSheet: check texture reference
|
|
271
|
+
if (asset.type === AssetType.SpriteSheet) {
|
|
272
|
+
const texId = asset.settings.spritesheetConfig.textureAssetId;
|
|
273
|
+
if (texId) {
|
|
274
|
+
const tex = allAssetsById.get(texId);
|
|
275
|
+
if (!tex) {
|
|
276
|
+
errors.push({ assetId: asset.id, message: `SpriteSheet "${asset.stringId}" references missing texture "${texId}"` });
|
|
277
|
+
}
|
|
278
|
+
else if (tex.settings.excluded) {
|
|
279
|
+
errors.push({ assetId: asset.id, message: `SpriteSheet "${asset.stringId}" references excluded texture "${tex.stringId}"` });
|
|
280
|
+
}
|
|
281
|
+
else if (!packIds.has(tex.id)) {
|
|
282
|
+
errors.push({ assetId: asset.id, message: `SpriteSheet "${asset.stringId}" references texture "${tex.stringId}" which is not in the same pack` });
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
270
286
|
// AnimationClip: check target mesh reference
|
|
271
287
|
if (asset.type === AssetType.AnimationClip && asset.settings.targetMeshId) {
|
|
272
288
|
const target = allAssetsById.get(asset.settings.targetMeshId);
|
|
@@ -298,6 +314,12 @@ export function buildPack(assets, assetsById) {
|
|
|
298
314
|
packer.addAsset(asset.stringId, AssetType.MaterialSchema, new Uint8Array(0), schemaBytes, asset.settings.tags);
|
|
299
315
|
continue;
|
|
300
316
|
}
|
|
317
|
+
if (asset.type === AssetType.SpriteSheet) {
|
|
318
|
+
const ssMeta = buildSpriteSheetMetadata(asset, assetsById);
|
|
319
|
+
const ssBytes = serializeSpriteSheetMetadata(ssMeta);
|
|
320
|
+
packer.addAsset(asset.stringId, AssetType.SpriteSheet, new Uint8Array(0), ssBytes, asset.settings.tags);
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
301
323
|
const processedData = BlobStore.getProcessed(asset.id);
|
|
302
324
|
if (!processedData) {
|
|
303
325
|
console.warn(`[buildPack] Skipping ${asset.id} (type=${asset.type}): no processed data in BlobStore`);
|
|
@@ -433,6 +455,20 @@ function buildMaterialSchemaMetadata(asset, assetsById) {
|
|
|
433
455
|
fields,
|
|
434
456
|
};
|
|
435
457
|
}
|
|
458
|
+
function buildSpriteSheetMetadata(asset, assetsById) {
|
|
459
|
+
const config = asset.settings.spritesheetConfig;
|
|
460
|
+
const textureAsset = config.textureAssetId
|
|
461
|
+
? assetsById.get(config.textureAssetId)
|
|
462
|
+
: undefined;
|
|
463
|
+
return {
|
|
464
|
+
stringId: asset.stringId,
|
|
465
|
+
textureId: textureAsset?.stringId ?? '',
|
|
466
|
+
rows: config.rows,
|
|
467
|
+
columns: config.columns,
|
|
468
|
+
frameCount: config.frameCount,
|
|
469
|
+
frameRate: config.frameRate,
|
|
470
|
+
};
|
|
471
|
+
}
|
|
436
472
|
// ─── Animation data blob builder (v2) ────────────────────────────────────────
|
|
437
473
|
export function buildAnimationDataBlobsV2(imported) {
|
|
438
474
|
const results = [];
|
package/dist/server.js
CHANGED
|
@@ -8,6 +8,7 @@ import { BlobStore } from './app/blob-store.js';
|
|
|
8
8
|
import { readProjectConfig, scanDirectory, readFile, writeFile, renameFile, deleteFile, getFileSnapshot, probeImageDimensions, } from './node-fs.js';
|
|
9
9
|
import { detectAssetType, readStowmeta, writeStowmeta, stowmetaToAssetSettings, assetSettingsToStowmeta, generateDefaultStowmeta, glbChildToAssetSettings, generateDefaultGlbChild, writeGlbChildSettings, } from './app/stowmeta-io.js';
|
|
10
10
|
import { readStowmat, writeStowmat, stowmatToMaterialConfig, materialConfigToStowmat } from './app/stowmat-io.js';
|
|
11
|
+
import { readStowSpriteSheet, writeStowSpriteSheet, stowSpriteSheetToConfig, spritesheetConfigToStowSpriteSheet } from './app/stowspritesheet-io.js';
|
|
11
12
|
import { readCacheBlobs, writeCacheBlobs, buildCacheStamp, isCacheValid, deleteCacheFile, } from './app/process-cache.js';
|
|
12
13
|
import { buildPack, validatePackDependencies, processExtractedAnimations } from './pipeline.js';
|
|
13
14
|
import { syncRuntimeAssets } from './sync-runtime-assets.js';
|
|
@@ -688,6 +689,33 @@ async function openProject(projectDir) {
|
|
|
688
689
|
processedSize: 0,
|
|
689
690
|
});
|
|
690
691
|
}
|
|
692
|
+
// SpriteSheets from .stowspritesheet files
|
|
693
|
+
for (const ssFile of scan.spritesheetFiles) {
|
|
694
|
+
const id = ssFile.relativePath;
|
|
695
|
+
const sheet = await readStowSpriteSheet(projectConfig.srcArtDir, id);
|
|
696
|
+
const fileName = id.split('/').pop() ?? id;
|
|
697
|
+
const baseName = fileName.replace(/\.[^.]+$/, '');
|
|
698
|
+
let meta = await readStowmeta(projectConfig.srcArtDir, id);
|
|
699
|
+
if (!meta) {
|
|
700
|
+
meta = generateDefaultStowmeta(id, AssetType.SpriteSheet, projectConfig.config.defaults);
|
|
701
|
+
await writeStowmeta(projectConfig.srcArtDir, id, meta);
|
|
702
|
+
}
|
|
703
|
+
const spritesheetConfig = sheet ? stowSpriteSheetToConfig(sheet) : { textureAssetId: null, rows: 1, columns: 1, frameCount: 1, frameRate: 12 };
|
|
704
|
+
const settings = defaultAssetSettings();
|
|
705
|
+
settings.spritesheetConfig = spritesheetConfig;
|
|
706
|
+
settings.pack = meta.pack ?? 'default';
|
|
707
|
+
settings.tags = meta.tags ?? [];
|
|
708
|
+
assets.push({
|
|
709
|
+
id,
|
|
710
|
+
fileName: baseName,
|
|
711
|
+
stringId: meta.stringId || baseName,
|
|
712
|
+
type: AssetType.SpriteSheet,
|
|
713
|
+
status: 'ready',
|
|
714
|
+
settings,
|
|
715
|
+
sourceSize: ssFile.size,
|
|
716
|
+
processedSize: 0,
|
|
717
|
+
});
|
|
718
|
+
}
|
|
691
719
|
console.log(`[server] Opened: ${projectConfig.projectName} (${assets.length} assets, ${folders.length} folders)`);
|
|
692
720
|
}
|
|
693
721
|
// ─── Process single asset ─────────────────────────────────────────────────
|
|
@@ -953,6 +981,7 @@ async function handleRequest(req, res, staticApps) {
|
|
|
953
981
|
const diskFiles = new Map([
|
|
954
982
|
...scan.sourceFiles.map(f => [f.relativePath, f]),
|
|
955
983
|
...scan.matFiles.map(f => [f.relativePath, f]),
|
|
984
|
+
...scan.spritesheetFiles.map(f => [f.relativePath, f]),
|
|
956
985
|
]);
|
|
957
986
|
const diskIds = new Set(diskFiles.keys());
|
|
958
987
|
// Check for added/removed files
|
|
@@ -964,7 +993,7 @@ async function handleRequest(req, res, staticApps) {
|
|
|
964
993
|
const modifiedIds = [];
|
|
965
994
|
if (!changed) {
|
|
966
995
|
for (const asset of currentAssets) {
|
|
967
|
-
if (asset.type === AssetType.MaterialSchema)
|
|
996
|
+
if (asset.type === AssetType.MaterialSchema || asset.type === AssetType.SpriteSheet)
|
|
968
997
|
continue;
|
|
969
998
|
const diskFile = diskFiles.get(asset.id);
|
|
970
999
|
if (diskFile && asset.sourceSize > 0 && diskFile.size !== asset.sourceSize) {
|
|
@@ -1154,6 +1183,10 @@ async function handleRequest(req, res, staticApps) {
|
|
|
1154
1183
|
const stowmat = materialConfigToStowmat(merged.materialConfig);
|
|
1155
1184
|
await writeStowmat(projectConfig.srcArtDir, id, stowmat);
|
|
1156
1185
|
}
|
|
1186
|
+
if (asset.type === AssetType.SpriteSheet && body.settings.spritesheetConfig) {
|
|
1187
|
+
const sheet = spritesheetConfigToStowSpriteSheet(merged.spritesheetConfig);
|
|
1188
|
+
await writeStowSpriteSheet(projectConfig.srcArtDir, id, sheet);
|
|
1189
|
+
}
|
|
1157
1190
|
}
|
|
1158
1191
|
}
|
|
1159
1192
|
// Check if needs reprocessing
|
|
@@ -1559,6 +1592,43 @@ async function handleRequest(req, res, staticApps) {
|
|
|
1559
1592
|
json(res, { ok: true, asset });
|
|
1560
1593
|
return;
|
|
1561
1594
|
}
|
|
1595
|
+
// POST /api/create-spritesheet
|
|
1596
|
+
if (pathname === '/api/create-spritesheet' && req.method === 'POST') {
|
|
1597
|
+
if (!projectConfig) {
|
|
1598
|
+
json(res, { error: 'No project open' }, 400);
|
|
1599
|
+
return;
|
|
1600
|
+
}
|
|
1601
|
+
const body = JSON.parse(await readBody(req));
|
|
1602
|
+
const targetFolder = body.targetFolder ?? '';
|
|
1603
|
+
const name = body.name?.trim() || `SpriteSheet ${assets.filter(a => a.type === AssetType.SpriteSheet).length + 1}`;
|
|
1604
|
+
const baseName = `${name.replace(/\s+/g, '_')}.stowspritesheet`;
|
|
1605
|
+
const fileName = targetFolder ? `${targetFolder}/${baseName}` : baseName;
|
|
1606
|
+
const settings = defaultAssetSettings();
|
|
1607
|
+
settings.spritesheetConfig = {
|
|
1608
|
+
textureAssetId: null,
|
|
1609
|
+
rows: 1,
|
|
1610
|
+
columns: 1,
|
|
1611
|
+
frameCount: 1,
|
|
1612
|
+
frameRate: 12,
|
|
1613
|
+
};
|
|
1614
|
+
const asset = {
|
|
1615
|
+
id: fileName,
|
|
1616
|
+
fileName: name,
|
|
1617
|
+
stringId: name,
|
|
1618
|
+
type: AssetType.SpriteSheet,
|
|
1619
|
+
status: 'ready',
|
|
1620
|
+
settings,
|
|
1621
|
+
sourceSize: 0,
|
|
1622
|
+
processedSize: 0,
|
|
1623
|
+
};
|
|
1624
|
+
assets.push(asset);
|
|
1625
|
+
const stowSpriteSheet = spritesheetConfigToStowSpriteSheet(settings.spritesheetConfig);
|
|
1626
|
+
await writeStowSpriteSheet(projectConfig.srcArtDir, fileName, stowSpriteSheet);
|
|
1627
|
+
const meta = assetSettingsToStowmeta(asset);
|
|
1628
|
+
await writeStowmeta(projectConfig.srcArtDir, fileName, meta);
|
|
1629
|
+
json(res, { ok: true, asset });
|
|
1630
|
+
return;
|
|
1631
|
+
}
|
|
1562
1632
|
// POST /api/create-folder
|
|
1563
1633
|
if (pathname === '/api/create-folder' && req.method === 'POST') {
|
|
1564
1634
|
if (!projectConfig) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@series-inc/stowkit-cli",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.40",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"stowkit": "./dist/cli.js"
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@google/genai": "^1.46.0",
|
|
22
22
|
"@series-inc/stowkit-editor": "^0.1.8",
|
|
23
|
-
"@series-inc/stowkit-packer-gui": "^0.1.
|
|
23
|
+
"@series-inc/stowkit-packer-gui": "^0.1.30",
|
|
24
24
|
"@strangeape/ffmpeg-audio-wasm": "^0.1.0",
|
|
25
25
|
"draco3d": "^1.5.7",
|
|
26
26
|
"fbx-parser": "^2.1.3",
|