unity-agentic-tools 0.3.1 → 0.3.2
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 +1 -1
- package/dist/cli.js +1444 -282
- package/dist/index.js +570 -74
- package/native/index.d.ts +10 -1
- package/native/index.js +2 -1
- package/native/unity-file-tools.darwin-arm64.node +0 -0
- package/native/unity-file-tools.darwin-x64.node +0 -0
- package/native/unity-file-tools.linux-x64-gnu.node +0 -0
- package/native/unity-file-tools.win32-x64-msvc.node +0 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2170,6 +2170,7 @@ __export(exports_scanner, {
|
|
|
2170
2170
|
getNativeExtractCsharpTypes: () => getNativeExtractCsharpTypes,
|
|
2171
2171
|
getNativeBuildTypeRegistry: () => getNativeBuildTypeRegistry,
|
|
2172
2172
|
getNativeBuildPackageGuidCache: () => getNativeBuildPackageGuidCache,
|
|
2173
|
+
getNativeBuildLocalPackageGuidCache: () => getNativeBuildLocalPackageGuidCache,
|
|
2173
2174
|
getNativeBuildGuidCache: () => getNativeBuildGuidCache,
|
|
2174
2175
|
UnityScanner: () => UnityScanner
|
|
2175
2176
|
});
|
|
@@ -2250,13 +2251,16 @@ function getNativeExtractDllTypes() {
|
|
|
2250
2251
|
function getNativeBuildPackageGuidCache() {
|
|
2251
2252
|
return nativeBuildPackageGuidCache;
|
|
2252
2253
|
}
|
|
2254
|
+
function getNativeBuildLocalPackageGuidCache() {
|
|
2255
|
+
return nativeBuildLocalPackageGuidCache;
|
|
2256
|
+
}
|
|
2253
2257
|
function getNativeExtractSerializedFields() {
|
|
2254
2258
|
return nativeExtractSerializedFields;
|
|
2255
2259
|
}
|
|
2256
2260
|
function getNativeExtractDllFields() {
|
|
2257
2261
|
return nativeExtractDllFields;
|
|
2258
2262
|
}
|
|
2259
|
-
var import_module, import_fs, import_path, __dirname = "/home/runner/work/unity-agentic-tools/unity-agentic-tools/unity-agentic-tools/src", RustScanner = null, nativeModuleError = null, nativeWalkProjectFiles = null, nativeGrepProject = null, nativeBuildGuidCache = null, nativeExtractCsharpTypes = null, nativeBuildTypeRegistry = null, nativeExtractDllTypes = null, nativeBuildPackageGuidCache = null, nativeExtractSerializedFields = null, nativeExtractDllFields = null;
|
|
2263
|
+
var import_module, import_fs, import_path, __dirname = "/home/runner/work/unity-agentic-tools/unity-agentic-tools/unity-agentic-tools/src", RustScanner = null, nativeModuleError = null, nativeWalkProjectFiles = null, nativeGrepProject = null, nativeBuildGuidCache = null, nativeExtractCsharpTypes = null, nativeBuildTypeRegistry = null, nativeExtractDllTypes = null, nativeBuildPackageGuidCache = null, nativeBuildLocalPackageGuidCache = null, nativeExtractSerializedFields = null, nativeExtractDllFields = null;
|
|
2260
2264
|
var init_scanner = __esm(() => {
|
|
2261
2265
|
import_module = require("module");
|
|
2262
2266
|
import_fs = require("fs");
|
|
@@ -2280,6 +2284,7 @@ var init_scanner = __esm(() => {
|
|
|
2280
2284
|
nativeBuildTypeRegistry = rustModule.buildTypeRegistry || null;
|
|
2281
2285
|
nativeExtractDllTypes = rustModule.extractDllTypes || null;
|
|
2282
2286
|
nativeBuildPackageGuidCache = rustModule.buildPackageGuidCache || null;
|
|
2287
|
+
nativeBuildLocalPackageGuidCache = rustModule.buildLocalPackageGuidCache || null;
|
|
2283
2288
|
nativeExtractSerializedFields = rustModule.extractSerializedFields || null;
|
|
2284
2289
|
nativeExtractDllFields = rustModule.extractDllFields || null;
|
|
2285
2290
|
} catch (err) {
|
|
@@ -2294,7 +2299,7 @@ var require_package = __commonJS((exports2, module2) => {
|
|
|
2294
2299
|
module2.exports = {
|
|
2295
2300
|
name: "unity-agentic-tools",
|
|
2296
2301
|
packageManager: "bun@latest",
|
|
2297
|
-
version: "0.3.
|
|
2302
|
+
version: "0.3.2",
|
|
2298
2303
|
description: "Fast, token-efficient Unity YAML parser for AI agents",
|
|
2299
2304
|
exports: {
|
|
2300
2305
|
".": {
|
|
@@ -2386,6 +2391,7 @@ var CONFIG_DIR = ".unity-agentic";
|
|
|
2386
2391
|
var CONFIG_FILE = "config.json";
|
|
2387
2392
|
var GUID_CACHE_FILE = "guid-cache.json";
|
|
2388
2393
|
var PACKAGE_CACHE_FILE = "package-cache.json";
|
|
2394
|
+
var LOCAL_PACKAGE_CACHE_FILE = "local-package-cache.json";
|
|
2389
2395
|
var TYPE_REGISTRY_FILE = "type-registry.json";
|
|
2390
2396
|
var DOC_INDEX_FILE = "doc-index.json";
|
|
2391
2397
|
function setup(options = {}) {
|
|
@@ -2429,6 +2435,17 @@ function setup(options = {}) {
|
|
|
2429
2435
|
packageGuidCount = Object.keys(packageCache).length;
|
|
2430
2436
|
} catch {}
|
|
2431
2437
|
}
|
|
2438
|
+
const nativeLocalPkgBuild = getNativeBuildLocalPackageGuidCache();
|
|
2439
|
+
if (nativeLocalPkgBuild) {
|
|
2440
|
+
try {
|
|
2441
|
+
const localPkgCache = nativeLocalPkgBuild(projectPath);
|
|
2442
|
+
const localPkgCount = Object.keys(localPkgCache).length;
|
|
2443
|
+
if (localPkgCount > 0) {
|
|
2444
|
+
const localPkgCachePath = import_path2.join(configPath, LOCAL_PACKAGE_CACHE_FILE);
|
|
2445
|
+
import_fs2.writeFileSync(localPkgCachePath, JSON.stringify(localPkgCache, null, 2));
|
|
2446
|
+
}
|
|
2447
|
+
} catch {}
|
|
2448
|
+
}
|
|
2432
2449
|
let typeRegistryCreated = false;
|
|
2433
2450
|
let typeCount;
|
|
2434
2451
|
const nativeRegistryBuild = getNativeBuildTypeRegistry();
|
|
@@ -2578,7 +2595,7 @@ function removeDirectoryRecursive(dir) {
|
|
|
2578
2595
|
}
|
|
2579
2596
|
|
|
2580
2597
|
// src/cmd-create.ts
|
|
2581
|
-
var
|
|
2598
|
+
var import_fs16 = require("fs");
|
|
2582
2599
|
var import_path7 = require("path");
|
|
2583
2600
|
var import_crypto2 = require("crypto");
|
|
2584
2601
|
|
|
@@ -2622,31 +2639,44 @@ function atomicWrite(filePath, content) {
|
|
|
2622
2639
|
};
|
|
2623
2640
|
}
|
|
2624
2641
|
}
|
|
2625
|
-
const
|
|
2642
|
+
const suffix = `${process.pid}-${Math.random().toString(36).slice(2, 8)}`;
|
|
2643
|
+
const tmpPath = `${filePath}.${suffix}.tmp`;
|
|
2644
|
+
const bakPath = `${filePath}.${suffix}.bak`;
|
|
2645
|
+
let bakCreated = false;
|
|
2626
2646
|
try {
|
|
2627
2647
|
import_fs4.writeFileSync(tmpPath, content, "utf-8");
|
|
2628
|
-
if (import_fs4.existsSync(filePath)) {
|
|
2629
|
-
import_fs4.renameSync(filePath, `${filePath}.bak`);
|
|
2630
|
-
}
|
|
2631
|
-
import_fs4.renameSync(tmpPath, filePath);
|
|
2632
2648
|
try {
|
|
2633
|
-
|
|
2634
|
-
|
|
2649
|
+
import_fs4.renameSync(filePath, bakPath);
|
|
2650
|
+
bakCreated = true;
|
|
2651
|
+
} catch (err) {
|
|
2652
|
+
if (is_enoent(err)) {
|
|
2653
|
+
bakCreated = false;
|
|
2654
|
+
} else {
|
|
2655
|
+
throw err;
|
|
2635
2656
|
}
|
|
2636
|
-
}
|
|
2657
|
+
}
|
|
2658
|
+
import_fs4.renameSync(tmpPath, filePath);
|
|
2659
|
+
if (bakCreated) {
|
|
2660
|
+
try {
|
|
2661
|
+
import_fs4.unlinkSync(bakPath);
|
|
2662
|
+
} catch {}
|
|
2663
|
+
}
|
|
2637
2664
|
return {
|
|
2638
2665
|
success: true,
|
|
2639
2666
|
file_path: filePath,
|
|
2640
2667
|
bytes_written: Buffer.byteLength(content, "utf-8")
|
|
2641
2668
|
};
|
|
2642
2669
|
} catch (error) {
|
|
2643
|
-
if (
|
|
2670
|
+
if (bakCreated) {
|
|
2644
2671
|
try {
|
|
2645
|
-
import_fs4.renameSync(
|
|
2672
|
+
import_fs4.renameSync(bakPath, filePath);
|
|
2646
2673
|
} catch (restoreError) {
|
|
2647
2674
|
console.error("Failed to restore backup:", restoreError);
|
|
2648
2675
|
}
|
|
2649
2676
|
}
|
|
2677
|
+
try {
|
|
2678
|
+
import_fs4.unlinkSync(tmpPath);
|
|
2679
|
+
} catch {}
|
|
2650
2680
|
return {
|
|
2651
2681
|
success: false,
|
|
2652
2682
|
file_path: filePath,
|
|
@@ -2654,6 +2684,12 @@ function atomicWrite(filePath, content) {
|
|
|
2654
2684
|
};
|
|
2655
2685
|
}
|
|
2656
2686
|
}
|
|
2687
|
+
function is_enoent(err) {
|
|
2688
|
+
return err instanceof Error && "code" in err && err.code === "ENOENT";
|
|
2689
|
+
}
|
|
2690
|
+
function normalize_property_path(path) {
|
|
2691
|
+
return path.replace(/\.Array\.data\.(\d+)/g, ".Array.data[$1]");
|
|
2692
|
+
}
|
|
2657
2693
|
function is_match_all(pattern) {
|
|
2658
2694
|
return pattern === "*" || pattern === "." || pattern === "**" || pattern === ".*";
|
|
2659
2695
|
}
|
|
@@ -3032,6 +3068,31 @@ function extractGuidFromMeta(metaPath) {
|
|
|
3032
3068
|
return null;
|
|
3033
3069
|
}
|
|
3034
3070
|
}
|
|
3071
|
+
function resolve_source_prefab(doc, file_path, project_path) {
|
|
3072
|
+
const pi_blocks = doc.find_by_class_id(1001);
|
|
3073
|
+
if (pi_blocks.length === 0)
|
|
3074
|
+
return null;
|
|
3075
|
+
const pi_block = pi_blocks[0];
|
|
3076
|
+
const source_match = pi_block.raw.match(/m_SourcePrefab:[ \t]*\{[^}]*guid:[ \t]*([a-f0-9]{32})/);
|
|
3077
|
+
if (!source_match)
|
|
3078
|
+
return null;
|
|
3079
|
+
const source_guid = source_match[1];
|
|
3080
|
+
const resolved_project = project_path || find_unity_project_root(path.dirname(file_path));
|
|
3081
|
+
if (!resolved_project)
|
|
3082
|
+
return null;
|
|
3083
|
+
const cache = load_guid_cache_for_file(file_path, resolved_project);
|
|
3084
|
+
if (!cache)
|
|
3085
|
+
return null;
|
|
3086
|
+
const source_path = cache.resolve_absolute(source_guid);
|
|
3087
|
+
if (!source_path || !import_fs6.existsSync(source_path))
|
|
3088
|
+
return null;
|
|
3089
|
+
return {
|
|
3090
|
+
source_guid,
|
|
3091
|
+
source_path,
|
|
3092
|
+
prefab_instance_id: pi_block.file_id,
|
|
3093
|
+
prefab_instance_block: pi_block
|
|
3094
|
+
};
|
|
3095
|
+
}
|
|
3035
3096
|
function resolveScriptGuid(script, projectPath) {
|
|
3036
3097
|
if (/^[a-f0-9]{32}$/i.test(script)) {
|
|
3037
3098
|
return { guid: script.toLowerCase(), path: null };
|
|
@@ -3081,27 +3142,122 @@ function resolveScriptGuid(script, projectPath) {
|
|
|
3081
3142
|
return false;
|
|
3082
3143
|
return true;
|
|
3083
3144
|
});
|
|
3084
|
-
if (matches.length === 1
|
|
3085
|
-
|
|
3145
|
+
if (matches.length === 1) {
|
|
3146
|
+
if (matches[0].guid) {
|
|
3147
|
+
return { guid: matches[0].guid, path: matches[0].filePath };
|
|
3148
|
+
}
|
|
3149
|
+
if (matches[0].filePath && projectPath) {
|
|
3150
|
+
const fullFilePath = path.isAbsolute(matches[0].filePath) ? matches[0].filePath : path.join(projectPath, matches[0].filePath);
|
|
3151
|
+
const metaPath = fullFilePath + ".meta";
|
|
3152
|
+
if (import_fs6.existsSync(metaPath)) {
|
|
3153
|
+
const guid = extractGuidFromMeta(metaPath);
|
|
3154
|
+
if (guid)
|
|
3155
|
+
return { guid, path: matches[0].filePath };
|
|
3156
|
+
}
|
|
3157
|
+
if (matches[0].filePath.startsWith("Packages/")) {
|
|
3158
|
+
const pkgPath = path.join(projectPath, matches[0].filePath);
|
|
3159
|
+
const pkgMetaPath = pkgPath + ".meta";
|
|
3160
|
+
if (import_fs6.existsSync(pkgMetaPath)) {
|
|
3161
|
+
const guid = extractGuidFromMeta(pkgMetaPath);
|
|
3162
|
+
if (guid)
|
|
3163
|
+
return { guid, path: matches[0].filePath };
|
|
3164
|
+
}
|
|
3165
|
+
}
|
|
3166
|
+
if (matches[0].filePath?.endsWith(".dll")) {
|
|
3167
|
+
const dllBasename = path.basename(matches[0].filePath).toLowerCase();
|
|
3168
|
+
for (const cacheName of ["package-cache.json", "local-package-cache.json"]) {
|
|
3169
|
+
const cachePath = path.join(projectPath, ".unity-agentic", cacheName);
|
|
3170
|
+
if (!import_fs6.existsSync(cachePath))
|
|
3171
|
+
continue;
|
|
3172
|
+
try {
|
|
3173
|
+
const cache = JSON.parse(import_fs6.readFileSync(cachePath, "utf-8"));
|
|
3174
|
+
for (const [guid, assetPath] of Object.entries(cache)) {
|
|
3175
|
+
if (assetPath.toLowerCase().endsWith(".dll") && path.basename(assetPath).toLowerCase() === dllBasename) {
|
|
3176
|
+
return { guid, path: assetPath };
|
|
3177
|
+
}
|
|
3178
|
+
}
|
|
3179
|
+
} catch {}
|
|
3180
|
+
}
|
|
3181
|
+
}
|
|
3182
|
+
}
|
|
3086
3183
|
}
|
|
3087
3184
|
if (matches.length > 1) {
|
|
3088
3185
|
const withGuid = matches.filter((m) => m.guid);
|
|
3089
3186
|
if (withGuid.length === 1) {
|
|
3090
3187
|
return { guid: withGuid[0].guid, path: withGuid[0].filePath };
|
|
3091
3188
|
}
|
|
3189
|
+
const resolvedFromMeta = matches.filter((m) => !m.guid && m.filePath).map((m) => {
|
|
3190
|
+
const fullPath = path.isAbsolute(m.filePath) ? m.filePath : path.join(projectPath, m.filePath);
|
|
3191
|
+
let guid = import_fs6.existsSync(fullPath + ".meta") ? extractGuidFromMeta(fullPath + ".meta") : null;
|
|
3192
|
+
if (!guid && m.filePath.startsWith("Packages/")) {
|
|
3193
|
+
const pkgPath = path.join(projectPath, m.filePath);
|
|
3194
|
+
if (import_fs6.existsSync(pkgPath + ".meta")) {
|
|
3195
|
+
guid = extractGuidFromMeta(pkgPath + ".meta");
|
|
3196
|
+
}
|
|
3197
|
+
}
|
|
3198
|
+
if (!guid && m.filePath?.endsWith(".dll")) {
|
|
3199
|
+
const dllBase = path.basename(m.filePath).toLowerCase();
|
|
3200
|
+
for (const cn of ["package-cache.json", "local-package-cache.json"]) {
|
|
3201
|
+
const cp = path.join(projectPath, ".unity-agentic", cn);
|
|
3202
|
+
if (!import_fs6.existsSync(cp))
|
|
3203
|
+
continue;
|
|
3204
|
+
try {
|
|
3205
|
+
const c = JSON.parse(import_fs6.readFileSync(cp, "utf-8"));
|
|
3206
|
+
for (const [g, p] of Object.entries(c)) {
|
|
3207
|
+
if (p.toLowerCase().endsWith(".dll") && path.basename(p).toLowerCase() === dllBase) {
|
|
3208
|
+
guid = g;
|
|
3209
|
+
break;
|
|
3210
|
+
}
|
|
3211
|
+
}
|
|
3212
|
+
} catch {}
|
|
3213
|
+
if (guid)
|
|
3214
|
+
break;
|
|
3215
|
+
}
|
|
3216
|
+
}
|
|
3217
|
+
return guid ? { guid, path: m.filePath } : null;
|
|
3218
|
+
}).filter((r) => r !== null);
|
|
3219
|
+
const allResolved = [...withGuid.map((m) => ({ guid: m.guid, path: m.filePath })), ...resolvedFromMeta];
|
|
3220
|
+
if (allResolved.length === 1) {
|
|
3221
|
+
return allResolved[0];
|
|
3222
|
+
}
|
|
3223
|
+
if (allResolved.length > 1) {
|
|
3224
|
+
const pkgCachePaths = [
|
|
3225
|
+
path.join(projectPath, ".unity-agentic", "package-cache.json"),
|
|
3226
|
+
path.join(projectPath, ".unity-agentic", "local-package-cache.json")
|
|
3227
|
+
];
|
|
3228
|
+
for (const cachePath of pkgCachePaths) {
|
|
3229
|
+
if (!import_fs6.existsSync(cachePath))
|
|
3230
|
+
continue;
|
|
3231
|
+
try {
|
|
3232
|
+
const cache = JSON.parse(import_fs6.readFileSync(cachePath, "utf-8"));
|
|
3233
|
+
const inCache = allResolved.filter((r) => (r.guid in cache));
|
|
3234
|
+
if (inCache.length === 1)
|
|
3235
|
+
return inCache[0];
|
|
3236
|
+
} catch {}
|
|
3237
|
+
}
|
|
3238
|
+
const paths = allResolved.map((m) => m.path).join(", ");
|
|
3239
|
+
throw new Error(`Ambiguous type "${script}": found ${allResolved.length} matches (${paths}). ` + `Use a qualified name (e.g., "Namespace.${targetName}") or provide the full path.`);
|
|
3240
|
+
}
|
|
3092
3241
|
}
|
|
3093
3242
|
} catch {}
|
|
3094
3243
|
}
|
|
3095
|
-
const
|
|
3096
|
-
|
|
3244
|
+
const scriptNameLower = script.toLowerCase().replace(/\.cs$/, "");
|
|
3245
|
+
const dotIdx = scriptNameLower.lastIndexOf(".");
|
|
3246
|
+
const classNameOnly = dotIdx > 0 ? scriptNameLower.substring(dotIdx + 1) : null;
|
|
3247
|
+
const cachePaths = [
|
|
3248
|
+
path.join(projectPath, ".unity-agentic", "package-cache.json"),
|
|
3249
|
+
path.join(projectPath, ".unity-agentic", "local-package-cache.json")
|
|
3250
|
+
];
|
|
3251
|
+
for (const cachePath of cachePaths) {
|
|
3252
|
+
if (!import_fs6.existsSync(cachePath))
|
|
3253
|
+
continue;
|
|
3097
3254
|
try {
|
|
3098
|
-
const
|
|
3099
|
-
const
|
|
3100
|
-
for (const [guid, assetPath] of Object.entries(packageCache)) {
|
|
3255
|
+
const cache = JSON.parse(import_fs6.readFileSync(cachePath, "utf-8"));
|
|
3256
|
+
for (const [guid, assetPath] of Object.entries(cache)) {
|
|
3101
3257
|
if (!assetPath.endsWith(".cs"))
|
|
3102
3258
|
continue;
|
|
3103
3259
|
const fileName = path.basename(assetPath, ".cs").toLowerCase();
|
|
3104
|
-
if (fileName === scriptNameLower) {
|
|
3260
|
+
if (fileName === scriptNameLower || classNameOnly && fileName === classNameOnly) {
|
|
3105
3261
|
return { guid, path: assetPath };
|
|
3106
3262
|
}
|
|
3107
3263
|
}
|
|
@@ -3152,6 +3308,8 @@ function resolve_script_with_fields(script, project_path) {
|
|
|
3152
3308
|
result.fields = chosen.fields;
|
|
3153
3309
|
result.base_class = chosen.baseClass ?? undefined;
|
|
3154
3310
|
result.kind = chosen.kind;
|
|
3311
|
+
result.namespace = chosen.namespace ?? undefined;
|
|
3312
|
+
result.class_name = chosen.name;
|
|
3155
3313
|
}
|
|
3156
3314
|
} else {
|
|
3157
3315
|
result.extraction_error = "Native extractDllFields function not available";
|
|
@@ -3347,6 +3505,16 @@ function yaml_default_for_type(csharp_type, version) {
|
|
|
3347
3505
|
function generate_field_yaml(fields, version, indent = " ") {
|
|
3348
3506
|
const lines = [];
|
|
3349
3507
|
for (const field of fields) {
|
|
3508
|
+
if (field.hasSerializeReference) {
|
|
3509
|
+
const t = field.typeName;
|
|
3510
|
+
if (t.endsWith("[]") || t.startsWith("List<") && t.endsWith(">")) {
|
|
3511
|
+
lines.push(`${indent}${field.name}: []`);
|
|
3512
|
+
} else {
|
|
3513
|
+
lines.push(`${indent}${field.name}:`);
|
|
3514
|
+
lines.push(`${indent} rid: 0`);
|
|
3515
|
+
}
|
|
3516
|
+
continue;
|
|
3517
|
+
}
|
|
3350
3518
|
const default_value = yaml_default_for_type(field.typeName, version);
|
|
3351
3519
|
if (default_value === null) {
|
|
3352
3520
|
continue;
|
|
@@ -3390,6 +3558,17 @@ function parse_header(raw) {
|
|
|
3390
3558
|
function escape_regex(str) {
|
|
3391
3559
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3392
3560
|
}
|
|
3561
|
+
function yaml_quote_if_needed(value) {
|
|
3562
|
+
if (value === "")
|
|
3563
|
+
return value;
|
|
3564
|
+
if (value.startsWith("{") && value.endsWith("}") || value.startsWith("[") && value.endsWith("]")) {
|
|
3565
|
+
return value;
|
|
3566
|
+
}
|
|
3567
|
+
if (value.includes(": ") || value.includes(" #") || /^[#\{\[*&!|>'"]/.test(value) || value !== value.trim()) {
|
|
3568
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
3569
|
+
}
|
|
3570
|
+
return value;
|
|
3571
|
+
}
|
|
3393
3572
|
|
|
3394
3573
|
class UnityBlock {
|
|
3395
3574
|
_raw;
|
|
@@ -3425,6 +3604,7 @@ class UnityBlock {
|
|
|
3425
3604
|
return this._dirty;
|
|
3426
3605
|
}
|
|
3427
3606
|
get_property(path2) {
|
|
3607
|
+
path2 = normalize_property_path(path2);
|
|
3428
3608
|
if (path2.includes("Array.data[")) {
|
|
3429
3609
|
return this._get_array_element(path2);
|
|
3430
3610
|
}
|
|
@@ -3451,13 +3631,17 @@ class UnityBlock {
|
|
|
3451
3631
|
return match ? match[1].trim() : null;
|
|
3452
3632
|
}
|
|
3453
3633
|
set_property(path2, value, object_reference) {
|
|
3634
|
+
path2 = normalize_property_path(path2);
|
|
3454
3635
|
const old_raw = this._raw;
|
|
3455
3636
|
const effective_ref = object_reference && object_reference !== "{fileID: 0}" ? object_reference : undefined;
|
|
3456
3637
|
if (!path2.includes(".") && !path2.includes("Array")) {
|
|
3457
3638
|
const prop_pattern = new RegExp(`(^\\s*${escape_regex(path2)}:\\s*)(.*)$`, "m");
|
|
3458
3639
|
if (prop_pattern.test(this._raw)) {
|
|
3459
|
-
const replacement_value = effective_ref ?? value;
|
|
3460
|
-
this._raw = this._raw.replace(prop_pattern,
|
|
3640
|
+
const replacement_value = effective_ref ?? yaml_quote_if_needed(value);
|
|
3641
|
+
this._raw = this._raw.replace(prop_pattern, (_match, prefix) => prefix + replacement_value);
|
|
3642
|
+
} else {
|
|
3643
|
+
const insert_value = effective_ref ?? yaml_quote_if_needed(value);
|
|
3644
|
+
this._insert_property(path2, insert_value);
|
|
3461
3645
|
}
|
|
3462
3646
|
return this._check_dirty(old_raw);
|
|
3463
3647
|
}
|
|
@@ -3472,8 +3656,8 @@ class UnityBlock {
|
|
|
3472
3656
|
const fields = inline_match[2];
|
|
3473
3657
|
const field_pattern = new RegExp(`(${escape_regex(sub_field)}:\\s*)([^,}]+)`);
|
|
3474
3658
|
if (field_pattern.test(fields)) {
|
|
3475
|
-
const updated_fields = fields.replace(field_pattern,
|
|
3476
|
-
this._raw = this._raw.replace(inline_pattern,
|
|
3659
|
+
const updated_fields = fields.replace(field_pattern, (_m, prefix) => prefix + value);
|
|
3660
|
+
this._raw = this._raw.replace(inline_pattern, (_m, g1, _g2, g3) => g1 + updated_fields + g3);
|
|
3477
3661
|
inline_applied = true;
|
|
3478
3662
|
}
|
|
3479
3663
|
}
|
|
@@ -3482,6 +3666,8 @@ class UnityBlock {
|
|
|
3482
3666
|
const block_result = this._resolve_block_style_path(parts, effective_value);
|
|
3483
3667
|
if (block_result !== null) {
|
|
3484
3668
|
this._raw = block_result;
|
|
3669
|
+
} else if (parts.length === 2) {
|
|
3670
|
+
this._insert_struct_property(parent_prop, sub_field, effective_value);
|
|
3485
3671
|
}
|
|
3486
3672
|
}
|
|
3487
3673
|
return this._check_dirty(old_raw);
|
|
@@ -3499,7 +3685,7 @@ class UnityBlock {
|
|
|
3499
3685
|
`).filter((l) => l.trim().startsWith("-"));
|
|
3500
3686
|
if (index < lines.length) {
|
|
3501
3687
|
const old_line = lines[index];
|
|
3502
|
-
const new_line = old_line.replace(/-\s*.*/, `- ${ref_value}`);
|
|
3688
|
+
const new_line = old_line.replace(/-\s*.*/, () => `- ${ref_value}`);
|
|
3503
3689
|
this._raw = this._raw.replace(old_line, new_line);
|
|
3504
3690
|
}
|
|
3505
3691
|
}
|
|
@@ -3508,6 +3694,44 @@ class UnityBlock {
|
|
|
3508
3694
|
}
|
|
3509
3695
|
return false;
|
|
3510
3696
|
}
|
|
3697
|
+
_insert_property(path2, value) {
|
|
3698
|
+
const alt = path2.startsWith("m_") ? path2.slice(2) : "m_" + path2;
|
|
3699
|
+
const alt_pattern = new RegExp(`^\\s*${escape_regex(alt)}:`, "m");
|
|
3700
|
+
if (alt_pattern.test(this._raw)) {
|
|
3701
|
+
return;
|
|
3702
|
+
}
|
|
3703
|
+
const indented_line = ` ${path2}: ${value}`;
|
|
3704
|
+
const eci_pattern = /^([ \t]*m_EditorClassIdentifier:[ \t]*[^\n]*)/m;
|
|
3705
|
+
const eci_match = this._raw.match(eci_pattern);
|
|
3706
|
+
if (eci_match && eci_match.index !== undefined) {
|
|
3707
|
+
const insert_after = eci_match.index + eci_match[0].length;
|
|
3708
|
+
this._raw = this._raw.slice(0, insert_after) + `
|
|
3709
|
+
` + indented_line + this._raw.slice(insert_after);
|
|
3710
|
+
return;
|
|
3711
|
+
}
|
|
3712
|
+
this._raw = this._raw.trimEnd() + `
|
|
3713
|
+
` + indented_line + `
|
|
3714
|
+
`;
|
|
3715
|
+
}
|
|
3716
|
+
_insert_struct_property(parent, child, value) {
|
|
3717
|
+
const parent_pattern = new RegExp(`^[ ]*${escape_regex(parent)}:`, "m");
|
|
3718
|
+
if (parent_pattern.test(this._raw)) {
|
|
3719
|
+
return;
|
|
3720
|
+
}
|
|
3721
|
+
const struct_block = ` ${parent}:
|
|
3722
|
+
${child}: ${value}`;
|
|
3723
|
+
const eci_pattern = /^([ \t]*m_EditorClassIdentifier:[ \t]*[^\n]*)/m;
|
|
3724
|
+
const eci_match = this._raw.match(eci_pattern);
|
|
3725
|
+
if (eci_match && eci_match.index !== undefined) {
|
|
3726
|
+
const insert_after = eci_match.index + eci_match[0].length;
|
|
3727
|
+
this._raw = this._raw.slice(0, insert_after) + `
|
|
3728
|
+
` + struct_block + this._raw.slice(insert_after);
|
|
3729
|
+
return;
|
|
3730
|
+
}
|
|
3731
|
+
this._raw = this._raw.trimEnd() + `
|
|
3732
|
+
` + struct_block + `
|
|
3733
|
+
`;
|
|
3734
|
+
}
|
|
3511
3735
|
has_property(path2) {
|
|
3512
3736
|
return this.get_property(path2) !== null;
|
|
3513
3737
|
}
|
|
@@ -3563,7 +3787,7 @@ class UnityBlock {
|
|
|
3563
3787
|
if (empty_match) {
|
|
3564
3788
|
const base_indent = empty_match[2];
|
|
3565
3789
|
const element_indent2 = base_indent + " ";
|
|
3566
|
-
this._raw = this._raw.replace(empty_pattern, `$
|
|
3790
|
+
this._raw = this._raw.replace(empty_pattern, (_m, g1) => `${g1}
|
|
3567
3791
|
${element_indent2}- ${value}`);
|
|
3568
3792
|
return this._check_dirty(old_raw);
|
|
3569
3793
|
}
|
|
@@ -4508,6 +4732,20 @@ function get_project_info(projectPath) {
|
|
|
4508
4732
|
}
|
|
4509
4733
|
|
|
4510
4734
|
// src/editor/create.ts
|
|
4735
|
+
function compute_dll_script_file_id(namespace, class_name) {
|
|
4736
|
+
const { createHash } = require("crypto");
|
|
4737
|
+
const full_name = namespace ? `${namespace}.${class_name}` : class_name;
|
|
4738
|
+
const name_bytes = Buffer.from(full_name, "utf-8");
|
|
4739
|
+
const input = Buffer.alloc(4 + name_bytes.length);
|
|
4740
|
+
input.writeInt32LE(114, 0);
|
|
4741
|
+
name_bytes.copy(input, 4);
|
|
4742
|
+
const hash = createHash("md4").update(input).digest();
|
|
4743
|
+
const a = hash.readInt32LE(0);
|
|
4744
|
+
const b = hash.readInt32LE(4);
|
|
4745
|
+
const c = hash.readInt32LE(8);
|
|
4746
|
+
const d = hash.readInt32LE(12);
|
|
4747
|
+
return a ^ b ^ c ^ d;
|
|
4748
|
+
}
|
|
4511
4749
|
function get_layer_from_parent(doc, parentTransformId) {
|
|
4512
4750
|
if (parentTransformId === "0")
|
|
4513
4751
|
return 0;
|
|
@@ -4523,7 +4761,7 @@ function get_layer_from_parent(doc, parentTransformId) {
|
|
|
4523
4761
|
const layerMatch = parentGo.raw.match(/m_Layer:\s*(\d+)/);
|
|
4524
4762
|
return layerMatch ? parseInt(layerMatch[1], 10) : 0;
|
|
4525
4763
|
}
|
|
4526
|
-
function createGameObjectYAML(gameObjectId, transformId, name, parentTransformId = 0, rootOrder = 0, layer = 0) {
|
|
4764
|
+
function createGameObjectYAML(gameObjectId, transformId, name, parentTransformId = "0", rootOrder = 0, layer = 0) {
|
|
4527
4765
|
return `--- !u!1 &${gameObjectId}
|
|
4528
4766
|
GameObject:
|
|
4529
4767
|
m_ObjectHideFlags: 0
|
|
@@ -4584,9 +4822,9 @@ function findStrippedRootTransform(doc, prefabInstanceId) {
|
|
|
4584
4822
|
for (const block of doc.blocks) {
|
|
4585
4823
|
if (block.class_id !== 4 || !block.is_stripped)
|
|
4586
4824
|
continue;
|
|
4587
|
-
const piMatch = block.raw.match(/m_PrefabInstance
|
|
4825
|
+
const piMatch = block.raw.match(/m_PrefabInstance:[ \t]*\{fileID:[ \t]*(-?\d+)\}/);
|
|
4588
4826
|
if (piMatch && piMatch[1] === prefabInstanceId) {
|
|
4589
|
-
const sourceMatch = block.raw.match(/m_CorrespondingSourceObject
|
|
4827
|
+
const sourceMatch = block.raw.match(/m_CorrespondingSourceObject:[ \t]*(\{[^}]+\})/);
|
|
4590
4828
|
if (sourceMatch) {
|
|
4591
4829
|
return {
|
|
4592
4830
|
transformId: block.file_id,
|
|
@@ -4597,6 +4835,66 @@ function findStrippedRootTransform(doc, prefabInstanceId) {
|
|
|
4597
4835
|
}
|
|
4598
4836
|
return null;
|
|
4599
4837
|
}
|
|
4838
|
+
function find_game_object_in_variant(doc, name, file_path, project_path) {
|
|
4839
|
+
const pi_blocks = doc.find_by_class_id(1001);
|
|
4840
|
+
for (const pi_block of pi_blocks) {
|
|
4841
|
+
const mod_pattern = /- target:[ \t]*(\{[^}]+\})\s*propertyPath:[ \t]*m_Name\s*value:[ \t]*([^\n]*)/g;
|
|
4842
|
+
let mod_match;
|
|
4843
|
+
while ((mod_match = mod_pattern.exec(pi_block.raw)) !== null) {
|
|
4844
|
+
const target_ref = mod_match[1];
|
|
4845
|
+
const mod_value = mod_match[2].trim();
|
|
4846
|
+
if (mod_value !== name)
|
|
4847
|
+
continue;
|
|
4848
|
+
for (const block of doc.blocks) {
|
|
4849
|
+
if (block.class_id !== 1 || !block.is_stripped)
|
|
4850
|
+
continue;
|
|
4851
|
+
const source_match = block.raw.match(/m_CorrespondingSourceObject:[ \t]*(\{[^}]+\})/);
|
|
4852
|
+
if (!source_match)
|
|
4853
|
+
continue;
|
|
4854
|
+
const normalized_source = source_match[1].replace(/\s+/g, " ");
|
|
4855
|
+
const normalized_target = target_ref.replace(/\s+/g, " ");
|
|
4856
|
+
if (normalized_source === normalized_target) {
|
|
4857
|
+
return {
|
|
4858
|
+
stripped_go_id: block.file_id,
|
|
4859
|
+
source_ref: target_ref,
|
|
4860
|
+
prefab_instance_id: pi_block.file_id
|
|
4861
|
+
};
|
|
4862
|
+
}
|
|
4863
|
+
}
|
|
4864
|
+
}
|
|
4865
|
+
}
|
|
4866
|
+
const source_info = resolve_source_prefab(doc, file_path, project_path);
|
|
4867
|
+
if (!source_info)
|
|
4868
|
+
return null;
|
|
4869
|
+
let source_doc;
|
|
4870
|
+
try {
|
|
4871
|
+
source_doc = UnityDocument.from_file(source_info.source_path);
|
|
4872
|
+
} catch {
|
|
4873
|
+
return null;
|
|
4874
|
+
}
|
|
4875
|
+
const source_gos = source_doc.find_game_objects_by_name(name);
|
|
4876
|
+
if (source_gos.length !== 1)
|
|
4877
|
+
return null;
|
|
4878
|
+
const source_go = source_gos[0];
|
|
4879
|
+
const source_go_file_id = source_go.file_id;
|
|
4880
|
+
const source_guid = source_info.source_guid;
|
|
4881
|
+
for (const block of doc.blocks) {
|
|
4882
|
+
if (block.class_id !== 1 || !block.is_stripped)
|
|
4883
|
+
continue;
|
|
4884
|
+
const source_match = block.raw.match(/m_CorrespondingSourceObject:[ \t]*\{[^}]*fileID:[ \t]*(-?\d+)[^}]*guid:[ \t]*([a-f0-9]{32})/);
|
|
4885
|
+
if (!source_match)
|
|
4886
|
+
continue;
|
|
4887
|
+
if (source_match[1] === source_go_file_id && source_match[2] === source_guid) {
|
|
4888
|
+
const source_ref = `{fileID: ${source_go_file_id}, guid: ${source_guid}, type: 3}`;
|
|
4889
|
+
return {
|
|
4890
|
+
stripped_go_id: block.file_id,
|
|
4891
|
+
source_ref,
|
|
4892
|
+
prefab_instance_id: source_info.prefab_instance_id
|
|
4893
|
+
};
|
|
4894
|
+
}
|
|
4895
|
+
}
|
|
4896
|
+
return null;
|
|
4897
|
+
}
|
|
4600
4898
|
function appendToAddedGameObjects(doc, piId, targetSourceRef, newGoId) {
|
|
4601
4899
|
const piBlock = doc.find_by_file_id(piId);
|
|
4602
4900
|
if (!piBlock)
|
|
@@ -4606,13 +4904,34 @@ function appendToAddedGameObjects(doc, piId, targetSourceRef, newGoId) {
|
|
|
4606
4904
|
insertIndex: -1
|
|
4607
4905
|
addedObject: {fileID: ${newGoId}}`;
|
|
4608
4906
|
let raw = piBlock.raw;
|
|
4609
|
-
const emptyPattern = /m_AddedGameObjects
|
|
4907
|
+
const emptyPattern = /m_AddedGameObjects:[ \t]*\[\]/;
|
|
4610
4908
|
if (emptyPattern.test(raw)) {
|
|
4611
4909
|
raw = raw.replace(emptyPattern, `m_AddedGameObjects:${entry}`);
|
|
4612
4910
|
piBlock.replace_raw(raw);
|
|
4613
4911
|
return;
|
|
4614
4912
|
}
|
|
4615
|
-
const existingPattern = /(m_AddedGameObjects
|
|
4913
|
+
const existingPattern = /(m_AddedGameObjects:[ \t]*\n(?:[ \t]+-[\s\S]*?(?=\n[ \t]+m_|$))*)/;
|
|
4914
|
+
if (existingPattern.test(raw)) {
|
|
4915
|
+
raw = raw.replace(existingPattern, `$1${entry}`);
|
|
4916
|
+
piBlock.replace_raw(raw);
|
|
4917
|
+
}
|
|
4918
|
+
}
|
|
4919
|
+
function appendToAddedComponents(doc, piId, targetSourceRef, newComponentId) {
|
|
4920
|
+
const piBlock = doc.find_by_file_id(piId);
|
|
4921
|
+
if (!piBlock)
|
|
4922
|
+
return;
|
|
4923
|
+
const entry = `
|
|
4924
|
+
- targetCorrespondingSourceObject: ${targetSourceRef}
|
|
4925
|
+
insertIndex: -1
|
|
4926
|
+
addedObject: {fileID: ${newComponentId}}`;
|
|
4927
|
+
let raw = piBlock.raw;
|
|
4928
|
+
const emptyPattern = /m_AddedComponents:[ \t]*\[\]/;
|
|
4929
|
+
if (emptyPattern.test(raw)) {
|
|
4930
|
+
raw = raw.replace(emptyPattern, `m_AddedComponents:${entry}`);
|
|
4931
|
+
piBlock.replace_raw(raw);
|
|
4932
|
+
return;
|
|
4933
|
+
}
|
|
4934
|
+
const existingPattern = /(m_AddedComponents:[ \t]*\n(?:[ \t]+-[\s\S]*?(?=\n[ \t]+m_|$))*)/;
|
|
4616
4935
|
if (existingPattern.test(raw)) {
|
|
4617
4936
|
raw = raw.replace(existingPattern, `$1${entry}`);
|
|
4618
4937
|
piBlock.replace_raw(raw);
|
|
@@ -4635,11 +4954,31 @@ var COMPONENT_DEFAULTS = {
|
|
|
4635
4954
|
m_Materials:
|
|
4636
4955
|
- {fileID: 0}`,
|
|
4637
4956
|
33: ` m_Mesh: {fileID: 0}`,
|
|
4957
|
+
50: ` m_BodyType: 0
|
|
4958
|
+
m_Mass: 1
|
|
4959
|
+
m_LinearDrag: 0
|
|
4960
|
+
m_AngularDrag: 0.05
|
|
4961
|
+
m_GravityScale: 1
|
|
4962
|
+
m_Interpolate: 0
|
|
4963
|
+
m_SleepingMode: 1
|
|
4964
|
+
m_CollisionDetection: 0`,
|
|
4638
4965
|
54: ` m_Mass: 1
|
|
4639
4966
|
m_Drag: 0
|
|
4640
4967
|
m_AngularDrag: 0.05
|
|
4641
4968
|
m_UseGravity: 1
|
|
4642
4969
|
m_IsKinematic: 0`,
|
|
4970
|
+
58: ` m_IsTrigger: 0
|
|
4971
|
+
m_Material: {fileID: 0}
|
|
4972
|
+
m_Offset: {x: 0, y: 0}
|
|
4973
|
+
m_Radius: 0.5`,
|
|
4974
|
+
60: ` m_IsTrigger: 0
|
|
4975
|
+
m_Material: {fileID: 0}
|
|
4976
|
+
m_Offset: {x: 0, y: 0}
|
|
4977
|
+
m_Points: []`,
|
|
4978
|
+
61: ` m_IsTrigger: 0
|
|
4979
|
+
m_Material: {fileID: 0}
|
|
4980
|
+
m_Offset: {x: 0, y: 0}
|
|
4981
|
+
m_Size: {x: 1, y: 1}`,
|
|
4643
4982
|
64: ` m_IsTrigger: 0
|
|
4644
4983
|
m_Convex: 0
|
|
4645
4984
|
m_CookingOptions: 30
|
|
@@ -4648,6 +4987,19 @@ var COMPONENT_DEFAULTS = {
|
|
|
4648
4987
|
m_Material: {fileID: 0}
|
|
4649
4988
|
m_Center: {x: 0, y: 0, z: 0}
|
|
4650
4989
|
m_Size: {x: 1, y: 1, z: 1}`,
|
|
4990
|
+
66: ` m_IsTrigger: 0
|
|
4991
|
+
m_Material: {fileID: 0}
|
|
4992
|
+
m_Offset: {x: 0, y: 0}
|
|
4993
|
+
m_GeometryType: 0`,
|
|
4994
|
+
68: ` m_IsTrigger: 0
|
|
4995
|
+
m_Material: {fileID: 0}
|
|
4996
|
+
m_Offset: {x: 0, y: 0}
|
|
4997
|
+
m_Points: []`,
|
|
4998
|
+
70: ` m_IsTrigger: 0
|
|
4999
|
+
m_Material: {fileID: 0}
|
|
5000
|
+
m_Offset: {x: 0, y: 0}
|
|
5001
|
+
m_Size: {x: 1, y: 1}
|
|
5002
|
+
m_Direction: 0`,
|
|
4651
5003
|
82: ` m_PlayOnAwake: 1
|
|
4652
5004
|
m_Volume: 1
|
|
4653
5005
|
m_Pitch: 1
|
|
@@ -4733,9 +5085,14 @@ function addComponentToGameObject(doc, gameObjectId, componentId) {
|
|
|
4733
5085
|
`);
|
|
4734
5086
|
goBlock.replace_raw(raw);
|
|
4735
5087
|
}
|
|
4736
|
-
function createMonoBehaviourYAML(componentId, gameObjectId, scriptGuid, fields, version) {
|
|
5088
|
+
function createMonoBehaviourYAML(componentId, gameObjectId, scriptGuid, fields, version, scriptFileId = 11500000) {
|
|
4737
5089
|
const field_yaml = fields && fields.length > 0 ? generate_field_yaml(fields, version) : `
|
|
4738
5090
|
`;
|
|
5091
|
+
const has_serialize_ref = fields?.some((f) => f.hasSerializeReference) ?? false;
|
|
5092
|
+
const references_section = has_serialize_ref ? ` references:
|
|
5093
|
+
version: 2
|
|
5094
|
+
RefIds: []
|
|
5095
|
+
` : "";
|
|
4739
5096
|
return `--- !u!114 &${componentId}
|
|
4740
5097
|
MonoBehaviour:
|
|
4741
5098
|
m_ObjectHideFlags: 0
|
|
@@ -4745,9 +5102,9 @@ MonoBehaviour:
|
|
|
4745
5102
|
m_GameObject: {fileID: ${gameObjectId}}
|
|
4746
5103
|
m_Enabled: 1
|
|
4747
5104
|
m_EditorHideFlags: 0
|
|
4748
|
-
m_Script: {fileID:
|
|
5105
|
+
m_Script: {fileID: ${scriptFileId}, guid: ${scriptGuid}, type: 3}
|
|
4749
5106
|
m_Name:
|
|
4750
|
-
m_EditorClassIdentifier:${field_yaml}`;
|
|
5107
|
+
m_EditorClassIdentifier:${field_yaml}${references_section}`;
|
|
4751
5108
|
}
|
|
4752
5109
|
function createGameObject(options) {
|
|
4753
5110
|
const { file_path, name, parent } = options;
|
|
@@ -4846,9 +5203,9 @@ function createGameObject(options) {
|
|
|
4846
5203
|
const layer = get_layer_from_parent(doc, parentTransformIdStr);
|
|
4847
5204
|
const gameObjectIdStr = doc.generate_file_id();
|
|
4848
5205
|
const transformIdStr = doc.generate_file_id();
|
|
4849
|
-
const gameObjectId =
|
|
4850
|
-
const transformId =
|
|
4851
|
-
const parentTransformId =
|
|
5206
|
+
const gameObjectId = gameObjectIdStr;
|
|
5207
|
+
const transformId = transformIdStr;
|
|
5208
|
+
const parentTransformId = parentTransformIdStr;
|
|
4852
5209
|
const newBlocks = createGameObjectYAML(gameObjectId, transformId, name.trim(), parentTransformId, rootOrder, layer);
|
|
4853
5210
|
doc.append_raw(newBlocks);
|
|
4854
5211
|
if (parentTransformIdStr !== "0" && !variantPiId) {
|
|
@@ -4870,7 +5227,7 @@ function createGameObject(options) {
|
|
|
4870
5227
|
file_path,
|
|
4871
5228
|
game_object_id: gameObjectId,
|
|
4872
5229
|
transform_id: transformId,
|
|
4873
|
-
prefab_instance_id: variantPiId
|
|
5230
|
+
prefab_instance_id: variantPiId || undefined
|
|
4874
5231
|
};
|
|
4875
5232
|
}
|
|
4876
5233
|
function createScene(options) {
|
|
@@ -5316,9 +5673,9 @@ function createPrefabVariant(options) {
|
|
|
5316
5673
|
const tempDoc = UnityDocument.from_string(`%YAML 1.1
|
|
5317
5674
|
%TAG !u! tag:unity3d.com,2011:
|
|
5318
5675
|
`);
|
|
5319
|
-
const prefabInstanceId =
|
|
5320
|
-
const strippedGoId =
|
|
5321
|
-
const strippedTransformId =
|
|
5676
|
+
const prefabInstanceId = tempDoc.generate_file_id();
|
|
5677
|
+
const strippedGoId = tempDoc.generate_file_id();
|
|
5678
|
+
const strippedTransformId = tempDoc.generate_file_id();
|
|
5322
5679
|
const finalName = variant_name || `${rootInfo.name} Variant`;
|
|
5323
5680
|
const variantYaml = `%YAML 1.1
|
|
5324
5681
|
%TAG !u! tag:unity3d.com,2011:
|
|
@@ -5434,7 +5791,7 @@ function createScriptableObject(options) {
|
|
|
5434
5791
|
const baseName = path3.basename(output_path, ".asset");
|
|
5435
5792
|
const field_yaml = resolved.fields && resolved.fields.length > 0 ? generate_field_yaml(resolved.fields, version) : `
|
|
5436
5793
|
`;
|
|
5437
|
-
|
|
5794
|
+
let assetYaml = `%YAML 1.1
|
|
5438
5795
|
%TAG !u! tag:unity3d.com,2011:
|
|
5439
5796
|
--- !u!114 &11400000
|
|
5440
5797
|
MonoBehaviour:
|
|
@@ -5448,6 +5805,16 @@ MonoBehaviour:
|
|
|
5448
5805
|
m_Script: {fileID: 11500000, guid: ${resolved.guid}, type: 3}
|
|
5449
5806
|
m_Name: ${baseName}
|
|
5450
5807
|
m_EditorClassIdentifier:${field_yaml}`;
|
|
5808
|
+
if (options.initial_values && Object.keys(options.initial_values).length > 0) {
|
|
5809
|
+
const doc = UnityDocument.from_string(assetYaml);
|
|
5810
|
+
const block = doc.blocks[0];
|
|
5811
|
+
if (block) {
|
|
5812
|
+
for (const [key, val] of Object.entries(options.initial_values)) {
|
|
5813
|
+
block.set_property(key, val);
|
|
5814
|
+
}
|
|
5815
|
+
assetYaml = doc.serialize();
|
|
5816
|
+
}
|
|
5817
|
+
}
|
|
5451
5818
|
try {
|
|
5452
5819
|
import_fs8.writeFileSync(output_path, assetYaml, "utf-8");
|
|
5453
5820
|
} catch (err) {
|
|
@@ -5528,6 +5895,80 @@ MonoImporter:
|
|
|
5528
5895
|
guid
|
|
5529
5896
|
};
|
|
5530
5897
|
}
|
|
5898
|
+
var COMPONENT_BASE_CLASSES = new Set([
|
|
5899
|
+
"MonoBehaviour",
|
|
5900
|
+
"NetworkBehaviour",
|
|
5901
|
+
"StateMachineBehaviour"
|
|
5902
|
+
]);
|
|
5903
|
+
function is_valid_component_base(base_class, project_path, depth = 0) {
|
|
5904
|
+
if (depth > 5)
|
|
5905
|
+
return false;
|
|
5906
|
+
if (COMPONENT_BASE_CLASSES.has(base_class))
|
|
5907
|
+
return true;
|
|
5908
|
+
if (!project_path)
|
|
5909
|
+
return false;
|
|
5910
|
+
const registryPath = path3.join(project_path, ".unity-agentic", "type-registry.json");
|
|
5911
|
+
if (import_fs8.existsSync(registryPath)) {
|
|
5912
|
+
try {
|
|
5913
|
+
const registry = JSON.parse(import_fs8.readFileSync(registryPath, "utf-8"));
|
|
5914
|
+
const match = registry.find((t) => t.name === base_class && t.kind === "class");
|
|
5915
|
+
if (match?.filePath) {
|
|
5916
|
+
const fullPath = path3.isAbsolute(match.filePath) ? match.filePath : path3.join(project_path, match.filePath);
|
|
5917
|
+
if (fullPath.endsWith(".cs") && import_fs8.existsSync(fullPath)) {
|
|
5918
|
+
const { getNativeExtractSerializedFields: getNativeExtractSerializedFields2 } = (init_scanner(), __toCommonJS(exports_scanner));
|
|
5919
|
+
const extract = getNativeExtractSerializedFields2();
|
|
5920
|
+
if (extract) {
|
|
5921
|
+
const typeInfos = extract(fullPath);
|
|
5922
|
+
const info = typeInfos?.find((t) => t.name === base_class);
|
|
5923
|
+
if (info?.baseClass) {
|
|
5924
|
+
return is_valid_component_base(info.baseClass, project_path, depth + 1);
|
|
5925
|
+
}
|
|
5926
|
+
}
|
|
5927
|
+
}
|
|
5928
|
+
if (!fullPath.endsWith(".cs") || !import_fs8.existsSync(fullPath)) {
|
|
5929
|
+
if (match.kind === "class") {
|
|
5930
|
+
return is_likely_component_base_name(base_class);
|
|
5931
|
+
}
|
|
5932
|
+
}
|
|
5933
|
+
}
|
|
5934
|
+
} catch {}
|
|
5935
|
+
}
|
|
5936
|
+
const cachePaths = [
|
|
5937
|
+
path3.join(project_path, ".unity-agentic", "package-cache.json"),
|
|
5938
|
+
path3.join(project_path, ".unity-agentic", "local-package-cache.json")
|
|
5939
|
+
];
|
|
5940
|
+
for (const cachePath of cachePaths) {
|
|
5941
|
+
if (!import_fs8.existsSync(cachePath))
|
|
5942
|
+
continue;
|
|
5943
|
+
try {
|
|
5944
|
+
const cache = JSON.parse(import_fs8.readFileSync(cachePath, "utf-8"));
|
|
5945
|
+
const baseClassLower = base_class.toLowerCase();
|
|
5946
|
+
for (const [, assetPath] of Object.entries(cache)) {
|
|
5947
|
+
if (!assetPath.endsWith(".cs"))
|
|
5948
|
+
continue;
|
|
5949
|
+
if (path3.basename(assetPath, ".cs").toLowerCase() !== baseClassLower)
|
|
5950
|
+
continue;
|
|
5951
|
+
const fullPath = path3.join(project_path, assetPath);
|
|
5952
|
+
if (!import_fs8.existsSync(fullPath))
|
|
5953
|
+
continue;
|
|
5954
|
+
const { getNativeExtractSerializedFields: getNativeExtractSerializedFields2 } = (init_scanner(), __toCommonJS(exports_scanner));
|
|
5955
|
+
const extract = getNativeExtractSerializedFields2();
|
|
5956
|
+
if (!extract)
|
|
5957
|
+
continue;
|
|
5958
|
+
const typeInfos = extract(fullPath);
|
|
5959
|
+
const info = typeInfos?.find((t) => t.name === base_class);
|
|
5960
|
+
if (info?.baseClass) {
|
|
5961
|
+
return is_valid_component_base(info.baseClass, project_path, depth + 1);
|
|
5962
|
+
}
|
|
5963
|
+
}
|
|
5964
|
+
} catch {}
|
|
5965
|
+
}
|
|
5966
|
+
return false;
|
|
5967
|
+
}
|
|
5968
|
+
function is_likely_component_base_name(name) {
|
|
5969
|
+
const lower = name.toLowerCase();
|
|
5970
|
+
return lower.endsWith("behaviour") || lower.endsWith("behavior") || lower.includes("monobehaviour") || lower.includes("networkbehaviour");
|
|
5971
|
+
}
|
|
5531
5972
|
function addComponent(options) {
|
|
5532
5973
|
const { file_path, game_object_name, component_type } = options;
|
|
5533
5974
|
const project_path = options.project_path || find_unity_project_root(path3.dirname(file_path)) || undefined;
|
|
@@ -5553,11 +5994,19 @@ function addComponent(options) {
|
|
|
5553
5994
|
};
|
|
5554
5995
|
}
|
|
5555
5996
|
const goResult = doc.require_unique_game_object(game_object_name);
|
|
5997
|
+
let gameObjectIdStr;
|
|
5998
|
+
let variantInfo = null;
|
|
5556
5999
|
if ("error" in goResult) {
|
|
5557
|
-
|
|
6000
|
+
const vResult = find_game_object_in_variant(doc, game_object_name, file_path, project_path);
|
|
6001
|
+
if (!vResult) {
|
|
6002
|
+
return { success: false, file_path, error: goResult.error };
|
|
6003
|
+
}
|
|
6004
|
+
gameObjectIdStr = vResult.stripped_go_id;
|
|
6005
|
+
variantInfo = { source_ref: vResult.source_ref, prefab_instance_id: vResult.prefab_instance_id };
|
|
6006
|
+
} else {
|
|
6007
|
+
gameObjectIdStr = goResult.file_id;
|
|
5558
6008
|
}
|
|
5559
|
-
const
|
|
5560
|
-
const gameObjectId = parseInt(gameObjectIdStr, 10);
|
|
6009
|
+
const gameObjectId = gameObjectIdStr;
|
|
5561
6010
|
const classId = get_class_id(component_type);
|
|
5562
6011
|
let duplicateWarning;
|
|
5563
6012
|
const goBlock = doc.find_by_file_id(gameObjectIdStr);
|
|
@@ -5572,7 +6021,7 @@ function addComponent(options) {
|
|
|
5572
6021
|
}
|
|
5573
6022
|
}
|
|
5574
6023
|
const componentIdStr = doc.generate_file_id();
|
|
5575
|
-
const componentId =
|
|
6024
|
+
const componentId = componentIdStr;
|
|
5576
6025
|
let componentYAML;
|
|
5577
6026
|
let scriptGuid;
|
|
5578
6027
|
let scriptPath;
|
|
@@ -5581,7 +6030,16 @@ function addComponent(options) {
|
|
|
5581
6030
|
const componentName = UNITY_CLASS_IDS[classId] || component_type;
|
|
5582
6031
|
componentYAML = createGenericComponentYAML(componentName, classId, componentId, gameObjectId);
|
|
5583
6032
|
} else {
|
|
5584
|
-
|
|
6033
|
+
let resolved;
|
|
6034
|
+
try {
|
|
6035
|
+
resolved = resolve_script_with_fields(component_type, project_path);
|
|
6036
|
+
} catch (e) {
|
|
6037
|
+
return {
|
|
6038
|
+
success: false,
|
|
6039
|
+
file_path,
|
|
6040
|
+
error: e instanceof Error ? e.message : String(e)
|
|
6041
|
+
};
|
|
6042
|
+
}
|
|
5585
6043
|
if (!resolved) {
|
|
5586
6044
|
const hints = [];
|
|
5587
6045
|
if (project_path) {
|
|
@@ -5608,11 +6066,11 @@ function addComponent(options) {
|
|
|
5608
6066
|
error: `"${component_type}" is ${resolved.kind === "enum" ? "an enum" : "an interface"}, not a MonoBehaviour. Cannot add as a component.`
|
|
5609
6067
|
};
|
|
5610
6068
|
}
|
|
5611
|
-
if (resolved.base_class && !
|
|
6069
|
+
if (resolved.base_class && !COMPONENT_BASE_CLASSES.has(resolved.base_class) && !is_valid_component_base(resolved.base_class, project_path)) {
|
|
5612
6070
|
return {
|
|
5613
6071
|
success: false,
|
|
5614
6072
|
file_path,
|
|
5615
|
-
error: `"${component_type}" extends ${resolved.base_class}, not MonoBehaviour. Cannot add as a component.`
|
|
6073
|
+
error: `"${component_type}" extends ${resolved.base_class}, which does not inherit from MonoBehaviour. Cannot add as a component. If this is incorrect, ensure the type registry is up to date ("setup" command).`
|
|
5616
6074
|
};
|
|
5617
6075
|
}
|
|
5618
6076
|
let version;
|
|
@@ -5621,12 +6079,20 @@ function addComponent(options) {
|
|
|
5621
6079
|
version = read_project_version(project_path);
|
|
5622
6080
|
} catch {}
|
|
5623
6081
|
}
|
|
5624
|
-
|
|
6082
|
+
let scriptFileId = 11500000;
|
|
6083
|
+
if (resolved.path?.endsWith(".dll") && resolved.class_name) {
|
|
6084
|
+
scriptFileId = compute_dll_script_file_id(resolved.namespace ?? "", resolved.class_name);
|
|
6085
|
+
}
|
|
6086
|
+
componentYAML = createMonoBehaviourYAML(componentId, gameObjectId, resolved.guid, resolved.fields, version, scriptFileId);
|
|
5625
6087
|
scriptGuid = resolved.guid;
|
|
5626
6088
|
scriptPath = resolved.path || undefined;
|
|
5627
6089
|
extractionError = resolved.extraction_error;
|
|
5628
6090
|
}
|
|
5629
|
-
|
|
6091
|
+
if (variantInfo) {
|
|
6092
|
+
appendToAddedComponents(doc, variantInfo.prefab_instance_id, variantInfo.source_ref, componentIdStr);
|
|
6093
|
+
} else {
|
|
6094
|
+
addComponentToGameObject(doc, gameObjectIdStr, componentIdStr);
|
|
6095
|
+
}
|
|
5630
6096
|
doc.append_raw(componentYAML);
|
|
5631
6097
|
const saveResult = doc.save();
|
|
5632
6098
|
if (!saveResult.success) {
|
|
@@ -5703,6 +6169,7 @@ function copyComponent(options) {
|
|
|
5703
6169
|
}
|
|
5704
6170
|
// src/editor/update.ts
|
|
5705
6171
|
var import_fs10 = require("fs");
|
|
6172
|
+
var import_fs11 = require("fs");
|
|
5706
6173
|
|
|
5707
6174
|
// src/settings.ts
|
|
5708
6175
|
var import_fs9 = require("fs");
|
|
@@ -6309,6 +6776,14 @@ function edit_sorting_layer(options) {
|
|
|
6309
6776
|
}
|
|
6310
6777
|
|
|
6311
6778
|
// src/editor/update.ts
|
|
6779
|
+
function enrich_target_ref(targetRef, blockRaw) {
|
|
6780
|
+
if (/guid:/.test(targetRef))
|
|
6781
|
+
return targetRef;
|
|
6782
|
+
const sourceMatch = blockRaw.match(/m_SourcePrefab:[ \t]*\{[^}]*guid:[ \t]*([a-f0-9]{32})/);
|
|
6783
|
+
if (!sourceMatch)
|
|
6784
|
+
return null;
|
|
6785
|
+
return targetRef.replace(/\}$/, `, guid: ${sourceMatch[1]}, type: 3}`);
|
|
6786
|
+
}
|
|
6312
6787
|
function eulerToQuaternion(euler) {
|
|
6313
6788
|
const deg2rad = Math.PI / 180;
|
|
6314
6789
|
const x = euler.x * deg2rad;
|
|
@@ -6331,6 +6806,9 @@ function validate_value_type(current_value, new_value) {
|
|
|
6331
6806
|
const current = current_value.trim();
|
|
6332
6807
|
const incoming = new_value.trim();
|
|
6333
6808
|
if (/^\{fileID:/.test(current)) {
|
|
6809
|
+
if (/^\{fileID:[ \t]*0[ \t]*\}$/.test(current)) {
|
|
6810
|
+
return null;
|
|
6811
|
+
}
|
|
6334
6812
|
if (!/^\{fileID:/.test(incoming)) {
|
|
6335
6813
|
return `Expected a reference value ({fileID: ...}), got "${incoming}"`;
|
|
6336
6814
|
}
|
|
@@ -6515,10 +6993,10 @@ function safeUnityYAMLEdit(filePath, objectName, propertyName, newValue, project
|
|
|
6515
6993
|
const propertyPattern = new RegExp(`(^\\s*m_${normalizedProperty}:\\s*)([^\\n]*)`, "m");
|
|
6516
6994
|
let updatedRaw = targetBlock.raw;
|
|
6517
6995
|
if (propertyPattern.test(updatedRaw)) {
|
|
6518
|
-
updatedRaw = updatedRaw.replace(propertyPattern,
|
|
6996
|
+
updatedRaw = updatedRaw.replace(propertyPattern, (_m, prefix) => prefix + newValue);
|
|
6519
6997
|
} else {
|
|
6520
|
-
updatedRaw = updatedRaw.replace(/(\n)(--- !u!|$)/, `
|
|
6521
|
-
m_${normalizedProperty}: ${newValue}$
|
|
6998
|
+
updatedRaw = updatedRaw.replace(/(\n)(--- !u!|$)/, (_m, g1, g2) => `
|
|
6999
|
+
m_${normalizedProperty}: ${newValue}${g1}${g2}`);
|
|
6522
7000
|
}
|
|
6523
7001
|
targetBlock.replace_raw(updatedRaw);
|
|
6524
7002
|
const saveResult = doc.save();
|
|
@@ -6604,7 +7082,9 @@ function editComponentByFileId(options) {
|
|
|
6604
7082
|
};
|
|
6605
7083
|
}
|
|
6606
7084
|
}
|
|
6607
|
-
const
|
|
7085
|
+
const exactValue = targetBlock.get_property(exactProperty);
|
|
7086
|
+
const resolvedProperty = exactValue !== null ? exactProperty : exactProperty !== prefixedProperty && targetBlock.get_property(prefixedProperty) !== null ? prefixedProperty : null;
|
|
7087
|
+
const currentValue = exactValue ?? (resolvedProperty === prefixedProperty ? targetBlock.get_property(prefixedProperty) : null);
|
|
6608
7088
|
if (currentValue !== null) {
|
|
6609
7089
|
const typeError = validate_value_type(currentValue, new_value);
|
|
6610
7090
|
if (typeError) {
|
|
@@ -6615,9 +7095,14 @@ function editComponentByFileId(options) {
|
|
|
6615
7095
|
};
|
|
6616
7096
|
}
|
|
6617
7097
|
}
|
|
6618
|
-
let modified
|
|
6619
|
-
if (
|
|
6620
|
-
modified = targetBlock.set_property(
|
|
7098
|
+
let modified;
|
|
7099
|
+
if (resolvedProperty) {
|
|
7100
|
+
modified = targetBlock.set_property(resolvedProperty, new_value, "{fileID: 0}");
|
|
7101
|
+
} else {
|
|
7102
|
+
modified = targetBlock.set_property(exactProperty, new_value, "{fileID: 0}");
|
|
7103
|
+
if (!modified && exactProperty !== prefixedProperty) {
|
|
7104
|
+
modified = targetBlock.set_property(prefixedProperty, new_value, "{fileID: 0}");
|
|
7105
|
+
}
|
|
6621
7106
|
}
|
|
6622
7107
|
if (!modified) {
|
|
6623
7108
|
if (currentValue !== null) {
|
|
@@ -6654,8 +7139,10 @@ function editComponentByFileId(options) {
|
|
|
6654
7139
|
};
|
|
6655
7140
|
}
|
|
6656
7141
|
function editPrefabOverride(options) {
|
|
6657
|
-
const { file_path, prefab_instance,
|
|
6658
|
-
const
|
|
7142
|
+
const { file_path, prefab_instance, new_value, object_reference, target, managed_reference } = options;
|
|
7143
|
+
const property_path = /[\[\]]/.test(options.property_path) && !options.property_path.startsWith("'") ? `'${options.property_path}'` : options.property_path;
|
|
7144
|
+
const effectiveValue = managed_reference ?? new_value;
|
|
7145
|
+
const objRef = managed_reference ? "{fileID: 0}" : object_reference ?? "{fileID: 0}";
|
|
6659
7146
|
if (!import_fs10.existsSync(file_path)) {
|
|
6660
7147
|
return { success: false, file_path, error: `File not found: ${file_path}` };
|
|
6661
7148
|
}
|
|
@@ -6669,11 +7156,16 @@ function editPrefabOverride(options) {
|
|
|
6669
7156
|
if (!targetBlock) {
|
|
6670
7157
|
return { success: false, file_path, error: `PrefabInstance "${prefab_instance}" not found` };
|
|
6671
7158
|
}
|
|
6672
|
-
const
|
|
6673
|
-
const
|
|
7159
|
+
const unquotedPath = property_path.replace(/^'|'$/g, "");
|
|
7160
|
+
const quotedPath = `'${unquotedPath}'`;
|
|
7161
|
+
const escapedUnquoted = unquotedPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7162
|
+
const escapedQuoted = quotedPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7163
|
+
const pathAlternation = escapedUnquoted === escapedQuoted ? escapedUnquoted : `(?:${escapedQuoted}|${escapedUnquoted})`;
|
|
7164
|
+
const entryPattern = new RegExp(`(- target:\\s*\\{[^}]+\\}\\s*\\n\\s*propertyPath:\\s*)${pathAlternation}(\\s*\\n\\s*value:\\s*)(.*)(\\s*\\n\\s*objectReference:\\s*)(.*)`, "m");
|
|
6674
7165
|
const entryMatch = targetBlock.raw.match(entryPattern);
|
|
6675
7166
|
if (entryMatch) {
|
|
6676
|
-
const
|
|
7167
|
+
const quotedValue = yaml_quote_if_needed(effectiveValue);
|
|
7168
|
+
const updatedText2 = targetBlock.raw.replace(entryPattern, (_m, g1, g2, _g3, g4) => g1 + property_path + g2 + quotedValue + g4 + objRef);
|
|
6677
7169
|
targetBlock.replace_raw(updatedText2);
|
|
6678
7170
|
const saveResult2 = doc.save();
|
|
6679
7171
|
if (!saveResult2.success) {
|
|
@@ -6710,9 +7202,13 @@ function editPrefabOverride(options) {
|
|
|
6710
7202
|
error: `Invalid target reference "${targetRef}". Expected format: {fileID: N, guid: ..., type: T}`
|
|
6711
7203
|
};
|
|
6712
7204
|
}
|
|
7205
|
+
const enriched = enrich_target_ref(targetRef, targetBlock.raw);
|
|
7206
|
+
if (enriched)
|
|
7207
|
+
targetRef = enriched;
|
|
7208
|
+
const quotedNewValue = yaml_quote_if_needed(effectiveValue);
|
|
6713
7209
|
const newEntry = ` - target: ${targetRef}
|
|
6714
7210
|
propertyPath: ${property_path}
|
|
6715
|
-
value: ${
|
|
7211
|
+
value: ${quotedNewValue}
|
|
6716
7212
|
objectReference: ${objRef}`;
|
|
6717
7213
|
const removedPattern = /(\n\s*m_RemovedComponents:)/m;
|
|
6718
7214
|
const removedMatch = targetBlock.raw.match(removedPattern);
|
|
@@ -6759,6 +7255,118 @@ ${newEntry}$1`);
|
|
|
6759
7255
|
action: "added"
|
|
6760
7256
|
};
|
|
6761
7257
|
}
|
|
7258
|
+
function batchEditPrefabOverrides(file_path, prefab_instance, edits) {
|
|
7259
|
+
if (!import_fs10.existsSync(file_path)) {
|
|
7260
|
+
return { success: false, file_path, error: `File not found: ${file_path}` };
|
|
7261
|
+
}
|
|
7262
|
+
let doc;
|
|
7263
|
+
try {
|
|
7264
|
+
doc = UnityDocument.from_file(file_path);
|
|
7265
|
+
} catch (err) {
|
|
7266
|
+
return { success: false, file_path, error: `Failed to read file: ${err instanceof Error ? err.message : String(err)}` };
|
|
7267
|
+
}
|
|
7268
|
+
const targetBlock = findPrefabInstanceBlock(doc, prefab_instance);
|
|
7269
|
+
if (!targetBlock) {
|
|
7270
|
+
return { success: false, file_path, error: `PrefabInstance "${prefab_instance}" not found` };
|
|
7271
|
+
}
|
|
7272
|
+
const actions = [];
|
|
7273
|
+
for (const edit of edits) {
|
|
7274
|
+
const { value, object_reference, target, managed_reference } = edit;
|
|
7275
|
+
const property_path = /[\[\]]/.test(edit.property_path) && !edit.property_path.startsWith("'") ? `'${edit.property_path}'` : edit.property_path;
|
|
7276
|
+
const effectiveValue = managed_reference ?? value;
|
|
7277
|
+
const objRef = managed_reference ? "{fileID: 0}" : object_reference ?? "{fileID: 0}";
|
|
7278
|
+
const unquotedPath = property_path.replace(/^'|'$/g, "");
|
|
7279
|
+
const quotedPathStr = `'${unquotedPath}'`;
|
|
7280
|
+
const batchEscapedUnquoted = unquotedPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7281
|
+
const batchEscapedQuoted = quotedPathStr.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7282
|
+
const batchPathAlt = batchEscapedUnquoted === batchEscapedQuoted ? batchEscapedUnquoted : `(?:${batchEscapedQuoted}|${batchEscapedUnquoted})`;
|
|
7283
|
+
const entryPattern = new RegExp(`(- target:\\s*\\{[^}]+\\}\\s*\\n\\s*propertyPath:\\s*)${batchPathAlt}(\\s*\\n\\s*value:\\s*)(.*)(\\s*\\n\\s*objectReference:\\s*)(.*)`, "m");
|
|
7284
|
+
const entryMatch = targetBlock.raw.match(entryPattern);
|
|
7285
|
+
if (entryMatch) {
|
|
7286
|
+
const quotedValue = yaml_quote_if_needed(effectiveValue);
|
|
7287
|
+
const updatedText = targetBlock.raw.replace(entryPattern, (_m, g1, g2, _g3, g4) => g1 + property_path + g2 + quotedValue + g4 + objRef);
|
|
7288
|
+
targetBlock.replace_raw(updatedText);
|
|
7289
|
+
actions.push({ property_path, action: "updated" });
|
|
7290
|
+
} else {
|
|
7291
|
+
let targetRef = target;
|
|
7292
|
+
if (!targetRef) {
|
|
7293
|
+
const rootProp = property_path.split(".")[0];
|
|
7294
|
+
const siblingPattern = new RegExp(`- target:\\s*(\\{[^}]+\\})\\s*\\n\\s*propertyPath:\\s*${rootProp.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`, "m");
|
|
7295
|
+
const siblingMatch = targetBlock.raw.match(siblingPattern);
|
|
7296
|
+
if (siblingMatch) {
|
|
7297
|
+
targetRef = siblingMatch[1];
|
|
7298
|
+
}
|
|
7299
|
+
}
|
|
7300
|
+
if (!targetRef) {
|
|
7301
|
+
return {
|
|
7302
|
+
success: false,
|
|
7303
|
+
file_path,
|
|
7304
|
+
error: `Cannot infer target for new override "${property_path}". Provide "target" in the edit entry (e.g., "{fileID: 400000, guid: ..., type: 3}").`
|
|
7305
|
+
};
|
|
7306
|
+
}
|
|
7307
|
+
if (!/^\{fileID:\s*-?\d+/.test(targetRef)) {
|
|
7308
|
+
return {
|
|
7309
|
+
success: false,
|
|
7310
|
+
file_path,
|
|
7311
|
+
error: `Invalid target reference "${targetRef}" for "${property_path}". Expected format: {fileID: N, guid: ..., type: T}`
|
|
7312
|
+
};
|
|
7313
|
+
}
|
|
7314
|
+
const enriched = enrich_target_ref(targetRef, targetBlock.raw);
|
|
7315
|
+
if (enriched)
|
|
7316
|
+
targetRef = enriched;
|
|
7317
|
+
const quotedNewValue = yaml_quote_if_needed(effectiveValue);
|
|
7318
|
+
const newEntry = ` - target: ${targetRef}
|
|
7319
|
+
propertyPath: ${property_path}
|
|
7320
|
+
value: ${quotedNewValue}
|
|
7321
|
+
objectReference: ${objRef}`;
|
|
7322
|
+
const removedPattern = /(\n\s*m_RemovedComponents:)/m;
|
|
7323
|
+
const removedMatch = targetBlock.raw.match(removedPattern);
|
|
7324
|
+
let updatedText;
|
|
7325
|
+
if (removedMatch) {
|
|
7326
|
+
updatedText = targetBlock.raw.replace(removedPattern, `
|
|
7327
|
+
${newEntry}$1`);
|
|
7328
|
+
} else {
|
|
7329
|
+
const lines = targetBlock.raw.split(`
|
|
7330
|
+
`);
|
|
7331
|
+
let lastObjRefIdx = -1;
|
|
7332
|
+
let inModifications = false;
|
|
7333
|
+
for (let i = 0;i < lines.length; i++) {
|
|
7334
|
+
if (/m_Modifications:/.test(lines[i])) {
|
|
7335
|
+
inModifications = true;
|
|
7336
|
+
continue;
|
|
7337
|
+
}
|
|
7338
|
+
if (inModifications && /^\s*objectReference:/.test(lines[i])) {
|
|
7339
|
+
lastObjRefIdx = i;
|
|
7340
|
+
}
|
|
7341
|
+
if (inModifications && /^\s*m_\w+:/.test(lines[i]) && !/objectReference/.test(lines[i]) && !/propertyPath/.test(lines[i])) {
|
|
7342
|
+
if (lastObjRefIdx !== -1)
|
|
7343
|
+
break;
|
|
7344
|
+
}
|
|
7345
|
+
}
|
|
7346
|
+
if (lastObjRefIdx !== -1) {
|
|
7347
|
+
lines.splice(lastObjRefIdx + 1, 0, newEntry);
|
|
7348
|
+
updatedText = lines.join(`
|
|
7349
|
+
`);
|
|
7350
|
+
} else {
|
|
7351
|
+
return { success: false, file_path, error: `Could not find insertion point in m_Modifications for "${property_path}"` };
|
|
7352
|
+
}
|
|
7353
|
+
}
|
|
7354
|
+
targetBlock.replace_raw(updatedText);
|
|
7355
|
+
actions.push({ property_path, action: "added" });
|
|
7356
|
+
}
|
|
7357
|
+
}
|
|
7358
|
+
const saveResult = doc.save();
|
|
7359
|
+
if (!saveResult.success) {
|
|
7360
|
+
return { success: false, file_path, error: saveResult.error };
|
|
7361
|
+
}
|
|
7362
|
+
return {
|
|
7363
|
+
success: true,
|
|
7364
|
+
file_path,
|
|
7365
|
+
prefab_instance_id: prefab_instance,
|
|
7366
|
+
applied: actions.length,
|
|
7367
|
+
actions
|
|
7368
|
+
};
|
|
7369
|
+
}
|
|
6762
7370
|
function editTransform(options) {
|
|
6763
7371
|
const { file_path, transform_id, position, rotation, scale } = options;
|
|
6764
7372
|
const pathError = validate_file_path(file_path, "write");
|
|
@@ -6855,10 +7463,10 @@ function batchEditProperties(filePath, edits) {
|
|
|
6855
7463
|
const propertyPattern = new RegExp(`(^\\s*m_${normalizedProperty}:\\s*)([^\\n]*)`, "m");
|
|
6856
7464
|
let updatedRaw = targetBlock.raw;
|
|
6857
7465
|
if (propertyPattern.test(updatedRaw)) {
|
|
6858
|
-
updatedRaw = updatedRaw.replace(propertyPattern,
|
|
7466
|
+
updatedRaw = updatedRaw.replace(propertyPattern, (_m, prefix) => prefix + edit.new_value);
|
|
6859
7467
|
} else {
|
|
6860
|
-
updatedRaw = updatedRaw.replace(/(\n)(--- !u!|$)/, `
|
|
6861
|
-
m_${normalizedProperty}: ${edit.new_value}$
|
|
7468
|
+
updatedRaw = updatedRaw.replace(/(\n)(--- !u!|$)/, (_m, g1, g2) => `
|
|
7469
|
+
m_${normalizedProperty}: ${edit.new_value}${g1}${g2}`);
|
|
6862
7470
|
}
|
|
6863
7471
|
targetBlock.replace_raw(updatedRaw);
|
|
6864
7472
|
}
|
|
@@ -6963,9 +7571,9 @@ function reparentGameObject(options) {
|
|
|
6963
7571
|
return {
|
|
6964
7572
|
success: true,
|
|
6965
7573
|
file_path,
|
|
6966
|
-
child_transform_id:
|
|
6967
|
-
old_parent_transform_id:
|
|
6968
|
-
new_parent_transform_id:
|
|
7574
|
+
child_transform_id: childTransformId,
|
|
7575
|
+
old_parent_transform_id: oldParentTransformId,
|
|
7576
|
+
new_parent_transform_id: newParentTransformId
|
|
6969
7577
|
};
|
|
6970
7578
|
}
|
|
6971
7579
|
function findPrefabInstanceBlock(doc, identifier) {
|
|
@@ -7320,39 +7928,267 @@ function removeRemovedGameObject(options) {
|
|
|
7320
7928
|
} catch (err) {
|
|
7321
7929
|
return { success: false, file_path, error: `Failed to read file: ${err instanceof Error ? err.message : String(err)}` };
|
|
7322
7930
|
}
|
|
7323
|
-
const targetBlock = findPrefabInstanceBlock(doc, prefab_instance);
|
|
7324
|
-
if (!targetBlock) {
|
|
7325
|
-
return { success: false, file_path, error: `PrefabInstance "${prefab_instance}" not found` };
|
|
7931
|
+
const targetBlock = findPrefabInstanceBlock(doc, prefab_instance);
|
|
7932
|
+
if (!targetBlock) {
|
|
7933
|
+
return { success: false, file_path, error: `PrefabInstance "${prefab_instance}" not found` };
|
|
7934
|
+
}
|
|
7935
|
+
const escapedRef = component_ref.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7936
|
+
const refPattern = new RegExp(`\\s*- ${escapedRef}\\n?`, "m");
|
|
7937
|
+
if (!refPattern.test(targetBlock.raw)) {
|
|
7938
|
+
return { success: false, file_path, error: `GameObject reference "${component_ref}" not found in m_RemovedGameObjects` };
|
|
7939
|
+
}
|
|
7940
|
+
const updatedRaw = targetBlock.raw.replace(refPattern, "");
|
|
7941
|
+
targetBlock.replace_raw(updatedRaw);
|
|
7942
|
+
if (!doc.validate()) {
|
|
7943
|
+
return { success: false, file_path, error: "Validation failed after removing GameObject" };
|
|
7944
|
+
}
|
|
7945
|
+
const restoreGoSaveResult = doc.save();
|
|
7946
|
+
if (!restoreGoSaveResult.success) {
|
|
7947
|
+
return { success: false, file_path, error: restoreGoSaveResult.error };
|
|
7948
|
+
}
|
|
7949
|
+
return {
|
|
7950
|
+
success: true,
|
|
7951
|
+
file_path,
|
|
7952
|
+
prefab_instance_id: targetBlock.file_id
|
|
7953
|
+
};
|
|
7954
|
+
}
|
|
7955
|
+
function generate_managed_reference_id(existing_raw, count = 1) {
|
|
7956
|
+
const { randomBytes } = require("crypto");
|
|
7957
|
+
const existingIds = new Set;
|
|
7958
|
+
const idPattern = /\b(\d{1,19})\b/g;
|
|
7959
|
+
for (const line of existing_raw.split(`
|
|
7960
|
+
`)) {
|
|
7961
|
+
if (line.includes("managedReferences[") || line.includes("rid:") || line.includes("objectReference:") && /\d{10,}/.test(line) || line.includes("value:") && /\d{16,}/.test(line)) {
|
|
7962
|
+
let m;
|
|
7963
|
+
while ((m = idPattern.exec(line)) !== null) {
|
|
7964
|
+
const val = BigInt(m[1]);
|
|
7965
|
+
if (val > 0n)
|
|
7966
|
+
existingIds.add(val);
|
|
7967
|
+
}
|
|
7968
|
+
}
|
|
7969
|
+
}
|
|
7970
|
+
const buf = randomBytes(8);
|
|
7971
|
+
const raw64 = buf.readBigUInt64BE();
|
|
7972
|
+
const mask46 = (1n << 46n) - 1n;
|
|
7973
|
+
let base = (raw64 & mask46 | 1n) << 18n;
|
|
7974
|
+
const INT64_MAX = 9223372036854775807n;
|
|
7975
|
+
if (base > INT64_MAX)
|
|
7976
|
+
base = base & INT64_MAX >> 18n << 18n;
|
|
7977
|
+
if (base <= 0n)
|
|
7978
|
+
base = 1n << 18n;
|
|
7979
|
+
const results = [];
|
|
7980
|
+
for (let i = 0;i < count; i++) {
|
|
7981
|
+
let id = base + BigInt(i);
|
|
7982
|
+
while (id <= 0n || id > INT64_MAX || existingIds.has(id)) {
|
|
7983
|
+
id += 1n;
|
|
7984
|
+
}
|
|
7985
|
+
existingIds.add(id);
|
|
7986
|
+
results.push(id.toString());
|
|
7987
|
+
}
|
|
7988
|
+
return results;
|
|
7989
|
+
}
|
|
7990
|
+
function addPrefabManagedReference(options) {
|
|
7991
|
+
const { file_path, prefab_instance, field_path, type_name, target, project_path } = options;
|
|
7992
|
+
const index = options.index ?? 0;
|
|
7993
|
+
if (!import_fs10.existsSync(file_path)) {
|
|
7994
|
+
return { success: false, file_path, error: `File not found: ${file_path}` };
|
|
7995
|
+
}
|
|
7996
|
+
const typeInfo = resolve_managed_type(type_name, project_path);
|
|
7997
|
+
let finalTypeInfo;
|
|
7998
|
+
if (typeInfo) {
|
|
7999
|
+
finalTypeInfo = typeInfo;
|
|
8000
|
+
} else {
|
|
8001
|
+
const spaceIdx = type_name.indexOf(" ");
|
|
8002
|
+
if (spaceIdx > 0) {
|
|
8003
|
+
const asm = type_name.substring(0, spaceIdx);
|
|
8004
|
+
const fullType = type_name.substring(spaceIdx + 1);
|
|
8005
|
+
const lastDot = fullType.lastIndexOf(".");
|
|
8006
|
+
finalTypeInfo = {
|
|
8007
|
+
assembly: asm,
|
|
8008
|
+
namespace: lastDot >= 0 ? fullType.substring(0, lastDot) : "",
|
|
8009
|
+
class_name: lastDot >= 0 ? fullType.substring(lastDot + 1) : fullType
|
|
8010
|
+
};
|
|
8011
|
+
} else {
|
|
8012
|
+
return {
|
|
8013
|
+
success: false,
|
|
8014
|
+
file_path,
|
|
8015
|
+
error: `Type "${type_name}" not found in type registry. Use "Assembly Namespace.ClassName" format or run "setup" to rebuild.`
|
|
8016
|
+
};
|
|
8017
|
+
}
|
|
8018
|
+
}
|
|
8019
|
+
let doc;
|
|
8020
|
+
try {
|
|
8021
|
+
doc = UnityDocument.from_file(file_path);
|
|
8022
|
+
} catch (err) {
|
|
8023
|
+
return { success: false, file_path, error: `Failed to read file: ${err instanceof Error ? err.message : String(err)}` };
|
|
8024
|
+
}
|
|
8025
|
+
const piBlock = findPrefabInstanceBlock(doc, prefab_instance);
|
|
8026
|
+
if (!piBlock) {
|
|
8027
|
+
return { success: false, file_path, error: `PrefabInstance "${prefab_instance}" not found` };
|
|
8028
|
+
}
|
|
8029
|
+
const [rid] = generate_managed_reference_id(piBlock.raw);
|
|
8030
|
+
const typeValue = finalTypeInfo.namespace ? `${finalTypeInfo.assembly} ${finalTypeInfo.namespace}.${finalTypeInfo.class_name}` : `${finalTypeInfo.assembly} ${finalTypeInfo.class_name}`;
|
|
8031
|
+
const basePath = field_path.replace(/\.Array$/, "");
|
|
8032
|
+
const overrides = [
|
|
8033
|
+
{
|
|
8034
|
+
property_path: `${basePath}.Array.data[${index}].managedReferenceType`,
|
|
8035
|
+
value: typeValue,
|
|
8036
|
+
target
|
|
8037
|
+
},
|
|
8038
|
+
{
|
|
8039
|
+
property_path: `${basePath}.Array.data[${index}].managedReferenceValue`,
|
|
8040
|
+
value: rid,
|
|
8041
|
+
target
|
|
8042
|
+
},
|
|
8043
|
+
{
|
|
8044
|
+
property_path: `managedReferences[-2]`,
|
|
8045
|
+
value: "2",
|
|
8046
|
+
target
|
|
8047
|
+
}
|
|
8048
|
+
];
|
|
8049
|
+
const result = batchEditPrefabOverrides(file_path, prefab_instance, overrides);
|
|
8050
|
+
if (!result.success) {
|
|
8051
|
+
return { success: false, file_path, error: result.error };
|
|
8052
|
+
}
|
|
8053
|
+
return {
|
|
8054
|
+
success: true,
|
|
8055
|
+
file_path,
|
|
8056
|
+
rid,
|
|
8057
|
+
type_info: finalTypeInfo,
|
|
8058
|
+
overrides_created: overrides.map((o) => o.property_path)
|
|
8059
|
+
};
|
|
8060
|
+
}
|
|
8061
|
+
function resolve_managed_type(type_name, project_path) {
|
|
8062
|
+
if (!project_path)
|
|
8063
|
+
return null;
|
|
8064
|
+
const { join: join10 } = require("path");
|
|
8065
|
+
const registryPath = join10(project_path, ".unity-agentic", "type-registry.json");
|
|
8066
|
+
if (!import_fs10.existsSync(registryPath))
|
|
8067
|
+
return null;
|
|
8068
|
+
try {
|
|
8069
|
+
const registry = JSON.parse(import_fs11.readFileSync(registryPath, "utf-8"));
|
|
8070
|
+
let targetName = type_name;
|
|
8071
|
+
let targetNs = null;
|
|
8072
|
+
const dotIndex = type_name.lastIndexOf(".");
|
|
8073
|
+
if (dotIndex > 0) {
|
|
8074
|
+
targetNs = type_name.substring(0, dotIndex);
|
|
8075
|
+
targetName = type_name.substring(dotIndex + 1);
|
|
8076
|
+
}
|
|
8077
|
+
const matches = registry.filter((t) => {
|
|
8078
|
+
if (t.name.toLowerCase() !== targetName.toLowerCase())
|
|
8079
|
+
return false;
|
|
8080
|
+
if (targetNs && t.namespace?.toLowerCase() !== targetNs.toLowerCase())
|
|
8081
|
+
return false;
|
|
8082
|
+
return true;
|
|
8083
|
+
});
|
|
8084
|
+
if (matches.length === 0)
|
|
8085
|
+
return null;
|
|
8086
|
+
const match = matches[0];
|
|
8087
|
+
let assembly = "Assembly-CSharp";
|
|
8088
|
+
if (match.filePath && (match.filePath.includes("Packages/") || match.filePath.includes("PackageCache/"))) {
|
|
8089
|
+
const pkgMatch = match.filePath.match(/(?:Packages|PackageCache)\/([^/]+)/);
|
|
8090
|
+
if (pkgMatch)
|
|
8091
|
+
assembly = pkgMatch[1].replace(/@.*$/, "");
|
|
8092
|
+
}
|
|
8093
|
+
return { class_name: match.name, namespace: match.namespace || "", assembly };
|
|
8094
|
+
} catch {
|
|
8095
|
+
return null;
|
|
8096
|
+
}
|
|
8097
|
+
}
|
|
8098
|
+
function editManagedReference(options) {
|
|
8099
|
+
const { file_path, file_id, field_path, type_name, project_path, append, initial_values } = options;
|
|
8100
|
+
if (!import_fs10.existsSync(file_path)) {
|
|
8101
|
+
return { success: false, file_path, error: `File not found: ${file_path}` };
|
|
8102
|
+
}
|
|
8103
|
+
let doc;
|
|
8104
|
+
try {
|
|
8105
|
+
doc = UnityDocument.from_file(file_path);
|
|
8106
|
+
} catch (err) {
|
|
8107
|
+
return { success: false, file_path, error: `Failed to read file: ${err instanceof Error ? err.message : String(err)}` };
|
|
8108
|
+
}
|
|
8109
|
+
const block = doc.find_by_file_id(file_id);
|
|
8110
|
+
if (!block) {
|
|
8111
|
+
return { success: false, file_path, error: `Component with fileID ${file_id} not found` };
|
|
8112
|
+
}
|
|
8113
|
+
if (block.class_id !== 114) {
|
|
8114
|
+
return { success: false, file_path, error: `fileID ${file_id} is not a MonoBehaviour (class ${block.class_id}). Managed references only apply to MonoBehaviours.` };
|
|
8115
|
+
}
|
|
8116
|
+
const typeInfo = resolve_managed_type(type_name, project_path);
|
|
8117
|
+
if (!typeInfo) {
|
|
8118
|
+
const spaceIdx = type_name.indexOf(" ");
|
|
8119
|
+
if (spaceIdx > 0) {
|
|
8120
|
+
const asm = type_name.substring(0, spaceIdx);
|
|
8121
|
+
const fullType = type_name.substring(spaceIdx + 1);
|
|
8122
|
+
const lastDot = fullType.lastIndexOf(".");
|
|
8123
|
+
const manual = {
|
|
8124
|
+
assembly: asm,
|
|
8125
|
+
namespace: lastDot >= 0 ? fullType.substring(0, lastDot) : "",
|
|
8126
|
+
class_name: lastDot >= 0 ? fullType.substring(lastDot + 1) : fullType
|
|
8127
|
+
};
|
|
8128
|
+
return applyManagedReference(doc, block, file_path, field_path, manual, append, initial_values);
|
|
8129
|
+
}
|
|
8130
|
+
return {
|
|
8131
|
+
success: false,
|
|
8132
|
+
file_path,
|
|
8133
|
+
error: `Type "${type_name}" not found in type registry. Use "Assembly Namespace.ClassName" format or run "setup" to rebuild.`
|
|
8134
|
+
};
|
|
7326
8135
|
}
|
|
7327
|
-
|
|
7328
|
-
|
|
7329
|
-
|
|
7330
|
-
|
|
8136
|
+
return applyManagedReference(doc, block, file_path, field_path, typeInfo, append, initial_values);
|
|
8137
|
+
}
|
|
8138
|
+
function applyManagedReference(doc, block, file_path, field_path, typeInfo, append, initial_values) {
|
|
8139
|
+
let raw = block.raw;
|
|
8140
|
+
const ridMatches = [...raw.matchAll(/rid:[ \t]*(\d+)/g)];
|
|
8141
|
+
const existingRids = ridMatches.map((m) => parseInt(m[1], 10)).filter((n) => !isNaN(n));
|
|
8142
|
+
const nextRid = existingRids.length > 0 ? Math.max(...existingRids) + 1 : 1;
|
|
8143
|
+
let dataBlock = "{}";
|
|
8144
|
+
if (initial_values && Object.keys(initial_values).length > 0) {
|
|
8145
|
+
const lines = Object.entries(initial_values).map(([k, v]) => ` ${k}: ${v}`);
|
|
8146
|
+
dataBlock = `
|
|
8147
|
+
` + lines.join(`
|
|
8148
|
+
`);
|
|
7331
8149
|
}
|
|
7332
|
-
const
|
|
7333
|
-
|
|
7334
|
-
|
|
7335
|
-
|
|
8150
|
+
const refEntry = ` - rid: ${nextRid}
|
|
8151
|
+
type: {class: ${typeInfo.class_name}, ns: ${typeInfo.namespace}, asm: ${typeInfo.assembly}}
|
|
8152
|
+
data: ${dataBlock}`;
|
|
8153
|
+
const refIdsPattern = /(\s*RefIds:\s*\n)/;
|
|
8154
|
+
const referencesPattern = /(\s*references:\s*\n\s*version:\s*\d+\s*\n)/;
|
|
8155
|
+
if (refIdsPattern.test(raw)) {
|
|
8156
|
+
raw = raw.replace(refIdsPattern, `$1${refEntry}
|
|
8157
|
+
`);
|
|
8158
|
+
} else if (referencesPattern.test(raw)) {
|
|
8159
|
+
raw = raw.replace(referencesPattern, `$1 RefIds:
|
|
8160
|
+
${refEntry}
|
|
8161
|
+
`);
|
|
8162
|
+
} else {
|
|
8163
|
+
raw = raw.trimEnd() + `
|
|
8164
|
+
references:
|
|
8165
|
+
version: 2
|
|
8166
|
+
RefIds:
|
|
8167
|
+
${refEntry}
|
|
8168
|
+
`;
|
|
7336
8169
|
}
|
|
7337
|
-
|
|
7338
|
-
|
|
7339
|
-
|
|
8170
|
+
if (!append) {
|
|
8171
|
+
const fieldRidPattern = new RegExp(`(${field_path.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}:\\s*\\n\\s*rid:[ \\t]*)\\d+`, "m");
|
|
8172
|
+
if (fieldRidPattern.test(raw)) {
|
|
8173
|
+
raw = raw.replace(fieldRidPattern, `$1${nextRid}`);
|
|
8174
|
+
}
|
|
7340
8175
|
}
|
|
7341
|
-
|
|
7342
|
-
|
|
7343
|
-
|
|
7344
|
-
|
|
7345
|
-
}
|
|
8176
|
+
block.replace_raw(raw);
|
|
8177
|
+
const mrSave = doc.save();
|
|
8178
|
+
if (!mrSave.success) {
|
|
8179
|
+
return { success: false, file_path, error: mrSave.error };
|
|
8180
|
+
}
|
|
8181
|
+
return { success: true, file_path, rid: nextRid, type_info: typeInfo };
|
|
7346
8182
|
}
|
|
7347
8183
|
// src/editor/delete.ts
|
|
7348
|
-
var
|
|
8184
|
+
var import_fs12 = require("fs");
|
|
7349
8185
|
function removeComponent(options) {
|
|
7350
8186
|
const { file_path, file_id } = options;
|
|
7351
8187
|
const pathError = validate_file_path(file_path, "write");
|
|
7352
8188
|
if (pathError) {
|
|
7353
8189
|
return { success: false, file_path, error: pathError };
|
|
7354
8190
|
}
|
|
7355
|
-
if (!
|
|
8191
|
+
if (!import_fs12.existsSync(file_path)) {
|
|
7356
8192
|
return { success: false, file_path, error: `File not found: ${file_path}` };
|
|
7357
8193
|
}
|
|
7358
8194
|
let doc;
|
|
@@ -7376,7 +8212,8 @@ function removeComponent(options) {
|
|
|
7376
8212
|
const parentGoId = goMatch[1];
|
|
7377
8213
|
const goBlock = doc.find_by_file_id(parentGoId);
|
|
7378
8214
|
if (goBlock) {
|
|
7379
|
-
const
|
|
8215
|
+
const escaped = file_id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
8216
|
+
const compLinePattern = new RegExp(`^[ \\t]*- component: \\{fileID: ${escaped}\\}[ \\t]*\\n`, "m");
|
|
7380
8217
|
const modifiedRaw = goBlock.raw.replace(compLinePattern, "");
|
|
7381
8218
|
goBlock.replace_raw(modifiedRaw);
|
|
7382
8219
|
}
|
|
@@ -7402,7 +8239,7 @@ function deleteGameObject(options) {
|
|
|
7402
8239
|
if (pathError) {
|
|
7403
8240
|
return { success: false, file_path, error: pathError };
|
|
7404
8241
|
}
|
|
7405
|
-
if (!
|
|
8242
|
+
if (!import_fs12.existsSync(file_path)) {
|
|
7406
8243
|
return { success: false, file_path, error: `File not found: ${file_path}` };
|
|
7407
8244
|
}
|
|
7408
8245
|
let doc;
|
|
@@ -7481,7 +8318,7 @@ function deletePrefabInstance(options) {
|
|
|
7481
8318
|
if (pathError) {
|
|
7482
8319
|
return { success: false, file_path, error: pathError };
|
|
7483
8320
|
}
|
|
7484
|
-
if (!
|
|
8321
|
+
if (!import_fs12.existsSync(file_path)) {
|
|
7485
8322
|
return { success: false, file_path, error: `File not found: ${file_path}` };
|
|
7486
8323
|
}
|
|
7487
8324
|
let doc;
|
|
@@ -7561,7 +8398,7 @@ function deletePrefabInstance(options) {
|
|
|
7561
8398
|
};
|
|
7562
8399
|
}
|
|
7563
8400
|
// src/editor/duplicate.ts
|
|
7564
|
-
var
|
|
8401
|
+
var import_fs13 = require("fs");
|
|
7565
8402
|
var path5 = __toESM(require("path"));
|
|
7566
8403
|
init_scanner();
|
|
7567
8404
|
function findPrefabInstanceByName(doc, name) {
|
|
@@ -7577,7 +8414,7 @@ function findPrefabInstanceByName(doc, name) {
|
|
|
7577
8414
|
}
|
|
7578
8415
|
function duplicateGameObject(options) {
|
|
7579
8416
|
const { file_path, object_name, new_name } = options;
|
|
7580
|
-
if (!
|
|
8417
|
+
if (!import_fs13.existsSync(file_path)) {
|
|
7581
8418
|
return { success: false, file_path, error: `File not found: ${file_path}` };
|
|
7582
8419
|
}
|
|
7583
8420
|
let doc;
|
|
@@ -7710,7 +8547,7 @@ function duplicateGameObject(options) {
|
|
|
7710
8547
|
}
|
|
7711
8548
|
function unpackPrefab(options) {
|
|
7712
8549
|
const { file_path, prefab_instance, project_path } = options;
|
|
7713
|
-
if (!
|
|
8550
|
+
if (!import_fs13.existsSync(file_path)) {
|
|
7714
8551
|
return { success: false, file_path, error: `File not found: ${file_path}` };
|
|
7715
8552
|
}
|
|
7716
8553
|
let sceneDoc;
|
|
@@ -7756,7 +8593,7 @@ function unpackPrefab(options) {
|
|
|
7756
8593
|
sourcePrefabPath = resolvedPath;
|
|
7757
8594
|
}
|
|
7758
8595
|
}
|
|
7759
|
-
if (!sourcePrefabPath || !
|
|
8596
|
+
if (!sourcePrefabPath || !import_fs13.existsSync(sourcePrefabPath)) {
|
|
7760
8597
|
const inferredProject = project_path || find_unity_project_root(path5.dirname(file_path));
|
|
7761
8598
|
if (inferredProject) {
|
|
7762
8599
|
const nativeBuild = getNativeBuildGuidCache();
|
|
@@ -7770,7 +8607,7 @@ function unpackPrefab(options) {
|
|
|
7770
8607
|
}
|
|
7771
8608
|
}
|
|
7772
8609
|
}
|
|
7773
|
-
if (!sourcePrefabPath || !
|
|
8610
|
+
if (!sourcePrefabPath || !import_fs13.existsSync(sourcePrefabPath)) {
|
|
7774
8611
|
const searchedPaths = [];
|
|
7775
8612
|
if (project_path)
|
|
7776
8613
|
searchedPaths.push(`GUID cache: ${path5.join(project_path, ".unity-agentic", "guid-cache.json")}`);
|
|
@@ -8203,15 +9040,15 @@ function move_scene(projectPath, scenePath, newPosition) {
|
|
|
8203
9040
|
}
|
|
8204
9041
|
|
|
8205
9042
|
// src/packages.ts
|
|
8206
|
-
var
|
|
9043
|
+
var import_fs14 = require("fs");
|
|
8207
9044
|
var import_path6 = require("path");
|
|
8208
9045
|
function load_manifest(project_path) {
|
|
8209
9046
|
const manifest_path = import_path6.join(project_path, "Packages", "manifest.json");
|
|
8210
|
-
if (!
|
|
9047
|
+
if (!import_fs14.existsSync(manifest_path)) {
|
|
8211
9048
|
return { error: `manifest.json not found at ${manifest_path}` };
|
|
8212
9049
|
}
|
|
8213
9050
|
try {
|
|
8214
|
-
const raw =
|
|
9051
|
+
const raw = import_fs14.readFileSync(manifest_path, "utf-8");
|
|
8215
9052
|
const parsed = JSON.parse(raw);
|
|
8216
9053
|
if (!parsed.dependencies || typeof parsed.dependencies !== "object") {
|
|
8217
9054
|
return { error: `Invalid manifest.json: missing "dependencies" object` };
|
|
@@ -8227,7 +9064,7 @@ function save_manifest(manifest_path, manifest) {
|
|
|
8227
9064
|
sorted_deps[key] = manifest.dependencies[key];
|
|
8228
9065
|
}
|
|
8229
9066
|
const output = { ...manifest, dependencies: sorted_deps };
|
|
8230
|
-
|
|
9067
|
+
import_fs14.writeFileSync(manifest_path, JSON.stringify(output, null, 2) + `
|
|
8231
9068
|
`, "utf-8");
|
|
8232
9069
|
}
|
|
8233
9070
|
function list_packages(project_path, search) {
|
|
@@ -8281,7 +9118,7 @@ function remove_package(project_path, name) {
|
|
|
8281
9118
|
}
|
|
8282
9119
|
|
|
8283
9120
|
// src/input-actions.ts
|
|
8284
|
-
var
|
|
9121
|
+
var import_fs15 = require("fs");
|
|
8285
9122
|
var import_crypto = require("crypto");
|
|
8286
9123
|
function generate_action_id() {
|
|
8287
9124
|
const bytes = import_crypto.randomBytes(16);
|
|
@@ -8295,18 +9132,18 @@ function generate_action_id() {
|
|
|
8295
9132
|
].join("-");
|
|
8296
9133
|
}
|
|
8297
9134
|
function load_input_actions(file) {
|
|
8298
|
-
if (!
|
|
9135
|
+
if (!import_fs15.existsSync(file)) {
|
|
8299
9136
|
return { error: `File not found: ${file}` };
|
|
8300
9137
|
}
|
|
8301
9138
|
try {
|
|
8302
|
-
const raw =
|
|
9139
|
+
const raw = import_fs15.readFileSync(file, "utf-8");
|
|
8303
9140
|
return JSON.parse(raw);
|
|
8304
9141
|
} catch (err) {
|
|
8305
9142
|
return { error: `Failed to parse input actions: ${err instanceof Error ? err.message : String(err)}` };
|
|
8306
9143
|
}
|
|
8307
9144
|
}
|
|
8308
9145
|
function save_input_actions(file, data) {
|
|
8309
|
-
|
|
9146
|
+
import_fs15.writeFileSync(file, JSON.stringify(data, null, 4) + `
|
|
8310
9147
|
`, "utf-8");
|
|
8311
9148
|
}
|
|
8312
9149
|
function add_map(data, name) {
|
|
@@ -8460,11 +9297,22 @@ function build_create_command() {
|
|
|
8460
9297
|
if (!result.success)
|
|
8461
9298
|
process.exitCode = 1;
|
|
8462
9299
|
});
|
|
8463
|
-
cmd.command("scriptable-object <output_path> <script>").description("Create a new ScriptableObject .asset file").option("-p, --project <path>", "Unity project path (for script GUID lookup)").option("-j, --json", "Output as JSON").action((output_path, script, options) => {
|
|
9300
|
+
cmd.command("scriptable-object <output_path> <script>").description("Create a new ScriptableObject .asset file").option("-p, --project <path>", "Unity project path (for script GUID lookup)").option("--set <json>", `Initial field values as JSON object (e.g. '{"damage": "10", "targetScope": "1"}')`).option("-j, --json", "Output as JSON").action((output_path, script, options) => {
|
|
9301
|
+
let initial_values;
|
|
9302
|
+
if (options.set) {
|
|
9303
|
+
try {
|
|
9304
|
+
initial_values = JSON.parse(options.set);
|
|
9305
|
+
} catch {
|
|
9306
|
+
console.log(JSON.stringify({ success: false, error: `Invalid JSON for --set: ${options.set}` }, null, 2));
|
|
9307
|
+
process.exitCode = 1;
|
|
9308
|
+
return;
|
|
9309
|
+
}
|
|
9310
|
+
}
|
|
8464
9311
|
const result = createScriptableObject({
|
|
8465
9312
|
output_path,
|
|
8466
9313
|
script,
|
|
8467
|
-
project_path: options.project
|
|
9314
|
+
project_path: options.project,
|
|
9315
|
+
initial_values
|
|
8468
9316
|
});
|
|
8469
9317
|
console.log(JSON.stringify(result, null, 2));
|
|
8470
9318
|
if (!result.success)
|
|
@@ -8521,7 +9369,7 @@ function build_create_command() {
|
|
|
8521
9369
|
console.log(JSON.stringify({ success: false, error: "--shader <guid> is required" }, null, 2));
|
|
8522
9370
|
process.exit(1);
|
|
8523
9371
|
}
|
|
8524
|
-
if (
|
|
9372
|
+
if (import_fs16.existsSync(output_path)) {
|
|
8525
9373
|
console.log(JSON.stringify({ success: false, error: `File already exists: ${output_path}` }, null, 2));
|
|
8526
9374
|
process.exit(1);
|
|
8527
9375
|
}
|
|
@@ -8593,7 +9441,7 @@ Material:
|
|
|
8593
9441
|
m_Colors: ${color_section}
|
|
8594
9442
|
m_BuildTextureStacks: []
|
|
8595
9443
|
`;
|
|
8596
|
-
|
|
9444
|
+
import_fs16.writeFileSync(output_path, mat_content, "utf-8");
|
|
8597
9445
|
const guid = import_crypto2.randomBytes(16).toString("hex");
|
|
8598
9446
|
const meta_content = `fileFormatVersion: 2
|
|
8599
9447
|
guid: ${guid}
|
|
@@ -8604,7 +9452,7 @@ NativeFormatImporter:
|
|
|
8604
9452
|
assetBundleName:
|
|
8605
9453
|
assetBundleVariant:
|
|
8606
9454
|
`;
|
|
8607
|
-
|
|
9455
|
+
import_fs16.writeFileSync(`${output_path}.meta`, meta_content, "utf-8");
|
|
8608
9456
|
console.log(JSON.stringify({
|
|
8609
9457
|
success: true,
|
|
8610
9458
|
file: output_path,
|
|
@@ -8634,7 +9482,7 @@ NativeFormatImporter:
|
|
|
8634
9482
|
process.exitCode = 1;
|
|
8635
9483
|
return;
|
|
8636
9484
|
}
|
|
8637
|
-
if (
|
|
9485
|
+
if (import_fs16.existsSync(output_path)) {
|
|
8638
9486
|
console.log(JSON.stringify({ success: false, error: `File already exists: ${output_path}` }, null, 2));
|
|
8639
9487
|
process.exitCode = 1;
|
|
8640
9488
|
return;
|
|
@@ -8661,7 +9509,7 @@ ScriptedImporter:
|
|
|
8661
9509
|
wrapperClassName:
|
|
8662
9510
|
wrapperCodeNamespace:
|
|
8663
9511
|
`;
|
|
8664
|
-
|
|
9512
|
+
import_fs16.writeFileSync(`${output_path}.meta`, meta_content, "utf-8");
|
|
8665
9513
|
console.log(JSON.stringify({
|
|
8666
9514
|
success: true,
|
|
8667
9515
|
file: output_path,
|
|
@@ -8677,7 +9525,7 @@ ScriptedImporter:
|
|
|
8677
9525
|
return;
|
|
8678
9526
|
}
|
|
8679
9527
|
const name = name_arg || import_path7.basename(output_path).replace(/\.anim$/i, "");
|
|
8680
|
-
if (
|
|
9528
|
+
if (import_fs16.existsSync(output_path)) {
|
|
8681
9529
|
console.log(JSON.stringify({ success: false, error: `File already exists: ${output_path}` }, null, 2));
|
|
8682
9530
|
process.exitCode = 1;
|
|
8683
9531
|
return;
|
|
@@ -8744,7 +9592,7 @@ AnimationClip:
|
|
|
8744
9592
|
m_HasMotionFloatCurves: 0
|
|
8745
9593
|
m_Events: []
|
|
8746
9594
|
`;
|
|
8747
|
-
|
|
9595
|
+
import_fs16.writeFileSync(output_path, anim_content, "utf-8");
|
|
8748
9596
|
const guid = import_crypto2.randomBytes(16).toString("hex");
|
|
8749
9597
|
const meta_content = `fileFormatVersion: 2
|
|
8750
9598
|
guid: ${guid}
|
|
@@ -8755,7 +9603,7 @@ NativeFormatImporter:
|
|
|
8755
9603
|
assetBundleName:
|
|
8756
9604
|
assetBundleVariant:
|
|
8757
9605
|
`;
|
|
8758
|
-
|
|
9606
|
+
import_fs16.writeFileSync(`${output_path}.meta`, meta_content, "utf-8");
|
|
8759
9607
|
console.log(JSON.stringify({
|
|
8760
9608
|
success: true,
|
|
8761
9609
|
file: output_path,
|
|
@@ -8773,7 +9621,7 @@ NativeFormatImporter:
|
|
|
8773
9621
|
process.exitCode = 1;
|
|
8774
9622
|
return;
|
|
8775
9623
|
}
|
|
8776
|
-
if (
|
|
9624
|
+
if (import_fs16.existsSync(output_path)) {
|
|
8777
9625
|
console.log(JSON.stringify({ success: false, error: `File already exists: ${output_path}` }, null, 2));
|
|
8778
9626
|
process.exitCode = 1;
|
|
8779
9627
|
return;
|
|
@@ -8823,7 +9671,7 @@ AnimatorStateMachine:
|
|
|
8823
9671
|
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
|
|
8824
9672
|
m_DefaultState: {fileID: 0}
|
|
8825
9673
|
`;
|
|
8826
|
-
|
|
9674
|
+
import_fs16.writeFileSync(output_path, ctrl_content, "utf-8");
|
|
8827
9675
|
const guid = import_crypto2.randomBytes(16).toString("hex");
|
|
8828
9676
|
const meta_content = `fileFormatVersion: 2
|
|
8829
9677
|
guid: ${guid}
|
|
@@ -8834,7 +9682,7 @@ NativeFormatImporter:
|
|
|
8834
9682
|
assetBundleName:
|
|
8835
9683
|
assetBundleVariant:
|
|
8836
9684
|
`;
|
|
8837
|
-
|
|
9685
|
+
import_fs16.writeFileSync(`${output_path}.meta`, meta_content, "utf-8");
|
|
8838
9686
|
console.log(JSON.stringify({
|
|
8839
9687
|
success: true,
|
|
8840
9688
|
file: output_path,
|
|
@@ -8851,7 +9699,7 @@ NativeFormatImporter:
|
|
|
8851
9699
|
process.exitCode = 1;
|
|
8852
9700
|
return;
|
|
8853
9701
|
}
|
|
8854
|
-
if (
|
|
9702
|
+
if (import_fs16.existsSync(output_path)) {
|
|
8855
9703
|
console.log(JSON.stringify({ success: false, error: `File already exists: ${output_path}` }, null, 2));
|
|
8856
9704
|
process.exitCode = 1;
|
|
8857
9705
|
return;
|
|
@@ -8890,7 +9738,7 @@ Transform:
|
|
|
8890
9738
|
m_Father: {fileID: 0}
|
|
8891
9739
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
8892
9740
|
`;
|
|
8893
|
-
|
|
9741
|
+
import_fs16.writeFileSync(output_path, prefab_content, "utf-8");
|
|
8894
9742
|
const guid = import_crypto2.randomBytes(16).toString("hex");
|
|
8895
9743
|
const meta_content = `fileFormatVersion: 2
|
|
8896
9744
|
guid: ${guid}
|
|
@@ -8900,7 +9748,7 @@ PrefabImporter:
|
|
|
8900
9748
|
assetBundleName:
|
|
8901
9749
|
assetBundleVariant:
|
|
8902
9750
|
`;
|
|
8903
|
-
|
|
9751
|
+
import_fs16.writeFileSync(`${output_path}.meta`, meta_content, "utf-8");
|
|
8904
9752
|
console.log(JSON.stringify({
|
|
8905
9753
|
success: true,
|
|
8906
9754
|
file: output_path,
|
|
@@ -8914,7 +9762,7 @@ PrefabImporter:
|
|
|
8914
9762
|
|
|
8915
9763
|
// src/cmd-read.ts
|
|
8916
9764
|
init_scanner();
|
|
8917
|
-
var
|
|
9765
|
+
var import_fs17 = require("fs");
|
|
8918
9766
|
var import_path8 = require("path");
|
|
8919
9767
|
var import_os = require("os");
|
|
8920
9768
|
function parse_material_yaml(content) {
|
|
@@ -9161,7 +10009,7 @@ function categorize_asset(filePath) {
|
|
|
9161
10009
|
function find_project_root_from_file(filePath) {
|
|
9162
10010
|
let dir = import_path8.dirname(import_path8.resolve(filePath));
|
|
9163
10011
|
for (let i = 0;i < 20; i++) {
|
|
9164
|
-
if (
|
|
10012
|
+
if (import_fs17.existsSync(import_path8.join(dir, "Assets")) && import_fs17.existsSync(import_path8.join(dir, "ProjectSettings"))) {
|
|
9165
10013
|
return dir;
|
|
9166
10014
|
}
|
|
9167
10015
|
const parent = import_path8.dirname(dir);
|
|
@@ -9507,7 +10355,7 @@ function walk_files(dir, extensions) {
|
|
|
9507
10355
|
const current = stack.pop();
|
|
9508
10356
|
let entries;
|
|
9509
10357
|
try {
|
|
9510
|
-
entries =
|
|
10358
|
+
entries = import_fs17.readdirSync(current);
|
|
9511
10359
|
} catch {
|
|
9512
10360
|
continue;
|
|
9513
10361
|
}
|
|
@@ -9516,7 +10364,7 @@ function walk_files(dir, extensions) {
|
|
|
9516
10364
|
continue;
|
|
9517
10365
|
const full = import_path8.join(current, entry);
|
|
9518
10366
|
try {
|
|
9519
|
-
const stat =
|
|
10367
|
+
const stat = import_fs17.statSync(full);
|
|
9520
10368
|
if (stat.isDirectory()) {
|
|
9521
10369
|
stack.push(full);
|
|
9522
10370
|
} else if (extensions.has(import_path8.extname(full).toLowerCase())) {
|
|
@@ -9530,7 +10378,7 @@ function walk_files(dir, extensions) {
|
|
|
9530
10378
|
return results;
|
|
9531
10379
|
}
|
|
9532
10380
|
function validate_unity_yaml(file) {
|
|
9533
|
-
if (!
|
|
10381
|
+
if (!import_fs17.existsSync(file)) {
|
|
9534
10382
|
return `File not found: ${file}`;
|
|
9535
10383
|
}
|
|
9536
10384
|
try {
|
|
@@ -9615,13 +10463,59 @@ function build_read_command(getScanner) {
|
|
|
9615
10463
|
result.warning = result.warning ? `${result.warning}; ${maxDepthWarning}` : maxDepthWarning;
|
|
9616
10464
|
}
|
|
9617
10465
|
if (result.total === 0 && !result.error) {
|
|
9618
|
-
|
|
9619
|
-
|
|
9620
|
-
|
|
9621
|
-
const
|
|
9622
|
-
|
|
9623
|
-
|
|
9624
|
-
|
|
10466
|
+
const prefabInstances = result.prefabInstances;
|
|
10467
|
+
if (prefabInstances && prefabInstances.length > 0) {
|
|
10468
|
+
try {
|
|
10469
|
+
const doc = UnityDocument.from_file(file);
|
|
10470
|
+
const projectPath = find_unity_project_root(import_path8.dirname(file));
|
|
10471
|
+
const resolved = resolve_source_prefab(doc, file, projectPath ?? undefined);
|
|
10472
|
+
if (resolved) {
|
|
10473
|
+
const sourceResult = getScanner().inspect_all_paginated({
|
|
10474
|
+
file: resolved.source_path,
|
|
10475
|
+
include_properties: options.properties === true,
|
|
10476
|
+
verbose: options.verbose === true,
|
|
10477
|
+
page_size: pageSize,
|
|
10478
|
+
cursor: 0,
|
|
10479
|
+
max_depth: maxDepth,
|
|
10480
|
+
filter_component: options.filterComponent
|
|
10481
|
+
});
|
|
10482
|
+
if (sourceResult.total > 0 && sourceResult.gameobjects) {
|
|
10483
|
+
const piBlock = resolved.prefab_instance_block;
|
|
10484
|
+
const nameOverrides = new Map;
|
|
10485
|
+
const namePattern = /- target:[ \t]*\{fileID:[ \t]*(-?\d+)[^}]*\}\s*\n\s*propertyPath:[ \t]*m_Name\s*\n\s*value:[ \t]*(.*)/g;
|
|
10486
|
+
let nameMatch;
|
|
10487
|
+
while ((nameMatch = namePattern.exec(piBlock.raw)) !== null) {
|
|
10488
|
+
nameOverrides.set(nameMatch[1], nameMatch[2].trim());
|
|
10489
|
+
}
|
|
10490
|
+
for (const go of sourceResult.gameobjects) {
|
|
10491
|
+
const goRecord = go;
|
|
10492
|
+
const override = nameOverrides.get(goRecord.fileId);
|
|
10493
|
+
if (override) {
|
|
10494
|
+
goRecord.name = override;
|
|
10495
|
+
}
|
|
10496
|
+
}
|
|
10497
|
+
const resultRecord = result;
|
|
10498
|
+
resultRecord.gameobjects = sourceResult.gameobjects;
|
|
10499
|
+
resultRecord.total = sourceResult.total;
|
|
10500
|
+
resultRecord.totalInScene = sourceResult.totalInScene;
|
|
10501
|
+
resultRecord.resolvedFromSource = true;
|
|
10502
|
+
resultRecord.sourcePrefab = resolved.source_path;
|
|
10503
|
+
resultRecord.sourceGuid = resolved.source_guid;
|
|
10504
|
+
const variantNote = `PrefabVariant resolved from source prefab: ${resolved.source_path}`;
|
|
10505
|
+
result.warning = result.warning ? `${result.warning}; ${variantNote}` : variantNote;
|
|
10506
|
+
}
|
|
10507
|
+
}
|
|
10508
|
+
} catch {}
|
|
10509
|
+
}
|
|
10510
|
+
if (result.total === 0) {
|
|
10511
|
+
try {
|
|
10512
|
+
const fileSize = import_fs17.statSync(file).size;
|
|
10513
|
+
if (fileSize > 100) {
|
|
10514
|
+
const corruptWarning = "File has valid Unity YAML header but contains no parseable GameObjects -- file may be corrupt or malformed";
|
|
10515
|
+
result.warning = result.warning ? `${result.warning}; ${corruptWarning}` : corruptWarning;
|
|
10516
|
+
}
|
|
10517
|
+
} catch {}
|
|
10518
|
+
}
|
|
9625
10519
|
}
|
|
9626
10520
|
if (options.summary) {
|
|
9627
10521
|
const component_counts = {};
|
|
@@ -9718,12 +10612,6 @@ function build_read_command(getScanner) {
|
|
|
9718
10612
|
};
|
|
9719
10613
|
console.log(JSON.stringify(output, null, 2));
|
|
9720
10614
|
});
|
|
9721
|
-
cmd.command("scriptable-object").description('(Deprecated: renamed to "read asset")').argument("[file]").allowUnknownOption().action(() => {
|
|
9722
|
-
console.log(JSON.stringify({
|
|
9723
|
-
error: 'Command "read scriptable-object" has been renamed to "read asset". Use: unity-agentic-tools read asset <file>'
|
|
9724
|
-
}, null, 2));
|
|
9725
|
-
process.exit(1);
|
|
9726
|
-
});
|
|
9727
10615
|
cmd.command("material <file>").description("Read a Unity Material file (.mat) with structured property output").option("--project <path>", "Unity project root (for GUID resolution)").option("--summary", "Show shader name, property count, texture count only").option("-j, --json", "Output as JSON").action((file, options) => {
|
|
9728
10616
|
if (!file.toLowerCase().endsWith(".mat")) {
|
|
9729
10617
|
console.log(JSON.stringify({ error: `File must be a .mat file: ${file}` }, null, 2));
|
|
@@ -9734,7 +10622,7 @@ function build_read_command(getScanner) {
|
|
|
9734
10622
|
console.log(JSON.stringify({ error: matValidationError }, null, 2));
|
|
9735
10623
|
process.exit(1);
|
|
9736
10624
|
}
|
|
9737
|
-
const content =
|
|
10625
|
+
const content = import_fs17.readFileSync(file, "utf-8");
|
|
9738
10626
|
if (!content.includes("Material:")) {
|
|
9739
10627
|
console.log(JSON.stringify({ error: `File "${file}" does not contain a Material block. Use 'read asset' for generic Unity YAML files.` }, null, 2));
|
|
9740
10628
|
process.exit(1);
|
|
@@ -9776,13 +10664,13 @@ function build_read_command(getScanner) {
|
|
|
9776
10664
|
}, null, 2));
|
|
9777
10665
|
});
|
|
9778
10666
|
cmd.command("dependencies <file>").description("List asset dependencies (GUIDs referenced by this file)").option("--project <path>", "Unity project root (for GUID resolution)").option("--unresolved", "Show only GUIDs that could not be resolved").option("--recursive [depth]", "Follow dependency chain N levels deep (default: 3)").option("-j, --json", "Output as JSON").action((file, options) => {
|
|
9779
|
-
if (!
|
|
10667
|
+
if (!import_fs17.existsSync(file)) {
|
|
9780
10668
|
console.log(JSON.stringify({ error: `File not found: ${file}` }, null, 2));
|
|
9781
10669
|
process.exit(1);
|
|
9782
10670
|
}
|
|
9783
10671
|
let content;
|
|
9784
10672
|
try {
|
|
9785
|
-
content =
|
|
10673
|
+
content = import_fs17.readFileSync(file, "utf-8");
|
|
9786
10674
|
} catch {
|
|
9787
10675
|
console.log(JSON.stringify({ error: `Cannot read file: ${file}` }, null, 2));
|
|
9788
10676
|
process.exit(1);
|
|
@@ -9823,7 +10711,7 @@ function build_read_command(getScanner) {
|
|
|
9823
10711
|
const result = [];
|
|
9824
10712
|
let fileContent;
|
|
9825
10713
|
try {
|
|
9826
|
-
fileContent =
|
|
10714
|
+
fileContent = import_fs17.readFileSync(filePath, "utf-8");
|
|
9827
10715
|
} catch {
|
|
9828
10716
|
return [];
|
|
9829
10717
|
}
|
|
@@ -9840,7 +10728,7 @@ function build_read_command(getScanner) {
|
|
|
9840
10728
|
const rAbsPath = cache.resolve_absolute(g);
|
|
9841
10729
|
const rType = rPath ? categorize_asset(rPath) : "unknown";
|
|
9842
10730
|
const dep = { guid: g, path: rPath, type: rType, depth };
|
|
9843
|
-
if (rAbsPath && depth < max_depth &&
|
|
10731
|
+
if (rAbsPath && depth < max_depth && import_fs17.existsSync(rAbsPath)) {
|
|
9844
10732
|
const subs = traverse_file(rAbsPath, depth + 1);
|
|
9845
10733
|
if (subs.length > 0)
|
|
9846
10734
|
dep.sub_dependencies = subs;
|
|
@@ -9869,7 +10757,7 @@ function build_read_command(getScanner) {
|
|
|
9869
10757
|
const rDep = { guid: dep.guid, path: dep.path, type: dep.type, depth: 0 };
|
|
9870
10758
|
if (dep.path) {
|
|
9871
10759
|
const absPath = cache.resolve_absolute(dep.guid);
|
|
9872
|
-
if (absPath &&
|
|
10760
|
+
if (absPath && import_fs17.existsSync(absPath)) {
|
|
9873
10761
|
const subs = traverse_file(absPath, 1);
|
|
9874
10762
|
if (subs.length > 0)
|
|
9875
10763
|
rDep.sub_dependencies = subs;
|
|
@@ -9960,14 +10848,31 @@ function build_read_command(getScanner) {
|
|
|
9960
10848
|
const target_match = lines[i].match(/\{fileID:\s*(-?\d+)/);
|
|
9961
10849
|
const property_match = i + 1 < lines.length ? lines[i + 1].match(/propertyPath:\s*(.+)/) : null;
|
|
9962
10850
|
const value_match = i + 2 < lines.length ? lines[i + 2].match(/value:\s*(.*)/) : null;
|
|
9963
|
-
const obj_ref_match = i + 3 < lines.length ? lines[i + 3].match(/objectReference
|
|
10851
|
+
const obj_ref_match = i + 3 < lines.length ? lines[i + 3].match(/objectReference:[ \t]*(.+)/) : null;
|
|
9964
10852
|
if (target_match && property_match) {
|
|
9965
|
-
|
|
10853
|
+
const mod = {
|
|
9966
10854
|
target_file_id: target_match[1],
|
|
9967
10855
|
property_path: property_match[1].trim(),
|
|
9968
10856
|
value: value_match ? value_match[1].trim() : "",
|
|
9969
|
-
object_reference: obj_ref_match ? obj_ref_match[1] : null
|
|
9970
|
-
}
|
|
10857
|
+
object_reference: obj_ref_match ? obj_ref_match[1].trim() : null
|
|
10858
|
+
};
|
|
10859
|
+
const propPath = mod.property_path;
|
|
10860
|
+
const modValue = mod.value;
|
|
10861
|
+
if (propPath.endsWith(".managedReferenceType") && modValue) {
|
|
10862
|
+
const spaceIdx = modValue.indexOf(" ");
|
|
10863
|
+
if (spaceIdx > 0) {
|
|
10864
|
+
const assembly = modValue.substring(0, spaceIdx);
|
|
10865
|
+
const full_type = modValue.substring(spaceIdx + 1);
|
|
10866
|
+
const lastDot = full_type.lastIndexOf(".");
|
|
10867
|
+
mod.managed_reference_type = {
|
|
10868
|
+
assembly,
|
|
10869
|
+
full_type,
|
|
10870
|
+
namespace: lastDot >= 0 ? full_type.substring(0, lastDot) : "",
|
|
10871
|
+
class_name: lastDot >= 0 ? full_type.substring(lastDot + 1) : full_type
|
|
10872
|
+
};
|
|
10873
|
+
}
|
|
10874
|
+
}
|
|
10875
|
+
modifications.push(mod);
|
|
9971
10876
|
}
|
|
9972
10877
|
i += 4;
|
|
9973
10878
|
} else {
|
|
@@ -10035,8 +10940,129 @@ function build_read_command(getScanner) {
|
|
|
10035
10940
|
process.exit(1);
|
|
10036
10941
|
}
|
|
10037
10942
|
});
|
|
10943
|
+
cmd.command("target <file> <gameobject_name> [component_type]").description("Build a --target reference string for prefab override commands").option("-p, --project <path>", "Unity project path").option("-j, --json", "Output as JSON").action((file, gameobject_name, component_type, options) => {
|
|
10944
|
+
try {
|
|
10945
|
+
if (!import_fs17.existsSync(file)) {
|
|
10946
|
+
console.log(JSON.stringify({ error: `File not found: ${file}` }, null, 2));
|
|
10947
|
+
process.exit(1);
|
|
10948
|
+
}
|
|
10949
|
+
const doc = UnityDocument.from_file(file);
|
|
10950
|
+
let guid;
|
|
10951
|
+
const piBlocks = doc.find_by_class_id(1001);
|
|
10952
|
+
if (piBlocks.length > 0) {
|
|
10953
|
+
const sourceMatch = piBlocks[0].raw.match(/m_SourcePrefab:[ \t]*\{[^}]*guid:[ \t]*([a-f0-9]{32})/);
|
|
10954
|
+
guid = sourceMatch ? sourceMatch[1] : null;
|
|
10955
|
+
if (!guid) {
|
|
10956
|
+
console.log(JSON.stringify({ error: "Cannot extract source GUID from PrefabInstance m_SourcePrefab." }, null, 2));
|
|
10957
|
+
process.exit(1);
|
|
10958
|
+
}
|
|
10959
|
+
} else {
|
|
10960
|
+
const metaPath = file + ".meta";
|
|
10961
|
+
guid = extractGuidFromMeta(metaPath);
|
|
10962
|
+
if (!guid) {
|
|
10963
|
+
console.log(JSON.stringify({ error: `Cannot read GUID from ${metaPath}. Ensure the .meta file exists.` }, null, 2));
|
|
10964
|
+
process.exit(1);
|
|
10965
|
+
}
|
|
10966
|
+
}
|
|
10967
|
+
const goResult = doc.require_unique_game_object(gameobject_name);
|
|
10968
|
+
let targetFileId;
|
|
10969
|
+
if ("error" in goResult) {
|
|
10970
|
+
let found = false;
|
|
10971
|
+
for (const block of doc.blocks) {
|
|
10972
|
+
if (block.class_id !== 1001)
|
|
10973
|
+
continue;
|
|
10974
|
+
const nameMatch = block.raw.match(new RegExp(`- target:[ \\t]*\\{fileID:[ \\t]*(-?\\d+)[^}]*\\}\\s*\\n\\s*propertyPath:[ \\t]*m_Name\\s*\\n\\s*value:[ \\t]*${gameobject_name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s*$`, "m"));
|
|
10975
|
+
if (nameMatch) {
|
|
10976
|
+
targetFileId = nameMatch[1];
|
|
10977
|
+
found = true;
|
|
10978
|
+
break;
|
|
10979
|
+
}
|
|
10980
|
+
}
|
|
10981
|
+
if (!found) {
|
|
10982
|
+
console.log(JSON.stringify({ error: goResult.error }, null, 2));
|
|
10983
|
+
process.exit(1);
|
|
10984
|
+
}
|
|
10985
|
+
} else {
|
|
10986
|
+
targetFileId = goResult.file_id;
|
|
10987
|
+
}
|
|
10988
|
+
if (component_type) {
|
|
10989
|
+
const classId = get_class_id(component_type);
|
|
10990
|
+
const goBlock = doc.find_by_file_id(targetFileId);
|
|
10991
|
+
if (goBlock && !goBlock.is_stripped) {
|
|
10992
|
+
const compRefs = [...goBlock.raw.matchAll(/component:[ \t]*\{fileID:[ \t]*(-?\d+)\}/g)].map((m) => m[1]);
|
|
10993
|
+
let compFound = false;
|
|
10994
|
+
for (const refId of compRefs) {
|
|
10995
|
+
const compBlock = doc.find_by_file_id(refId);
|
|
10996
|
+
if (!compBlock)
|
|
10997
|
+
continue;
|
|
10998
|
+
if (classId !== null && compBlock.class_id === classId) {
|
|
10999
|
+
targetFileId = refId;
|
|
11000
|
+
compFound = true;
|
|
11001
|
+
break;
|
|
11002
|
+
}
|
|
11003
|
+
if (classId === null && compBlock.class_id === 114) {
|
|
11004
|
+
const scriptMatch = compBlock.raw.match(/m_Script:[ \t]*\{[^}]*guid:[ \t]*([a-f0-9]{32})/);
|
|
11005
|
+
if (scriptMatch) {
|
|
11006
|
+
const project = options.project || find_unity_project_root(import_path8.dirname(file));
|
|
11007
|
+
if (project) {
|
|
11008
|
+
const cache = load_guid_cache(project);
|
|
11009
|
+
if (cache) {
|
|
11010
|
+
const scriptPath = cache.resolve(scriptMatch[1]);
|
|
11011
|
+
if (scriptPath && import_path8.basename(scriptPath, ".cs").toLowerCase() === component_type.toLowerCase().replace(/\.cs$/, "")) {
|
|
11012
|
+
targetFileId = refId;
|
|
11013
|
+
compFound = true;
|
|
11014
|
+
break;
|
|
11015
|
+
}
|
|
11016
|
+
}
|
|
11017
|
+
}
|
|
11018
|
+
}
|
|
11019
|
+
}
|
|
11020
|
+
}
|
|
11021
|
+
if (!compFound) {
|
|
11022
|
+
console.log(JSON.stringify({ error: `Component "${component_type}" not found on GameObject "${gameobject_name}"` }, null, 2));
|
|
11023
|
+
process.exit(1);
|
|
11024
|
+
}
|
|
11025
|
+
} else {
|
|
11026
|
+
const project = options.project || find_unity_project_root(import_path8.dirname(file));
|
|
11027
|
+
const resolved = resolve_source_prefab(doc, file, project ?? undefined);
|
|
11028
|
+
if (resolved) {
|
|
11029
|
+
const sourceDoc = UnityDocument.from_file(resolved.source_path);
|
|
11030
|
+
const sourceGo = sourceDoc.require_unique_game_object(gameobject_name);
|
|
11031
|
+
if (!("error" in sourceGo)) {
|
|
11032
|
+
const compRefs = [...sourceGo.raw.matchAll(/component:[ \t]*\{fileID:[ \t]*(-?\d+)\}/g)].map((m) => m[1]);
|
|
11033
|
+
let compFound = false;
|
|
11034
|
+
for (const refId of compRefs) {
|
|
11035
|
+
const compBlock = sourceDoc.find_by_file_id(refId);
|
|
11036
|
+
if (!compBlock)
|
|
11037
|
+
continue;
|
|
11038
|
+
if (classId !== null && compBlock.class_id === classId) {
|
|
11039
|
+
targetFileId = refId;
|
|
11040
|
+
compFound = true;
|
|
11041
|
+
break;
|
|
11042
|
+
}
|
|
11043
|
+
}
|
|
11044
|
+
if (!compFound) {
|
|
11045
|
+
console.log(JSON.stringify({ error: `Component "${component_type}" not found on "${gameobject_name}" in source prefab` }, null, 2));
|
|
11046
|
+
process.exit(1);
|
|
11047
|
+
}
|
|
11048
|
+
}
|
|
11049
|
+
}
|
|
11050
|
+
}
|
|
11051
|
+
}
|
|
11052
|
+
const target = `{fileID: ${targetFileId}, guid: ${guid}, type: 3}`;
|
|
11053
|
+
console.log(JSON.stringify({
|
|
11054
|
+
target,
|
|
11055
|
+
file_id: targetFileId,
|
|
11056
|
+
guid,
|
|
11057
|
+
type: 3
|
|
11058
|
+
}, null, 2));
|
|
11059
|
+
} catch (err) {
|
|
11060
|
+
console.log(JSON.stringify({ error: err instanceof Error ? err.message : String(err) }, null, 2));
|
|
11061
|
+
process.exit(1);
|
|
11062
|
+
}
|
|
11063
|
+
});
|
|
10038
11064
|
cmd.command("script <file>").description("Extract C# type declarations from a .cs file or .NET DLL").option("-j, --json", "Output as JSON").action((file, _options) => {
|
|
10039
|
-
if (!
|
|
11065
|
+
if (!import_fs17.existsSync(file)) {
|
|
10040
11066
|
console.log(JSON.stringify({ error: `File not found: ${file}` }, null, 2));
|
|
10041
11067
|
process.exit(1);
|
|
10042
11068
|
}
|
|
@@ -10121,18 +11147,20 @@ function build_read_command(getScanner) {
|
|
|
10121
11147
|
types: displayed
|
|
10122
11148
|
}, null, 2));
|
|
10123
11149
|
});
|
|
10124
|
-
cmd.command("log").description("Read and filter the Unity Editor.log").option("--path <file>", "Path to Editor.log (auto-detected if omitted)").option("--project <path>", "Filter to log entries from a specific Unity project session").option("--tail <n>", "Show last N lines (default 50)", "50").option("--errors", "Show only error entries").option("--warnings", "Show only warning entries").option("--compile-errors", "Show only C# compilation errors").option("--import-errors", "Show only asset import errors").option("--since <timestamp>", "Filter entries after this timestamp (YYYY-MM-DD or HH:MM:SS)").option("--search <pattern>", "Regex filter on log content").option("-j, --json", "Output as JSON").action((options) => {
|
|
11150
|
+
cmd.command("log [project-path]").description("Read and filter the Unity Editor.log").option("--path <file>", "Path to Editor.log (auto-detected if omitted)").option("--project <path>", "Filter to log entries from a specific Unity project session").option("--tail <n>", "Show last N lines (default 50)", "50").option("--errors", "Show only error entries").option("--warnings", "Show only warning entries").option("--compile-errors", "Show only C# compilation errors").option("--import-errors", "Show only asset import errors").option("--since <timestamp>", "Filter entries after this timestamp (YYYY-MM-DD or HH:MM:SS)").option("--search <pattern>", "Regex filter on log content").option("-j, --json", "Output as JSON").action((projectPath, options) => {
|
|
11151
|
+
if (projectPath && !options.project)
|
|
11152
|
+
options.project = projectPath;
|
|
10125
11153
|
const logPath = options.path || get_editor_log_path();
|
|
10126
|
-
if (!logPath || !
|
|
11154
|
+
if (!logPath || !import_fs17.existsSync(logPath)) {
|
|
10127
11155
|
console.log(JSON.stringify({ error: `Editor.log not found${logPath ? `: ${logPath}` : ". Could not detect platform log path."}` }, null, 2));
|
|
10128
11156
|
process.exit(1);
|
|
10129
11157
|
}
|
|
10130
|
-
const content =
|
|
11158
|
+
const content = import_fs17.readFileSync(logPath, "utf-8");
|
|
10131
11159
|
let lines = content.split(/\r?\n/);
|
|
10132
11160
|
if (options.project) {
|
|
10133
|
-
const
|
|
10134
|
-
const projectName = import_path8.basename(
|
|
10135
|
-
const escapedPath =
|
|
11161
|
+
const projectPath2 = import_path8.resolve(options.project);
|
|
11162
|
+
const projectName = import_path8.basename(projectPath2);
|
|
11163
|
+
const escapedPath = projectPath2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
10136
11164
|
const escapedName = projectName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
10137
11165
|
const session_markers = [
|
|
10138
11166
|
new RegExp(`Loading project at '${escapedPath}'`),
|
|
@@ -10248,11 +11276,11 @@ function build_read_command(getScanner) {
|
|
|
10248
11276
|
});
|
|
10249
11277
|
cmd.command("meta <file>").description("Read a Unity .meta file and show importer settings").option("--summary", "Show importer type and key settings only").option("-j, --json", "Output as JSON").action((file, options) => {
|
|
10250
11278
|
const metaPath = file.endsWith(".meta") ? file : `${file}.meta`;
|
|
10251
|
-
if (!
|
|
11279
|
+
if (!import_fs17.existsSync(metaPath)) {
|
|
10252
11280
|
console.log(JSON.stringify({ error: `Meta file not found: ${metaPath}` }, null, 2));
|
|
10253
11281
|
process.exit(1);
|
|
10254
11282
|
}
|
|
10255
|
-
const content =
|
|
11283
|
+
const content = import_fs17.readFileSync(metaPath, "utf-8");
|
|
10256
11284
|
const lines = content.split(/\r?\n/);
|
|
10257
11285
|
let guid = "";
|
|
10258
11286
|
let importer_type = "Unknown";
|
|
@@ -10340,7 +11368,7 @@ function build_read_command(getScanner) {
|
|
|
10340
11368
|
console.log(JSON.stringify({ error: animValidationError }, null, 2));
|
|
10341
11369
|
process.exit(1);
|
|
10342
11370
|
}
|
|
10343
|
-
const content =
|
|
11371
|
+
const content = import_fs17.readFileSync(file, "utf-8");
|
|
10344
11372
|
const clip = parse_animation_yaml(content, options.curves === true);
|
|
10345
11373
|
if (!clip) {
|
|
10346
11374
|
console.log(JSON.stringify({ error: `No AnimationClip found in "${file}". Is this an .anim file?` }, null, 2));
|
|
@@ -10401,7 +11429,7 @@ function build_read_command(getScanner) {
|
|
|
10401
11429
|
console.log(JSON.stringify({ error: ctrlValidationError }, null, 2));
|
|
10402
11430
|
process.exit(1);
|
|
10403
11431
|
}
|
|
10404
|
-
const content =
|
|
11432
|
+
const content = import_fs17.readFileSync(file, "utf-8");
|
|
10405
11433
|
const blocks = split_yaml_blocks(content);
|
|
10406
11434
|
const controller_block = blocks.find((b) => b.class_id === 91);
|
|
10407
11435
|
if (!controller_block) {
|
|
@@ -10631,7 +11659,7 @@ function build_read_command(getScanner) {
|
|
|
10631
11659
|
process.exit(1);
|
|
10632
11660
|
}
|
|
10633
11661
|
const assetsDir = import_path8.join(import_path8.resolve(project_path), "Assets");
|
|
10634
|
-
if (!
|
|
11662
|
+
if (!import_fs17.existsSync(assetsDir)) {
|
|
10635
11663
|
console.log(JSON.stringify({ error: `Assets directory not found in "${project_path}"` }, null, 2));
|
|
10636
11664
|
process.exit(1);
|
|
10637
11665
|
}
|
|
@@ -10660,7 +11688,7 @@ function build_read_command(getScanner) {
|
|
|
10660
11688
|
const guid_pattern = `guid: ${guid}`;
|
|
10661
11689
|
for (const f of files) {
|
|
10662
11690
|
try {
|
|
10663
|
-
const fc =
|
|
11691
|
+
const fc = import_fs17.readFileSync(f, "utf-8");
|
|
10664
11692
|
if (fc.includes(guid_pattern)) {
|
|
10665
11693
|
const rel = import_path8.relative(import_path8.resolve(project_path), f);
|
|
10666
11694
|
const ftype = categorize_asset(f);
|
|
@@ -10690,7 +11718,7 @@ function build_read_command(getScanner) {
|
|
|
10690
11718
|
cmd.command("unused <project_path>").description("Find potentially unused assets (zero inbound GUID references)").option("--type <type>", "Filter to specific asset types").option("--ignore <glob>", "Exclude paths matching this pattern").option("--max <n>", "Maximum results to return (default 200)", "200").option("-j, --json", "Output as JSON").action((project_path, options) => {
|
|
10691
11719
|
const resolvedProject = import_path8.resolve(project_path);
|
|
10692
11720
|
const assetsDir = import_path8.join(resolvedProject, "Assets");
|
|
10693
|
-
if (!
|
|
11721
|
+
if (!import_fs17.existsSync(assetsDir)) {
|
|
10694
11722
|
console.log(JSON.stringify({ error: `Assets directory not found in "${project_path}"` }, null, 2));
|
|
10695
11723
|
process.exit(1);
|
|
10696
11724
|
}
|
|
@@ -10718,7 +11746,7 @@ function build_read_command(getScanner) {
|
|
|
10718
11746
|
const guid_re = /guid:\s*([a-f0-9]{32})/g;
|
|
10719
11747
|
for (const f of files) {
|
|
10720
11748
|
try {
|
|
10721
|
-
const fc =
|
|
11749
|
+
const fc = import_fs17.readFileSync(f, "utf-8");
|
|
10722
11750
|
let gm;
|
|
10723
11751
|
while ((gm = guid_re.exec(fc)) !== null) {
|
|
10724
11752
|
referenced_guids.add(gm[1]);
|
|
@@ -10729,8 +11757,8 @@ function build_read_command(getScanner) {
|
|
|
10729
11757
|
}
|
|
10730
11758
|
const buildSettingsPath = import_path8.join(resolvedProject, "ProjectSettings", "EditorBuildSettings.asset");
|
|
10731
11759
|
const build_scene_guids = new Set;
|
|
10732
|
-
if (
|
|
10733
|
-
const bsc =
|
|
11760
|
+
if (import_fs17.existsSync(buildSettingsPath)) {
|
|
11761
|
+
const bsc = import_fs17.readFileSync(buildSettingsPath, "utf-8");
|
|
10734
11762
|
let bm;
|
|
10735
11763
|
while ((bm = guid_re.exec(bsc)) !== null) {
|
|
10736
11764
|
build_scene_guids.add(bm[1]);
|
|
@@ -10848,19 +11876,11 @@ function build_read_command(getScanner) {
|
|
|
10848
11876
|
}
|
|
10849
11877
|
console.log(JSON.stringify({ file, ...ia }, null, 2));
|
|
10850
11878
|
});
|
|
10851
|
-
cmd.command("prefab").argument("[file]").allowUnknownOption().action(() => {
|
|
10852
|
-
console.log(JSON.stringify({
|
|
10853
|
-
success: false,
|
|
10854
|
-
error: '"read prefab" does not exist. Use "read scene" -- it handles both .unity and .prefab files.',
|
|
10855
|
-
correct_usage: "unity-agentic-tools read scene <file.prefab>"
|
|
10856
|
-
}, null, 2));
|
|
10857
|
-
process.exitCode = 1;
|
|
10858
|
-
});
|
|
10859
11879
|
return cmd;
|
|
10860
11880
|
}
|
|
10861
11881
|
|
|
10862
11882
|
// src/cmd-update.ts
|
|
10863
|
-
var
|
|
11883
|
+
var import_fs18 = require("fs");
|
|
10864
11884
|
var import_path9 = require("path");
|
|
10865
11885
|
|
|
10866
11886
|
// src/animator-utils.ts
|
|
@@ -11006,10 +12026,10 @@ function resolve_transform_id(scanner, file, identifier) {
|
|
|
11006
12026
|
if (result && !result.is_error) {
|
|
11007
12027
|
const transform = result.components?.find((c) => c.class_id === 4 || c.class_id === 224);
|
|
11008
12028
|
if (transform)
|
|
11009
|
-
return { transform_id:
|
|
12029
|
+
return { transform_id: transform.file_id };
|
|
11010
12030
|
}
|
|
11011
12031
|
if (/^-?\d+$/.test(identifier)) {
|
|
11012
|
-
return { transform_id:
|
|
12032
|
+
return { transform_id: identifier };
|
|
11013
12033
|
}
|
|
11014
12034
|
return { error: `Could not resolve "${identifier}" to a Transform component. Use a GameObject name or transform fileID.` };
|
|
11015
12035
|
}
|
|
@@ -11027,7 +12047,7 @@ function build_update_command(getScanner) {
|
|
|
11027
12047
|
if (!result.success)
|
|
11028
12048
|
process.exitCode = 1;
|
|
11029
12049
|
});
|
|
11030
|
-
cmd.command("component <file> <file_id> <property> <value>").description("Edit any component property by file ID. Supports dotted paths (m_LocalPosition.x) and array paths (m_Materials.Array.data[0])").option("-j, --json", "Output as JSON").action((file, file_id, property, value, _options) => {
|
|
12050
|
+
cmd.command("component <file> <file_id> <property> <value>").description("Edit any component property by file ID. Supports dotted paths (m_LocalPosition.x) and array paths (m_Materials.Array.data[0]). Quote paths with brackets or use dot notation (data.0) to avoid shell glob expansion").option("-j, --json", "Output as JSON").action((file, file_id, property, value, _options) => {
|
|
11031
12051
|
if (property === "m_RootOrder") {
|
|
11032
12052
|
const num = Number(value);
|
|
11033
12053
|
if (!Number.isInteger(num) || num < 0) {
|
|
@@ -11183,14 +12203,71 @@ function build_update_command(getScanner) {
|
|
|
11183
12203
|
if (!result.success)
|
|
11184
12204
|
process.exitCode = 1;
|
|
11185
12205
|
});
|
|
11186
|
-
prefab_cmd.command("override <file> <prefab_instance> <property_path> <value>").description("Edit or add a property override in a PrefabInstance m_Modifications list").option("--object-reference <ref>", "Object reference value (default: {fileID: 0})").option("--target <target>", 'Target reference for new entries (e.g., "{fileID: 400000, guid: abc, type: 3}")').option("-j, --json", "Output as JSON").action((file, prefab_instance, property_path, value, options) => {
|
|
12206
|
+
prefab_cmd.command("override <file> <prefab_instance> <property_path> <value>").description("Edit or add a property override in a PrefabInstance m_Modifications list. Quote paths with brackets or use dot notation (data.0) to avoid shell glob expansion").option("--object-reference <ref>", "Object reference value (default: {fileID: 0})").option("--managed-reference <id>", "Managed reference ID -- placed in value: field, forces objectReference: {fileID: 0}").option("--target <target>", 'Target reference for new entries (e.g., "{fileID: 400000, guid: abc, type: 3}")').option("-j, --json", "Output as JSON").action((file, prefab_instance, property_path, value, options) => {
|
|
12207
|
+
if (options.objectReference && !/^\{fileID:/.test(options.objectReference)) {
|
|
12208
|
+
console.error(`Warning: --object-reference "${options.objectReference}" does not look like a Unity object reference ({fileID: ...}). For managed reference IDs, use --managed-reference instead or pass the ID as the <value> argument.`);
|
|
12209
|
+
}
|
|
11187
12210
|
const result = editPrefabOverride({
|
|
11188
12211
|
file_path: file,
|
|
11189
12212
|
prefab_instance,
|
|
11190
12213
|
property_path,
|
|
11191
12214
|
new_value: value,
|
|
11192
12215
|
object_reference: options.objectReference,
|
|
11193
|
-
target: options.target
|
|
12216
|
+
target: options.target,
|
|
12217
|
+
managed_reference: options.managedReference
|
|
12218
|
+
});
|
|
12219
|
+
console.log(JSON.stringify(result, null, 2));
|
|
12220
|
+
if (!result.success)
|
|
12221
|
+
process.exitCode = 1;
|
|
12222
|
+
});
|
|
12223
|
+
prefab_cmd.command("batch-overrides <file> <prefab_instance> <edits_json>").description('Batch edit multiple property overrides in a PrefabInstance. JSON format: [{"property_path":"...","value":"...","target":"...","object_reference":"..."}]').option("-j, --json", "Output as JSON").action((file, prefab_instance, edits_json, _options) => {
|
|
12224
|
+
let raw_edits;
|
|
12225
|
+
try {
|
|
12226
|
+
const parsed = JSON.parse(edits_json);
|
|
12227
|
+
if (!Array.isArray(parsed)) {
|
|
12228
|
+
console.log(JSON.stringify({ success: false, error: 'Edits must be a JSON array. Format: [{"property_path":"...","value":"..."}]' }, null, 2));
|
|
12229
|
+
process.exit(1);
|
|
12230
|
+
}
|
|
12231
|
+
raw_edits = parsed;
|
|
12232
|
+
} catch {
|
|
12233
|
+
console.log(JSON.stringify({ success: false, error: "Invalid JSON for edits" }, null, 2));
|
|
12234
|
+
process.exit(1);
|
|
12235
|
+
}
|
|
12236
|
+
const edits = raw_edits.map((e) => ({
|
|
12237
|
+
property_path: String(e.property_path ?? ""),
|
|
12238
|
+
value: String(e.new_value ?? e.value ?? ""),
|
|
12239
|
+
object_reference: e.object_reference != null ? String(e.object_reference) : undefined,
|
|
12240
|
+
target: e.target != null ? String(e.target) : undefined,
|
|
12241
|
+
managed_reference: e.managed_reference != null ? String(e.managed_reference) : undefined
|
|
12242
|
+
}));
|
|
12243
|
+
if (edits.length === 0) {
|
|
12244
|
+
console.log(JSON.stringify({ success: false, error: 'Empty edits array. Provide at least one edit: [{"property_path":"...","value":"..."}]' }, null, 2));
|
|
12245
|
+
process.exit(1);
|
|
12246
|
+
}
|
|
12247
|
+
for (const edit of edits) {
|
|
12248
|
+
if (!edit.property_path) {
|
|
12249
|
+
console.log(JSON.stringify({ success: false, error: 'Missing "property_path" in edit entry. JSON format: [{"property_path":"...","value":"..."}]' }, null, 2));
|
|
12250
|
+
process.exit(1);
|
|
12251
|
+
}
|
|
12252
|
+
if (!edit.value && !edit.object_reference && !edit.managed_reference) {
|
|
12253
|
+
console.log(JSON.stringify({ success: false, error: `Missing "value" for override "${edit.property_path}". Provide "value", "object_reference", or "managed_reference".` }, null, 2));
|
|
12254
|
+
process.exit(1);
|
|
12255
|
+
}
|
|
12256
|
+
}
|
|
12257
|
+
const result = batchEditPrefabOverrides(file, prefab_instance, edits);
|
|
12258
|
+
console.log(JSON.stringify(result, null, 2));
|
|
12259
|
+
if (!result.success)
|
|
12260
|
+
process.exitCode = 1;
|
|
12261
|
+
});
|
|
12262
|
+
prefab_cmd.command("managed-reference <file> <prefab_instance> <field_path> <type_name>").description("Add a [SerializeReference] managed reference to a prefab override. Auto-generates rid and creates type/data/version override entries.").requiredOption("--target <ref>", 'Target reference (e.g., "{fileID: 400000, guid: ..., type: 3}")').option("--index <n>", "Array index (default: 0)", "0").option("-p, --project <path>", "Unity project path (for type registry)").option("-j, --json", "Output as JSON").action((file, prefab_instance, field_path, type_name, options) => {
|
|
12263
|
+
const result = addPrefabManagedReference({
|
|
12264
|
+
file_path: file,
|
|
12265
|
+
prefab_instance,
|
|
12266
|
+
field_path,
|
|
12267
|
+
type_name,
|
|
12268
|
+
target: options.target,
|
|
12269
|
+
index: parseInt(options.index, 10),
|
|
12270
|
+
project_path: options.project
|
|
11194
12271
|
});
|
|
11195
12272
|
console.log(JSON.stringify(result, null, 2));
|
|
11196
12273
|
if (!result.success)
|
|
@@ -11222,7 +12299,7 @@ function build_update_command(getScanner) {
|
|
|
11222
12299
|
process.exitCode = 1;
|
|
11223
12300
|
}
|
|
11224
12301
|
});
|
|
11225
|
-
cmd.command("array <file> <file_id> <array_property> <action> [args...]").description("Insert, append, or remove array elements in a component. Insert: <index> <value> or <value> --index <n>. Append: <value>. Remove: <index> or --index <n>.").option("--index <n>", "Index for insert/remove").option("-j, --json", "Output as JSON").action((file, file_id, array_property, action, args, options) => {
|
|
12302
|
+
cmd.command("array <file> <file_id> <array_property> <action> [args...]").description("Insert, append, or remove array elements in a component. Insert: <index> <value> or <value> --index <n>. Append: <value>. Remove: <index> or --index <n>. Quote paths with brackets or use dot notation (data.0) to avoid shell glob expansion").option("--index <n>", "Index for insert/remove").option("-j, --json", "Output as JSON").action((file, file_id, array_property, action, args, options) => {
|
|
11226
12303
|
if (action !== "insert" && action !== "append" && action !== "remove") {
|
|
11227
12304
|
console.log(JSON.stringify({ success: false, error: 'Action must be "insert", "append", or "remove"' }, null, 2));
|
|
11228
12305
|
process.exit(1);
|
|
@@ -11357,7 +12434,7 @@ function build_update_command(getScanner) {
|
|
|
11357
12434
|
if (!result.success)
|
|
11358
12435
|
process.exitCode = 1;
|
|
11359
12436
|
});
|
|
11360
|
-
prefab_cmd.command("remove-override <file> <prefab_instance> <property_path>").description("Remove a property override from a PrefabInstance").option("--target <ref>", "Target reference to match (for disambiguation)").option("-j, --json", "Output as JSON").action((file, prefab_instance, property_path, options) => {
|
|
12437
|
+
prefab_cmd.command("remove-override <file> <prefab_instance> <property_path>").description("Remove a property override from a PrefabInstance. Quote paths with brackets or use dot notation (data.0) to avoid shell glob expansion").option("--target <ref>", "Target reference to match (for disambiguation)").option("-j, --json", "Output as JSON").action((file, prefab_instance, property_path, options) => {
|
|
11361
12438
|
const result = removePrefabOverride({
|
|
11362
12439
|
file_path: file,
|
|
11363
12440
|
prefab_instance,
|
|
@@ -11418,11 +12495,11 @@ function build_update_command(getScanner) {
|
|
|
11418
12495
|
}
|
|
11419
12496
|
}
|
|
11420
12497
|
}).action((file, options) => {
|
|
11421
|
-
if (!
|
|
12498
|
+
if (!import_fs18.existsSync(file)) {
|
|
11422
12499
|
console.log(JSON.stringify({ success: false, error: `File not found: ${file}` }, null, 2));
|
|
11423
12500
|
process.exit(1);
|
|
11424
12501
|
}
|
|
11425
|
-
let content =
|
|
12502
|
+
let content = import_fs18.readFileSync(file, "utf-8");
|
|
11426
12503
|
const changes = [];
|
|
11427
12504
|
if (options.shader) {
|
|
11428
12505
|
const guid = options.shader;
|
|
@@ -11571,7 +12648,7 @@ ${lm[1]} - ${kw}
|
|
|
11571
12648
|
process.exitCode = 1;
|
|
11572
12649
|
return;
|
|
11573
12650
|
}
|
|
11574
|
-
|
|
12651
|
+
import_fs18.writeFileSync(file, content, "utf-8");
|
|
11575
12652
|
console.log(JSON.stringify({ success: true, file, changes }, null, 2));
|
|
11576
12653
|
});
|
|
11577
12654
|
cmd.command("meta [file]").description("Edit Unity .meta file importer settings").option("--set <key=value>", "Set an importer setting (e.g., isReadable=1)", (v, p) => [...p, v], []).option("--max-size <n>", "Set TextureImporter maxTextureSize").option("--compression <type>", "Set textureCompression (0=None, 1=LowQuality, 2=Normal, 3=HighQuality)").option("--filter-mode <mode>", "Set filterMode (0=Point, 1=Bilinear, 2=Trilinear)").option("--read-write", "Enable isReadable").option("--no-read-write", "Disable isReadable").option("--batch <glob>", "Apply to all matching files").option("--dry-run", "Preview changes without writing").option("-j, --json", "Output as JSON").action((file, options) => {
|
|
@@ -11632,9 +12709,9 @@ ${lm[1]} - ${kw}
|
|
|
11632
12709
|
const suffix = import_path9.basename(pattern).replace(/^\*+/, "");
|
|
11633
12710
|
const meta_files = [];
|
|
11634
12711
|
const scan = (d) => {
|
|
11635
|
-
for (const entry of
|
|
12712
|
+
for (const entry of import_fs18.readdirSync(d)) {
|
|
11636
12713
|
const full = import_path9.join(d, entry);
|
|
11637
|
-
if (
|
|
12714
|
+
if (import_fs18.statSync(full).isDirectory()) {
|
|
11638
12715
|
if (pattern.includes("**"))
|
|
11639
12716
|
scan(full);
|
|
11640
12717
|
} else if (entry.endsWith(suffix)) {
|
|
@@ -11642,7 +12719,7 @@ ${lm[1]} - ${kw}
|
|
|
11642
12719
|
}
|
|
11643
12720
|
}
|
|
11644
12721
|
};
|
|
11645
|
-
if (
|
|
12722
|
+
if (import_fs18.existsSync(dir))
|
|
11646
12723
|
scan(dir);
|
|
11647
12724
|
if (meta_files.length === 0) {
|
|
11648
12725
|
console.log(JSON.stringify({ success: false, error: `No files matched pattern: ${glob_pattern}` }, null, 2));
|
|
@@ -11650,7 +12727,7 @@ ${lm[1]} - ${kw}
|
|
|
11650
12727
|
}
|
|
11651
12728
|
const results = [];
|
|
11652
12729
|
for (const mf of meta_files) {
|
|
11653
|
-
let mc =
|
|
12730
|
+
let mc = import_fs18.readFileSync(mf, "utf-8");
|
|
11654
12731
|
const file_changes = [];
|
|
11655
12732
|
for (const edit of edits) {
|
|
11656
12733
|
const re = new RegExp(`^(\\s*${edit.key}:)[ \\t]*.*$`, "m");
|
|
@@ -11661,7 +12738,7 @@ ${lm[1]} - ${kw}
|
|
|
11661
12738
|
}
|
|
11662
12739
|
if (file_changes.length > 0) {
|
|
11663
12740
|
if (!options.dryRun)
|
|
11664
|
-
|
|
12741
|
+
import_fs18.writeFileSync(mf, mc, "utf-8");
|
|
11665
12742
|
results.push({ file: mf, changes: file_changes });
|
|
11666
12743
|
}
|
|
11667
12744
|
}
|
|
@@ -11674,11 +12751,11 @@ ${lm[1]} - ${kw}
|
|
|
11674
12751
|
}, null, 2));
|
|
11675
12752
|
return;
|
|
11676
12753
|
}
|
|
11677
|
-
if (!
|
|
12754
|
+
if (!import_fs18.existsSync(metaPath)) {
|
|
11678
12755
|
console.log(JSON.stringify({ success: false, error: `Meta file not found: ${metaPath}` }, null, 2));
|
|
11679
12756
|
process.exit(1);
|
|
11680
12757
|
}
|
|
11681
|
-
let content =
|
|
12758
|
+
let content = import_fs18.readFileSync(metaPath, "utf-8");
|
|
11682
12759
|
const changes = [];
|
|
11683
12760
|
for (const edit of edits) {
|
|
11684
12761
|
const re = new RegExp(`^(\\s*${edit.key}:)[ \\t]*.*$`, "m");
|
|
@@ -11693,11 +12770,11 @@ ${lm[1]} - ${kw}
|
|
|
11693
12770
|
console.log(JSON.stringify({ success: true, dry_run: true, file: metaPath, changes }, null, 2));
|
|
11694
12771
|
return;
|
|
11695
12772
|
}
|
|
11696
|
-
|
|
12773
|
+
import_fs18.writeFileSync(metaPath, content, "utf-8");
|
|
11697
12774
|
console.log(JSON.stringify({ success: true, file: metaPath, changes }, null, 2));
|
|
11698
12775
|
});
|
|
11699
12776
|
cmd.command("animation <file>").description("Edit AnimationClip settings and events").option("--set <property=value>", "Set a clip property (e.g., wrap-mode=2 for Loop)", (v, p) => [...p, v], []).option("--add-event <time,function[,data]>", "Add an animation event (e.g., 0.5,OnFootstep,left)", (v, p) => [...p, v], []).option("--remove-event <index>", "Remove an animation event by index (0-based)").option("-j, --json", "Output as JSON").action((file, options) => {
|
|
11700
|
-
if (!
|
|
12777
|
+
if (!import_fs18.existsSync(file)) {
|
|
11701
12778
|
console.log(JSON.stringify({ success: false, error: `File not found: ${file}` }, null, 2));
|
|
11702
12779
|
process.exit(1);
|
|
11703
12780
|
}
|
|
@@ -11705,7 +12782,7 @@ ${lm[1]} - ${kw}
|
|
|
11705
12782
|
console.log(JSON.stringify({ success: false, error: `File is not an AnimationClip (.anim): ${file}` }, null, 2));
|
|
11706
12783
|
process.exit(1);
|
|
11707
12784
|
}
|
|
11708
|
-
let content =
|
|
12785
|
+
let content = import_fs18.readFileSync(file, "utf-8");
|
|
11709
12786
|
const changes = [];
|
|
11710
12787
|
const property_map = {
|
|
11711
12788
|
"wrap-mode": "m_WrapMode",
|
|
@@ -11866,16 +12943,16 @@ ${event_yaml}
|
|
|
11866
12943
|
process.exitCode = 1;
|
|
11867
12944
|
return;
|
|
11868
12945
|
}
|
|
11869
|
-
|
|
12946
|
+
import_fs18.writeFileSync(file, content, "utf-8");
|
|
11870
12947
|
console.log(JSON.stringify({ success: true, file, changes }, null, 2));
|
|
11871
12948
|
});
|
|
11872
12949
|
const PARAM_TYPE_MAP = { float: 1, int: 3, bool: 4, trigger: 9 };
|
|
11873
12950
|
cmd.command("animator <file>").description("Edit AnimatorController parameters").option("--add-parameter <name>", "Add a new parameter").option("--type <float|int|bool|trigger>", "Parameter type (required with --add-parameter)").option("--remove-parameter <name>", "Remove a parameter by name").option("--set-default <param=value>", "Set parameter default value (e.g., Speed=1.5)", (v, p) => [...p, v], []).option("-j, --json", "Output as JSON").action((file, options) => {
|
|
11874
|
-
if (!
|
|
12951
|
+
if (!import_fs18.existsSync(file)) {
|
|
11875
12952
|
console.log(JSON.stringify({ success: false, error: `File not found: ${file}` }, null, 2));
|
|
11876
12953
|
process.exit(1);
|
|
11877
12954
|
}
|
|
11878
|
-
let content =
|
|
12955
|
+
let content = import_fs18.readFileSync(file, "utf-8");
|
|
11879
12956
|
const had_crlf = content.includes(`\r
|
|
11880
12957
|
`);
|
|
11881
12958
|
if (had_crlf)
|
|
@@ -11977,7 +13054,7 @@ $1`);
|
|
|
11977
13054
|
if (had_crlf)
|
|
11978
13055
|
content = content.replace(/\n/g, `\r
|
|
11979
13056
|
`);
|
|
11980
|
-
|
|
13057
|
+
import_fs18.writeFileSync(file, content, "utf-8");
|
|
11981
13058
|
console.log(JSON.stringify({ success: true, file, changes }, null, 2));
|
|
11982
13059
|
});
|
|
11983
13060
|
cmd.command("sibling-index <file> <object_name> <index>").description("Set the sibling index of a GameObject, renumbering all siblings").option("-j, --json", "Output as JSON").action((file, object_name, index_str, _options) => {
|
|
@@ -11987,7 +13064,7 @@ $1`);
|
|
|
11987
13064
|
process.exitCode = 1;
|
|
11988
13065
|
return;
|
|
11989
13066
|
}
|
|
11990
|
-
if (!
|
|
13067
|
+
if (!import_fs18.existsSync(file)) {
|
|
11991
13068
|
console.log(JSON.stringify({ success: false, error: `File not found: ${file}` }, null, 2));
|
|
11992
13069
|
process.exitCode = 1;
|
|
11993
13070
|
return;
|
|
@@ -12182,7 +13259,7 @@ $1`);
|
|
|
12182
13259
|
console.log(JSON.stringify({ success: true, file, changes }, null, 2));
|
|
12183
13260
|
});
|
|
12184
13261
|
cmd.command("animation-curves <file>").description("Add, remove, or modify animation curves in an .anim file").option("--add-curve <json>", 'Add a curve (JSON: {"type":"float","path":"Body","attribute":"m_Alpha","classID":23,"keyframes":[{"time":0,"value":1}]})').option("--remove-curve <spec>", "Remove a curve by path:attribute (e.g., Body/Mesh:m_Alpha)").option("--set-keyframes <json>", 'Replace keyframes (JSON: {"curve":"path:attribute","keyframes":[{"time":0,"value":10}]})').option("-j, --json", "Output as JSON").action((file, options) => {
|
|
12185
|
-
if (!
|
|
13262
|
+
if (!import_fs18.existsSync(file)) {
|
|
12186
13263
|
console.log(JSON.stringify({ success: false, error: `File not found: ${file}` }, null, 2));
|
|
12187
13264
|
process.exitCode = 1;
|
|
12188
13265
|
return;
|
|
@@ -12192,7 +13269,7 @@ $1`);
|
|
|
12192
13269
|
process.exitCode = 1;
|
|
12193
13270
|
return;
|
|
12194
13271
|
}
|
|
12195
|
-
let content =
|
|
13272
|
+
let content = import_fs18.readFileSync(file, "utf-8");
|
|
12196
13273
|
const had_crlf = content.includes(`\r
|
|
12197
13274
|
`);
|
|
12198
13275
|
if (had_crlf)
|
|
@@ -12490,16 +13567,16 @@ ${curve_yaml}`);
|
|
|
12490
13567
|
if (had_crlf)
|
|
12491
13568
|
content = content.replace(/\n/g, `\r
|
|
12492
13569
|
`);
|
|
12493
|
-
|
|
13570
|
+
import_fs18.writeFileSync(file, content, "utf-8");
|
|
12494
13571
|
console.log(JSON.stringify({ success: true, file, changes }, null, 2));
|
|
12495
13572
|
});
|
|
12496
13573
|
cmd.command("animator-state <file>").description("Add/remove states and transitions in an AnimatorController").option("--add-state <name>", "Add a new AnimatorState").option("--motion <guid-or-path>", "Motion clip GUID or file path (companion to --add-state)").option("--layer <name>", "Target layer name (default: first layer)").option("--speed <n>", "State speed (companion to --add-state, default: 1)").option("--remove-state <name>", "Remove a state and all its transitions").option("--add-transition <src:dst>", 'Add a transition (use "any" for AnyState source)').option("--condition <param,mode,threshold>", "Transition condition (repeatable)", (v, p) => [...p, v], []).option("--has-exit-time", "Enable exit time on transition").option("--exit-time <n>", "Exit time value (default: 0.75)").option("--duration <n>", "Transition duration (default: 0.25)").option("--remove-transition <src:dst>", "Remove a transition by source:destination state names").option("--set-default-state <name>", "Set the default state in the state machine").option("-j, --json", "Output as JSON").action((file, options) => {
|
|
12497
|
-
if (!
|
|
13574
|
+
if (!import_fs18.existsSync(file)) {
|
|
12498
13575
|
console.log(JSON.stringify({ success: false, error: `File not found: ${file}` }, null, 2));
|
|
12499
13576
|
process.exitCode = 1;
|
|
12500
13577
|
return;
|
|
12501
13578
|
}
|
|
12502
|
-
let content =
|
|
13579
|
+
let content = import_fs18.readFileSync(file, "utf-8");
|
|
12503
13580
|
const had_crlf = content.includes(`\r
|
|
12504
13581
|
`);
|
|
12505
13582
|
if (had_crlf)
|
|
@@ -12838,10 +13915,34 @@ $1`);
|
|
|
12838
13915
|
if (had_crlf)
|
|
12839
13916
|
content = content.replace(/\n/g, `\r
|
|
12840
13917
|
`);
|
|
12841
|
-
|
|
13918
|
+
import_fs18.writeFileSync(file, content, "utf-8");
|
|
12842
13919
|
console.log(JSON.stringify({ success: true, file, changes }, null, 2));
|
|
12843
13920
|
});
|
|
12844
13921
|
cmd.addCommand(prefab_cmd);
|
|
13922
|
+
cmd.command("managed-reference <file> <component_id> <field_path> <type_name>").description('Add a managed reference (SerializeReference) to a component field. Type can be "Namespace.ClassName" (registry lookup) or "Assembly Namespace.ClassName" (manual).').option("-p, --project <path>", "Unity project path (for type registry)").option("--append", "Append to array (do not update field rid)").option("--properties <json>", `JSON object of initial field values for the data block (e.g. '{"damage": "10"}')`).option("-j, --json", "Output as JSON").action((file, component_id, field_path, type_name, options) => {
|
|
13923
|
+
let initial_values;
|
|
13924
|
+
if (options.properties) {
|
|
13925
|
+
try {
|
|
13926
|
+
initial_values = JSON.parse(options.properties);
|
|
13927
|
+
} catch {
|
|
13928
|
+
console.log(JSON.stringify({ success: false, error: `Invalid JSON for --properties: ${options.properties}` }, null, 2));
|
|
13929
|
+
process.exitCode = 1;
|
|
13930
|
+
return;
|
|
13931
|
+
}
|
|
13932
|
+
}
|
|
13933
|
+
const result = editManagedReference({
|
|
13934
|
+
file_path: file,
|
|
13935
|
+
file_id: component_id,
|
|
13936
|
+
field_path,
|
|
13937
|
+
type_name,
|
|
13938
|
+
project_path: options.project,
|
|
13939
|
+
append: options.append === true,
|
|
13940
|
+
initial_values
|
|
13941
|
+
});
|
|
13942
|
+
console.log(JSON.stringify(result, null, 2));
|
|
13943
|
+
if (!result.success)
|
|
13944
|
+
process.exitCode = 1;
|
|
13945
|
+
});
|
|
12845
13946
|
return cmd;
|
|
12846
13947
|
}
|
|
12847
13948
|
|
|
@@ -12907,16 +14008,16 @@ function build_delete_command() {
|
|
|
12907
14008
|
var import_path11 = require("path");
|
|
12908
14009
|
|
|
12909
14010
|
// src/editor-client.ts
|
|
12910
|
-
var
|
|
14011
|
+
var import_fs19 = require("fs");
|
|
12911
14012
|
var import_path10 = require("path");
|
|
12912
14013
|
function read_editor_config(project_path) {
|
|
12913
14014
|
const config_path = import_path10.join(project_path, ".unity-agentic", "editor.json");
|
|
12914
|
-
if (!
|
|
14015
|
+
if (!import_fs19.existsSync(config_path)) {
|
|
12915
14016
|
return { error: `Editor bridge not found at ${config_path}. Is the Unity Editor running with the bridge package installed?` };
|
|
12916
14017
|
}
|
|
12917
14018
|
let config;
|
|
12918
14019
|
try {
|
|
12919
|
-
const raw =
|
|
14020
|
+
const raw = import_fs19.readFileSync(config_path, "utf-8");
|
|
12920
14021
|
config = JSON.parse(raw);
|
|
12921
14022
|
} catch (err) {
|
|
12922
14023
|
return { error: `Failed to parse editor.json: ${err instanceof Error ? err.message : String(err)}` };
|
|
@@ -12929,23 +14030,45 @@ function read_editor_config(project_path) {
|
|
|
12929
14030
|
}
|
|
12930
14031
|
return config;
|
|
12931
14032
|
}
|
|
14033
|
+
var RETRYABLE_CODES = new Set([-32000, -32002, -32003]);
|
|
14034
|
+
var RETRY_DELAYS = [500, 1000, 2000];
|
|
12932
14035
|
async function call_editor(options) {
|
|
12933
|
-
const
|
|
14036
|
+
const maxRetries = options.retries ?? 2;
|
|
14037
|
+
let lastResponse;
|
|
14038
|
+
for (let attempt = 0;attempt <= maxRetries; attempt++) {
|
|
14039
|
+
lastResponse = await call_editor_once(options);
|
|
14040
|
+
if (!lastResponse.error || !RETRYABLE_CODES.has(lastResponse.error.code)) {
|
|
14041
|
+
return lastResponse;
|
|
14042
|
+
}
|
|
14043
|
+
if (attempt < maxRetries) {
|
|
14044
|
+
const delay = RETRY_DELAYS[Math.min(attempt, RETRY_DELAYS.length - 1)];
|
|
14045
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
14046
|
+
}
|
|
14047
|
+
}
|
|
14048
|
+
return lastResponse;
|
|
14049
|
+
}
|
|
14050
|
+
function call_editor_once(options) {
|
|
14051
|
+
const { method, params, timeout = 1e4, no_wait } = options;
|
|
12934
14052
|
const config = resolve_config(options);
|
|
12935
14053
|
if ("error" in config) {
|
|
12936
|
-
return {
|
|
14054
|
+
return Promise.resolve({
|
|
12937
14055
|
jsonrpc: "2.0",
|
|
12938
14056
|
id: "0",
|
|
12939
14057
|
error: { code: -32000, message: config.error }
|
|
12940
|
-
};
|
|
14058
|
+
});
|
|
12941
14059
|
}
|
|
12942
14060
|
const url = `ws://127.0.0.1:${config.port}/unity-agentic`;
|
|
12943
14061
|
const request_id = generate_id();
|
|
14062
|
+
const wire_params = { ...params };
|
|
14063
|
+
if (timeout !== 1e4)
|
|
14064
|
+
wire_params._timeout = timeout;
|
|
14065
|
+
if (no_wait)
|
|
14066
|
+
wire_params.no_wait = true;
|
|
12944
14067
|
const request = {
|
|
12945
14068
|
jsonrpc: "2.0",
|
|
12946
14069
|
id: request_id,
|
|
12947
14070
|
method,
|
|
12948
|
-
...
|
|
14071
|
+
...Object.keys(wire_params).length > 0 ? { params: wire_params } : {}
|
|
12949
14072
|
};
|
|
12950
14073
|
return new Promise((resolve7) => {
|
|
12951
14074
|
let resolved = false;
|
|
@@ -12967,6 +14090,20 @@ async function call_editor(options) {
|
|
|
12967
14090
|
ws = new WebSocket(url);
|
|
12968
14091
|
ws.onopen = () => {
|
|
12969
14092
|
ws.send(JSON.stringify(request));
|
|
14093
|
+
if (no_wait && !resolved) {
|
|
14094
|
+
resolved = true;
|
|
14095
|
+
clearTimeout(timer);
|
|
14096
|
+
setTimeout(() => {
|
|
14097
|
+
try {
|
|
14098
|
+
ws.close();
|
|
14099
|
+
} catch {}
|
|
14100
|
+
}, 200);
|
|
14101
|
+
resolve7({
|
|
14102
|
+
jsonrpc: "2.0",
|
|
14103
|
+
id: request_id,
|
|
14104
|
+
result: { queued: true }
|
|
14105
|
+
});
|
|
14106
|
+
}
|
|
12970
14107
|
};
|
|
12971
14108
|
ws.onmessage = (event) => {
|
|
12972
14109
|
try {
|
|
@@ -13022,42 +14159,75 @@ async function stream_editor(options) {
|
|
|
13022
14159
|
if ("error" in config) {
|
|
13023
14160
|
throw new Error(config.error);
|
|
13024
14161
|
}
|
|
13025
|
-
const
|
|
13026
|
-
|
|
13027
|
-
|
|
13028
|
-
jsonrpc: "2.0",
|
|
13029
|
-
id: request_id,
|
|
13030
|
-
method,
|
|
13031
|
-
...params ? { params } : {}
|
|
13032
|
-
};
|
|
14162
|
+
const MAX_RECONNECTS = 5;
|
|
14163
|
+
let reconnect_count = 0;
|
|
14164
|
+
let stopped = false;
|
|
13033
14165
|
return new Promise((resolve7, reject) => {
|
|
13034
|
-
let
|
|
13035
|
-
|
|
13036
|
-
|
|
13037
|
-
|
|
13038
|
-
|
|
13039
|
-
|
|
13040
|
-
|
|
13041
|
-
|
|
13042
|
-
|
|
13043
|
-
|
|
13044
|
-
|
|
13045
|
-
|
|
13046
|
-
|
|
13047
|
-
|
|
13048
|
-
try {
|
|
13049
|
-
const data = JSON.parse(String(event.data));
|
|
13050
|
-
if ("method" in data && !("id" in data)) {
|
|
13051
|
-
on_event(data);
|
|
14166
|
+
let resolved = false;
|
|
14167
|
+
function connect(url) {
|
|
14168
|
+
const ws = new WebSocket(url);
|
|
14169
|
+
const request_id = generate_id();
|
|
14170
|
+
const request = {
|
|
14171
|
+
jsonrpc: "2.0",
|
|
14172
|
+
id: request_id,
|
|
14173
|
+
method,
|
|
14174
|
+
...params ? { params } : {}
|
|
14175
|
+
};
|
|
14176
|
+
let connected = false;
|
|
14177
|
+
const timer = !resolved ? setTimeout(() => {
|
|
14178
|
+
if (!connected && !resolved) {
|
|
14179
|
+
reject(new Error(`Timeout connecting to ${url}`));
|
|
13052
14180
|
}
|
|
13053
|
-
}
|
|
13054
|
-
|
|
13055
|
-
|
|
13056
|
-
|
|
13057
|
-
|
|
13058
|
-
|
|
13059
|
-
|
|
13060
|
-
|
|
14181
|
+
}, timeout) : null;
|
|
14182
|
+
ws.onopen = () => {
|
|
14183
|
+
connected = true;
|
|
14184
|
+
if (timer)
|
|
14185
|
+
clearTimeout(timer);
|
|
14186
|
+
reconnect_count = 0;
|
|
14187
|
+
ws.send(JSON.stringify(request));
|
|
14188
|
+
if (!resolved) {
|
|
14189
|
+
resolved = true;
|
|
14190
|
+
resolve7({ close: () => {
|
|
14191
|
+
stopped = true;
|
|
14192
|
+
ws.close();
|
|
14193
|
+
} });
|
|
14194
|
+
}
|
|
14195
|
+
};
|
|
14196
|
+
ws.onmessage = (event) => {
|
|
14197
|
+
try {
|
|
14198
|
+
const data = JSON.parse(String(event.data));
|
|
14199
|
+
if ("method" in data && !("id" in data)) {
|
|
14200
|
+
on_event(data);
|
|
14201
|
+
}
|
|
14202
|
+
} catch {}
|
|
14203
|
+
};
|
|
14204
|
+
ws.onerror = () => {
|
|
14205
|
+
if (!connected && !resolved) {
|
|
14206
|
+
if (timer)
|
|
14207
|
+
clearTimeout(timer);
|
|
14208
|
+
reject(new Error(`WebSocket connection failed to ${url}`));
|
|
14209
|
+
}
|
|
14210
|
+
};
|
|
14211
|
+
ws.onclose = () => {
|
|
14212
|
+
if (stopped)
|
|
14213
|
+
return;
|
|
14214
|
+
if (!connected && !resolved)
|
|
14215
|
+
return;
|
|
14216
|
+
if (reconnect_count >= MAX_RECONNECTS)
|
|
14217
|
+
return;
|
|
14218
|
+
reconnect_count++;
|
|
14219
|
+
const delay = Math.min(500 * reconnect_count, 3000);
|
|
14220
|
+
setTimeout(() => {
|
|
14221
|
+
if (stopped)
|
|
14222
|
+
return;
|
|
14223
|
+
const fresh_config = resolve_config(options);
|
|
14224
|
+
if ("error" in fresh_config)
|
|
14225
|
+
return;
|
|
14226
|
+
connect(`ws://127.0.0.1:${fresh_config.port}/unity-agentic`);
|
|
14227
|
+
}, delay);
|
|
14228
|
+
};
|
|
14229
|
+
}
|
|
14230
|
+
connect(`ws://127.0.0.1:${config.port}/unity-agentic`);
|
|
13061
14231
|
});
|
|
13062
14232
|
}
|
|
13063
14233
|
function resolve_config(options) {
|
|
@@ -13101,12 +14271,12 @@ function get_common_options(cmd) {
|
|
|
13101
14271
|
const port = port_str ? parseInt(port_str, 10) : undefined;
|
|
13102
14272
|
return { project_path, timeout, port };
|
|
13103
14273
|
}
|
|
13104
|
-
function build_call_options(cmd, method, params) {
|
|
14274
|
+
function build_call_options(cmd, method, params, extra) {
|
|
13105
14275
|
const { project_path, timeout, port } = get_common_options(cmd);
|
|
13106
|
-
return { project_path, method, params, timeout, port };
|
|
14276
|
+
return { project_path, method, params, timeout, port, ...extra?.no_wait ? { no_wait: true } : {} };
|
|
13107
14277
|
}
|
|
13108
|
-
async function handle_rpc(cmd, method, params) {
|
|
13109
|
-
const options = build_call_options(cmd, method, params);
|
|
14278
|
+
async function handle_rpc(cmd, method, params, extra) {
|
|
14279
|
+
const options = build_call_options(cmd, method, params, extra);
|
|
13110
14280
|
const response = await call_editor(options);
|
|
13111
14281
|
output_response(response);
|
|
13112
14282
|
}
|
|
@@ -13183,24 +14353,27 @@ function build_editor_command() {
|
|
|
13183
14353
|
console.log(JSON.stringify(response.result, null, 2));
|
|
13184
14354
|
}
|
|
13185
14355
|
});
|
|
13186
|
-
cmd.command("invoke <type> <member> [args...]").description("Call a static Unity Editor API method or read/set a static property").option("--set <value>", "Set a static property value").option("--args <json>", "JSON array of method arguments (overrides positional args)").action(async function(type, member, args, options) {
|
|
14356
|
+
cmd.command("invoke <type> <member> [args...]").description("Call a static Unity Editor API method or read/set a static property").option("--set <value>", "Set a static property value").option("--args <json>", "JSON array of method arguments (overrides positional args)").option("--no-wait", "Fire and forget -- return immediately without waiting for result").action(async function(type, member, args, options) {
|
|
13187
14357
|
const params = { type, member };
|
|
13188
14358
|
if (options.set !== undefined) {
|
|
13189
14359
|
params.set = options.set;
|
|
13190
14360
|
} else if (options.args) {
|
|
13191
14361
|
params.args = options.args;
|
|
14362
|
+
} else if (args.length === 1 && args[0].startsWith("[")) {
|
|
14363
|
+
params.args = args[0];
|
|
13192
14364
|
} else if (args.length > 0) {
|
|
13193
14365
|
params.args = JSON.stringify(args);
|
|
13194
14366
|
}
|
|
13195
|
-
await handle_rpc(this, "editor.invoke", params);
|
|
14367
|
+
await handle_rpc(this, "editor.invoke", params, { no_wait: options.noWait });
|
|
13196
14368
|
});
|
|
13197
|
-
cmd.command("console-logs").description("Get recent console log entries").option("-c, --count <n>", "Number of log entries to retrieve", "50").option("--limit <n>", "Alias for --count").option("-t, --type <type>", "Filter by log type (Log, Warning, Error, Assert, Exception)").action(async function(options) {
|
|
14369
|
+
cmd.command("console-logs").description("Get recent console log entries").option("-c, --count <n>", "Number of log entries to retrieve", "50").option("--limit <n>", "Alias for --count").option("-t, --type <type>", "Filter by log type (Log, Warning, Error, Assert, Exception)").option("-s, --severity <type>", "Alias for --type").action(async function(options) {
|
|
13198
14370
|
const params = {};
|
|
13199
14371
|
const count = options.limit || options.count;
|
|
13200
14372
|
if (count)
|
|
13201
14373
|
params.count = parseInt(count, 10);
|
|
13202
|
-
|
|
13203
|
-
|
|
14374
|
+
const typeFilter = options.severity || options.type;
|
|
14375
|
+
if (typeFilter)
|
|
14376
|
+
params.type = typeFilter;
|
|
13204
14377
|
await handle_rpc(this, "editor.console.getLogs", params);
|
|
13205
14378
|
});
|
|
13206
14379
|
cmd.command("console-clear").description("Clear the console log buffer").action(async function() {
|
|
@@ -13217,7 +14390,7 @@ function build_editor_command() {
|
|
|
13217
14390
|
port,
|
|
13218
14391
|
method: "editor.console.subscribe",
|
|
13219
14392
|
on_event: (event) => {
|
|
13220
|
-
if (event.method === "editor.console.logReceived"
|
|
14393
|
+
if (event.method === "editor.console.logReceived") {
|
|
13221
14394
|
const params = event.params ?? {};
|
|
13222
14395
|
if (type_filter && typeof params.type === "string" && params.type.toLowerCase() !== type_filter) {
|
|
13223
14396
|
return;
|
|
@@ -13475,23 +14648,12 @@ function build_editor_command() {
|
|
|
13475
14648
|
process.exitCode = 1;
|
|
13476
14649
|
}
|
|
13477
14650
|
});
|
|
13478
|
-
cmd.command("log").allowUnknownOption().argument("[args...]").action(() => {
|
|
13479
|
-
console.log(JSON.stringify({
|
|
13480
|
-
success: false,
|
|
13481
|
-
error: '"editor log" does not exist. Use one of:',
|
|
13482
|
-
alternatives: [
|
|
13483
|
-
{ command: "editor console-logs", description: "Get recent console entries from the running Editor (live bridge)" },
|
|
13484
|
-
{ command: "read log", description: "Read and filter the Unity Editor.log file on disk (no bridge needed)" }
|
|
13485
|
-
]
|
|
13486
|
-
}, null, 2));
|
|
13487
|
-
process.exitCode = 1;
|
|
13488
|
-
});
|
|
13489
14651
|
return cmd;
|
|
13490
14652
|
}
|
|
13491
14653
|
|
|
13492
14654
|
// src/project-search.ts
|
|
13493
14655
|
init_scanner();
|
|
13494
|
-
var
|
|
14656
|
+
var import_fs20 = require("fs");
|
|
13495
14657
|
var path8 = __toESM(require("path"));
|
|
13496
14658
|
var BINARY_EXTENSIONS = new Set([
|
|
13497
14659
|
".png",
|
|
@@ -13554,7 +14716,7 @@ function walk_project_files_js(project_path, extensions, exclude_dirs) {
|
|
|
13554
14716
|
function walk(dir) {
|
|
13555
14717
|
let entries;
|
|
13556
14718
|
try {
|
|
13557
|
-
entries =
|
|
14719
|
+
entries = import_fs20.readdirSync(dir);
|
|
13558
14720
|
} catch {
|
|
13559
14721
|
return;
|
|
13560
14722
|
}
|
|
@@ -13562,7 +14724,7 @@ function walk_project_files_js(project_path, extensions, exclude_dirs) {
|
|
|
13562
14724
|
const full = path8.join(dir, entry);
|
|
13563
14725
|
let stat;
|
|
13564
14726
|
try {
|
|
13565
|
-
stat =
|
|
14727
|
+
stat = import_fs20.statSync(full);
|
|
13566
14728
|
} catch {
|
|
13567
14729
|
continue;
|
|
13568
14730
|
}
|
|
@@ -13579,14 +14741,14 @@ function walk_project_files_js(project_path, extensions, exclude_dirs) {
|
|
|
13579
14741
|
}
|
|
13580
14742
|
}
|
|
13581
14743
|
const assetsDir = path8.join(project_path, "Assets");
|
|
13582
|
-
if (
|
|
14744
|
+
if (import_fs20.existsSync(assetsDir)) {
|
|
13583
14745
|
walk(assetsDir);
|
|
13584
14746
|
} else {
|
|
13585
14747
|
walk(project_path);
|
|
13586
14748
|
}
|
|
13587
14749
|
if (extSet.has(".asset")) {
|
|
13588
14750
|
const settingsDir = path8.join(project_path, "ProjectSettings");
|
|
13589
|
-
if (
|
|
14751
|
+
if (import_fs20.existsSync(settingsDir)) {
|
|
13590
14752
|
walk(settingsDir);
|
|
13591
14753
|
}
|
|
13592
14754
|
}
|
|
@@ -13627,7 +14789,7 @@ function search_project(options) {
|
|
|
13627
14789
|
error: "Name pattern must not be empty"
|
|
13628
14790
|
};
|
|
13629
14791
|
}
|
|
13630
|
-
if (!
|
|
14792
|
+
if (!import_fs20.existsSync(project_path)) {
|
|
13631
14793
|
return {
|
|
13632
14794
|
success: false,
|
|
13633
14795
|
project_path,
|
|
@@ -13669,7 +14831,7 @@ function search_project(options) {
|
|
|
13669
14831
|
}
|
|
13670
14832
|
let display_name = fileName;
|
|
13671
14833
|
try {
|
|
13672
|
-
const content =
|
|
14834
|
+
const content = import_fs20.readFileSync(file, "utf-8");
|
|
13673
14835
|
const nameMatch = /^\s*m_Name:\s*(.+)$/m.exec(content.slice(0, 2000));
|
|
13674
14836
|
if (nameMatch)
|
|
13675
14837
|
display_name = nameMatch[1].trim();
|
|
@@ -13850,7 +15012,7 @@ function grep_project_js(options) {
|
|
|
13850
15012
|
max_results = 100,
|
|
13851
15013
|
context_lines = 0
|
|
13852
15014
|
} = options;
|
|
13853
|
-
if (!
|
|
15015
|
+
if (!import_fs20.existsSync(project_path)) {
|
|
13854
15016
|
return {
|
|
13855
15017
|
success: false,
|
|
13856
15018
|
project_path,
|
|
@@ -13940,7 +15102,7 @@ function grep_project_js(options) {
|
|
|
13940
15102
|
totalFilesScanned++;
|
|
13941
15103
|
let content;
|
|
13942
15104
|
try {
|
|
13943
|
-
content =
|
|
15105
|
+
content = import_fs20.readFileSync(file, "utf-8");
|
|
13944
15106
|
} catch {
|
|
13945
15107
|
continue;
|
|
13946
15108
|
}
|
|
@@ -14219,9 +15381,9 @@ program.command("status").description("Show current configuration and status").o
|
|
|
14219
15381
|
let config = null;
|
|
14220
15382
|
let guidCacheCount = 0;
|
|
14221
15383
|
try {
|
|
14222
|
-
const { existsSync: existsSync22, readFileSync:
|
|
15384
|
+
const { existsSync: existsSync22, readFileSync: readFileSync17 } = require("fs");
|
|
14223
15385
|
if (existsSync22(configFile)) {
|
|
14224
|
-
config = JSON.parse(
|
|
15386
|
+
config = JSON.parse(readFileSync17(configFile, "utf-8"));
|
|
14225
15387
|
}
|
|
14226
15388
|
const guidCacheObj = load_guid_cache(projectPath);
|
|
14227
15389
|
guidCacheCount = guidCacheObj?.count ?? 0;
|