unity-agentic-tools 0.4.1 → 0.4.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/dist/cli.js +945 -170
- package/dist/index.js +740 -117
- 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
|
@@ -2299,7 +2299,7 @@ var require_package = __commonJS((exports2, module2) => {
|
|
|
2299
2299
|
module2.exports = {
|
|
2300
2300
|
name: "unity-agentic-tools",
|
|
2301
2301
|
packageManager: "bun@latest",
|
|
2302
|
-
version: "0.4.
|
|
2302
|
+
version: "0.4.2",
|
|
2303
2303
|
description: "Fast, token-efficient Unity YAML parser for AI agents",
|
|
2304
2304
|
exports: {
|
|
2305
2305
|
".": {
|
|
@@ -2619,6 +2619,9 @@ function find_unity_project_root(startDir) {
|
|
|
2619
2619
|
}
|
|
2620
2620
|
return null;
|
|
2621
2621
|
}
|
|
2622
|
+
function resolve_project_path(project_path) {
|
|
2623
|
+
return import_path4.resolve(project_path || process.cwd());
|
|
2624
|
+
}
|
|
2622
2625
|
function ensure_parent_dir(file_path) {
|
|
2623
2626
|
const dir = import_path4.dirname(file_path);
|
|
2624
2627
|
if (dir && dir !== "." && !import_fs4.existsSync(dir)) {
|
|
@@ -3286,6 +3289,24 @@ function resolveScriptGuid(script, projectPath) {
|
|
|
3286
3289
|
}
|
|
3287
3290
|
} catch {}
|
|
3288
3291
|
}
|
|
3292
|
+
try {
|
|
3293
|
+
const assetsDir = path.join(projectPath, "Assets");
|
|
3294
|
+
if (import_fs6.existsSync(assetsDir)) {
|
|
3295
|
+
const entries = import_fs6.readdirSync(assetsDir, { recursive: true, withFileTypes: false });
|
|
3296
|
+
for (const entry of entries) {
|
|
3297
|
+
if (!entry.endsWith(".cs"))
|
|
3298
|
+
continue;
|
|
3299
|
+
const fileName = path.basename(entry, ".cs").toLowerCase();
|
|
3300
|
+
if (fileName === scriptNameLower || classNameOnly && fileName === classNameOnly) {
|
|
3301
|
+
const fullPath = path.join(assetsDir, entry);
|
|
3302
|
+
const guid = extractGuidFromMeta(fullPath + ".meta");
|
|
3303
|
+
if (guid) {
|
|
3304
|
+
return { guid, path: path.join("Assets", entry) };
|
|
3305
|
+
}
|
|
3306
|
+
}
|
|
3307
|
+
}
|
|
3308
|
+
}
|
|
3309
|
+
} catch {}
|
|
3289
3310
|
}
|
|
3290
3311
|
return null;
|
|
3291
3312
|
}
|
|
@@ -3440,8 +3461,8 @@ function build_type_lookup(project_path) {
|
|
|
3440
3461
|
const assetsDir = path.join(project_path, "Assets");
|
|
3441
3462
|
const csIndex = new Map;
|
|
3442
3463
|
try {
|
|
3443
|
-
const { readdirSync:
|
|
3444
|
-
const entries =
|
|
3464
|
+
const { readdirSync: readdirSync4 } = require("fs");
|
|
3465
|
+
const entries = readdirSync4(assetsDir, { recursive: true, withFileTypes: false });
|
|
3445
3466
|
for (const entry of entries) {
|
|
3446
3467
|
if (typeof entry === "string" && entry.endsWith(".cs")) {
|
|
3447
3468
|
const basename3 = entry.substring(entry.lastIndexOf("/") + 1).replace(/\.cs$/, "");
|
|
@@ -5223,48 +5244,320 @@ function find_game_object_in_variant(doc, name, file_path, project_path) {
|
|
|
5223
5244
|
}
|
|
5224
5245
|
return null;
|
|
5225
5246
|
}
|
|
5226
|
-
function
|
|
5227
|
-
const
|
|
5228
|
-
if (!
|
|
5229
|
-
return;
|
|
5230
|
-
const
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5247
|
+
function parsePrefabRef(refText) {
|
|
5248
|
+
const fileIdMatch = refText.match(/fileID:[ \t]*(-?\d+)/i);
|
|
5249
|
+
if (!fileIdMatch)
|
|
5250
|
+
return null;
|
|
5251
|
+
const guidMatch = refText.match(/guid:[ \t]*([a-f0-9]{32})/i);
|
|
5252
|
+
const typeMatch = refText.match(/type:[ \t]*(-?\d+)/i);
|
|
5253
|
+
return {
|
|
5254
|
+
file_id: fileIdMatch[1],
|
|
5255
|
+
guid: guidMatch ? guidMatch[1].toLowerCase() : undefined,
|
|
5256
|
+
type: typeMatch ? typeMatch[1] : undefined
|
|
5257
|
+
};
|
|
5258
|
+
}
|
|
5259
|
+
function extractPrefabSourceGuid(prefabInstanceRaw) {
|
|
5260
|
+
const sourceMatch = prefabInstanceRaw.match(/m_SourcePrefab:[ \t]*\{[^}]*guid:[ \t]*([a-f0-9]{32})/i);
|
|
5261
|
+
return sourceMatch ? sourceMatch[1].toLowerCase() : null;
|
|
5262
|
+
}
|
|
5263
|
+
function normalizePrefabRef(refText, sourceGuid) {
|
|
5264
|
+
const parsed = parsePrefabRef(refText);
|
|
5265
|
+
if (!parsed) {
|
|
5266
|
+
return { error: `Invalid reference "${refText}". Expected format: {fileID: N, guid: ..., type: T}` };
|
|
5267
|
+
}
|
|
5268
|
+
const guid = parsed.guid ?? sourceGuid;
|
|
5269
|
+
if (!guid) {
|
|
5270
|
+
return { error: `Reference "${refText}" is missing guid and source prefab guid could not be inferred.` };
|
|
5240
5271
|
}
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
raw = raw.replace(existingPattern, `$1${entry}`);
|
|
5244
|
-
piBlock.replace_raw(raw);
|
|
5272
|
+
if (!/^[a-f0-9]{32}$/i.test(guid)) {
|
|
5273
|
+
return { error: `Invalid guid in reference "${refText}". Expected 32-character hex GUID.` };
|
|
5245
5274
|
}
|
|
5275
|
+
const type = parsed.type ?? "3";
|
|
5276
|
+
if (!/^-?\d+$/.test(type)) {
|
|
5277
|
+
return { error: `Invalid type in reference "${refText}". Expected an integer type value.` };
|
|
5278
|
+
}
|
|
5279
|
+
return {
|
|
5280
|
+
ref: {
|
|
5281
|
+
file_id: parsed.file_id,
|
|
5282
|
+
guid,
|
|
5283
|
+
type
|
|
5284
|
+
}
|
|
5285
|
+
};
|
|
5246
5286
|
}
|
|
5247
|
-
function
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
const
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
const emptyPattern = /m_AddedComponents:[ \t]*\[\]/;
|
|
5257
|
-
if (emptyPattern.test(raw)) {
|
|
5258
|
-
raw = raw.replace(emptyPattern, `m_AddedComponents:${entry}`);
|
|
5259
|
-
piBlock.replace_raw(raw);
|
|
5260
|
-
return;
|
|
5287
|
+
function serializePrefabRef(ref) {
|
|
5288
|
+
return `{fileID: ${ref.file_id}, guid: ${ref.guid}, type: ${ref.type}}`;
|
|
5289
|
+
}
|
|
5290
|
+
function ensurePrefabModificationSerializedVersion(prefabInstanceBlock) {
|
|
5291
|
+
const raw = prefabInstanceBlock.raw;
|
|
5292
|
+
const updated = raw.replace(/(^([ \t]*)m_Modification:[ \t]*\n)(?!\2[ \t]+serializedVersion:[ \t]*\d+)/m, (_match, prefix, indent) => `${prefix}${indent} serializedVersion: 3
|
|
5293
|
+
`);
|
|
5294
|
+
if (updated === raw) {
|
|
5295
|
+
return false;
|
|
5261
5296
|
}
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5297
|
+
prefabInstanceBlock.replace_raw(updated);
|
|
5298
|
+
return true;
|
|
5299
|
+
}
|
|
5300
|
+
function addedOverrideEntryKey(entry) {
|
|
5301
|
+
return `${entry.target.file_id}|${entry.target.guid}|${entry.target.type}|${entry.insert_index}|${entry.added_object_file_id}`;
|
|
5302
|
+
}
|
|
5303
|
+
function splitPrefabArraySection(rawText, key) {
|
|
5304
|
+
const lines = rawText.split(`
|
|
5305
|
+
`);
|
|
5306
|
+
const keyPattern = new RegExp(`^([ ]*)${key}:[ ]*(.*)$`);
|
|
5307
|
+
let keyIndex = -1;
|
|
5308
|
+
let indent = "";
|
|
5309
|
+
for (let i = 0;i < lines.length; i++) {
|
|
5310
|
+
const match = lines[i].match(keyPattern);
|
|
5311
|
+
if (match) {
|
|
5312
|
+
keyIndex = i;
|
|
5313
|
+
indent = match[1];
|
|
5314
|
+
break;
|
|
5315
|
+
}
|
|
5316
|
+
}
|
|
5317
|
+
if (keyIndex === -1) {
|
|
5318
|
+
return null;
|
|
5319
|
+
}
|
|
5320
|
+
const keyIndentLen = indent.length;
|
|
5321
|
+
let sectionEnd = keyIndex + 1;
|
|
5322
|
+
for (let i = keyIndex + 1;i < lines.length; i++) {
|
|
5323
|
+
const line = lines[i];
|
|
5324
|
+
const trimmed = line.trim();
|
|
5325
|
+
if (trimmed.length === 0) {
|
|
5326
|
+
sectionEnd = i + 1;
|
|
5327
|
+
continue;
|
|
5328
|
+
}
|
|
5329
|
+
const indentLen = (line.match(/^[ \t]*/) || [""])[0].length;
|
|
5330
|
+
if (indentLen < keyIndentLen) {
|
|
5331
|
+
break;
|
|
5332
|
+
}
|
|
5333
|
+
if (indentLen === keyIndentLen && !trimmed.startsWith("-") && /^[A-Za-z_][A-Za-z0-9_]*:/.test(trimmed)) {
|
|
5334
|
+
break;
|
|
5335
|
+
}
|
|
5336
|
+
sectionEnd = i + 1;
|
|
5337
|
+
}
|
|
5338
|
+
return {
|
|
5339
|
+
lines,
|
|
5340
|
+
key_index: keyIndex,
|
|
5341
|
+
section_end: sectionEnd,
|
|
5342
|
+
indent
|
|
5343
|
+
};
|
|
5344
|
+
}
|
|
5345
|
+
function collectAddedOverrideEntries(lines, key_index, section_end, sourceGuid) {
|
|
5346
|
+
const sectionLines = lines.slice(key_index + 1, section_end);
|
|
5347
|
+
const dedup = new Map;
|
|
5348
|
+
let i = 0;
|
|
5349
|
+
while (i < sectionLines.length) {
|
|
5350
|
+
const line = sectionLines[i];
|
|
5351
|
+
const trimmed = line.trimStart();
|
|
5352
|
+
if (!trimmed.startsWith("-")) {
|
|
5353
|
+
i++;
|
|
5354
|
+
continue;
|
|
5355
|
+
}
|
|
5356
|
+
const entryIndent = (line.match(/^[ \t]*/) || [""])[0].length;
|
|
5357
|
+
const entryLines = [line];
|
|
5358
|
+
i++;
|
|
5359
|
+
while (i < sectionLines.length) {
|
|
5360
|
+
const nextLine = sectionLines[i];
|
|
5361
|
+
const nextTrimmed = nextLine.trim();
|
|
5362
|
+
const nextIndent = (nextLine.match(/^[ \t]*/) || [""])[0].length;
|
|
5363
|
+
if (nextTrimmed.length > 0 && nextIndent === entryIndent && nextTrimmed.startsWith("-")) {
|
|
5364
|
+
break;
|
|
5365
|
+
}
|
|
5366
|
+
entryLines.push(nextLine);
|
|
5367
|
+
i++;
|
|
5368
|
+
}
|
|
5369
|
+
const entryText = entryLines.join(`
|
|
5370
|
+
`);
|
|
5371
|
+
const targetMatch = entryText.match(/targetCorrespondingSourceObject:[ \t]*(\{[^}]+\})/);
|
|
5372
|
+
const insertMatch = entryText.match(/insertIndex:[ \t]*(-?\d+)/);
|
|
5373
|
+
const addedObjectMatch = entryText.match(/addedObject:[ \t]*\{[^}]*fileID:[ \t]*(-?\d+)/);
|
|
5374
|
+
if (!targetMatch || !addedObjectMatch) {
|
|
5375
|
+
continue;
|
|
5376
|
+
}
|
|
5377
|
+
const normalizedTarget = normalizePrefabRef(targetMatch[1], sourceGuid).ref;
|
|
5378
|
+
if (!normalizedTarget) {
|
|
5379
|
+
continue;
|
|
5380
|
+
}
|
|
5381
|
+
const insertIndex = insertMatch ? Number.parseInt(insertMatch[1], 10) : -1;
|
|
5382
|
+
const entry = {
|
|
5383
|
+
target: normalizedTarget,
|
|
5384
|
+
insert_index: Number.isNaN(insertIndex) ? -1 : insertIndex,
|
|
5385
|
+
added_object_file_id: addedObjectMatch[1]
|
|
5386
|
+
};
|
|
5387
|
+
const dedupKey = addedOverrideEntryKey(entry);
|
|
5388
|
+
if (!dedup.has(dedupKey)) {
|
|
5389
|
+
dedup.set(dedupKey, entry);
|
|
5390
|
+
}
|
|
5391
|
+
}
|
|
5392
|
+
return [...dedup.values()];
|
|
5393
|
+
}
|
|
5394
|
+
function appendToAddedOverrideArray(doc, piId, key, targetSourceRef, newObjectId) {
|
|
5395
|
+
const piBlock = doc.find_by_file_id(piId);
|
|
5396
|
+
if (!piBlock) {
|
|
5397
|
+
return { success: false, error: `PrefabInstance with fileID ${piId} not found` };
|
|
5398
|
+
}
|
|
5399
|
+
ensurePrefabModificationSerializedVersion(piBlock);
|
|
5400
|
+
const split = splitPrefabArraySection(piBlock.raw, key);
|
|
5401
|
+
if (!split) {
|
|
5402
|
+
return { success: false, error: `${key} property not found in PrefabInstance ${piId}` };
|
|
5403
|
+
}
|
|
5404
|
+
const sourceGuid = extractPrefabSourceGuid(piBlock.raw);
|
|
5405
|
+
const normalizedTarget = normalizePrefabRef(targetSourceRef, sourceGuid);
|
|
5406
|
+
if (!normalizedTarget.ref) {
|
|
5407
|
+
return { success: false, error: normalizedTarget.error };
|
|
5408
|
+
}
|
|
5409
|
+
const candidate = {
|
|
5410
|
+
target: normalizedTarget.ref,
|
|
5411
|
+
insert_index: -1,
|
|
5412
|
+
added_object_file_id: newObjectId
|
|
5413
|
+
};
|
|
5414
|
+
const candidateKey = addedOverrideEntryKey(candidate);
|
|
5415
|
+
const existing = collectAddedOverrideEntries(split.lines, split.key_index, split.section_end, sourceGuid);
|
|
5416
|
+
if (existing.some((entry) => addedOverrideEntryKey(entry) === candidateKey)) {
|
|
5417
|
+
return { success: true, changed: false };
|
|
5418
|
+
}
|
|
5419
|
+
const entryLines = [
|
|
5420
|
+
`${split.indent}- targetCorrespondingSourceObject: ${serializePrefabRef(candidate.target)}`,
|
|
5421
|
+
`${split.indent} insertIndex: ${candidate.insert_index}`,
|
|
5422
|
+
`${split.indent} addedObject: {fileID: ${candidate.added_object_file_id}}`
|
|
5423
|
+
];
|
|
5424
|
+
const keyLine = split.lines[split.key_index].trim();
|
|
5425
|
+
let insertIndex = split.section_end;
|
|
5426
|
+
while (insertIndex > split.key_index + 1 && split.lines[insertIndex - 1].trim().length === 0) {
|
|
5427
|
+
insertIndex--;
|
|
5428
|
+
}
|
|
5429
|
+
let updatedLines;
|
|
5430
|
+
if (keyLine === `${key}: []`) {
|
|
5431
|
+
const replacement = [`${split.indent}${key}:`, ...entryLines];
|
|
5432
|
+
updatedLines = [
|
|
5433
|
+
...split.lines.slice(0, split.key_index),
|
|
5434
|
+
...replacement,
|
|
5435
|
+
...split.lines.slice(split.section_end)
|
|
5436
|
+
];
|
|
5437
|
+
} else {
|
|
5438
|
+
updatedLines = [
|
|
5439
|
+
...split.lines.slice(0, insertIndex),
|
|
5440
|
+
...entryLines,
|
|
5441
|
+
...split.lines.slice(insertIndex)
|
|
5442
|
+
];
|
|
5266
5443
|
}
|
|
5444
|
+
piBlock.replace_raw(updatedLines.join(`
|
|
5445
|
+
`));
|
|
5446
|
+
return { success: true, changed: true };
|
|
5447
|
+
}
|
|
5448
|
+
function appendToAddedGameObjects(doc, piId, targetSourceRef, newGoId) {
|
|
5449
|
+
return appendToAddedOverrideArray(doc, piId, "m_AddedGameObjects", targetSourceRef, newGoId);
|
|
5450
|
+
}
|
|
5451
|
+
function appendToAddedComponents(doc, piId, targetSourceRef, newComponentId) {
|
|
5452
|
+
return appendToAddedOverrideArray(doc, piId, "m_AddedComponents", targetSourceRef, newComponentId);
|
|
5267
5453
|
}
|
|
5454
|
+
var COMPONENT_FULL_TEMPLATES = {
|
|
5455
|
+
65: (gameObjectId) => ` m_GameObject: {fileID: ${gameObjectId}}
|
|
5456
|
+
m_Material: {fileID: 0}
|
|
5457
|
+
m_IncludeLayers:
|
|
5458
|
+
serializedVersion: 2
|
|
5459
|
+
m_Bits: 0
|
|
5460
|
+
m_ExcludeLayers:
|
|
5461
|
+
serializedVersion: 2
|
|
5462
|
+
m_Bits: 0
|
|
5463
|
+
m_LayerOverridePriority: 0
|
|
5464
|
+
m_IsTrigger: 0
|
|
5465
|
+
m_ProvidesContacts: 0
|
|
5466
|
+
m_Enabled: 1
|
|
5467
|
+
serializedVersion: 3
|
|
5468
|
+
m_Size: {x: 1, y: 1, z: 1}
|
|
5469
|
+
m_Center: {x: 0, y: 0, z: 0}`,
|
|
5470
|
+
82: (gameObjectId) => ` m_GameObject: {fileID: ${gameObjectId}}
|
|
5471
|
+
m_Enabled: 1
|
|
5472
|
+
serializedVersion: 4
|
|
5473
|
+
OutputAudioMixerGroup: {fileID: 0}
|
|
5474
|
+
m_audioClip: {fileID: 0}
|
|
5475
|
+
m_PlayOnAwake: 1
|
|
5476
|
+
m_Volume: 1
|
|
5477
|
+
m_Pitch: 1
|
|
5478
|
+
Loop: 0
|
|
5479
|
+
Mute: 0
|
|
5480
|
+
Spatialize: 0
|
|
5481
|
+
SpatializePostEffects: 0
|
|
5482
|
+
Priority: 128
|
|
5483
|
+
DopplerLevel: 1
|
|
5484
|
+
MinDistance: 1
|
|
5485
|
+
MaxDistance: 500
|
|
5486
|
+
Pan2D: 0
|
|
5487
|
+
rolloffMode: 0
|
|
5488
|
+
BypassEffects: 0
|
|
5489
|
+
BypassListenerEffects: 0
|
|
5490
|
+
BypassReverbZones: 0
|
|
5491
|
+
rolloffCustomCurve:
|
|
5492
|
+
serializedVersion: 2
|
|
5493
|
+
m_Curve:
|
|
5494
|
+
- serializedVersion: 3
|
|
5495
|
+
time: 0
|
|
5496
|
+
value: 1
|
|
5497
|
+
inSlope: 0
|
|
5498
|
+
outSlope: 0
|
|
5499
|
+
tangentMode: 0
|
|
5500
|
+
weightedMode: 0
|
|
5501
|
+
inWeight: 0.33333334
|
|
5502
|
+
outWeight: 0.33333334
|
|
5503
|
+
- serializedVersion: 3
|
|
5504
|
+
time: 1
|
|
5505
|
+
value: 0
|
|
5506
|
+
inSlope: 0
|
|
5507
|
+
outSlope: 0
|
|
5508
|
+
tangentMode: 0
|
|
5509
|
+
weightedMode: 0
|
|
5510
|
+
inWeight: 0.33333334
|
|
5511
|
+
outWeight: 0.33333334
|
|
5512
|
+
m_PreInfinity: 2
|
|
5513
|
+
m_PostInfinity: 2
|
|
5514
|
+
m_RotationOrder: 4
|
|
5515
|
+
panLevelCustomCurve:
|
|
5516
|
+
serializedVersion: 2
|
|
5517
|
+
m_Curve:
|
|
5518
|
+
- serializedVersion: 3
|
|
5519
|
+
time: 0
|
|
5520
|
+
value: 0
|
|
5521
|
+
inSlope: 0
|
|
5522
|
+
outSlope: 0
|
|
5523
|
+
tangentMode: 0
|
|
5524
|
+
weightedMode: 0
|
|
5525
|
+
inWeight: 0.33333334
|
|
5526
|
+
outWeight: 0.33333334
|
|
5527
|
+
m_PreInfinity: 2
|
|
5528
|
+
m_PostInfinity: 2
|
|
5529
|
+
m_RotationOrder: 4
|
|
5530
|
+
spreadCustomCurve:
|
|
5531
|
+
serializedVersion: 2
|
|
5532
|
+
m_Curve:
|
|
5533
|
+
- serializedVersion: 3
|
|
5534
|
+
time: 0
|
|
5535
|
+
value: 0
|
|
5536
|
+
inSlope: 0
|
|
5537
|
+
outSlope: 0
|
|
5538
|
+
tangentMode: 0
|
|
5539
|
+
weightedMode: 0
|
|
5540
|
+
inWeight: 0.33333334
|
|
5541
|
+
outWeight: 0.33333334
|
|
5542
|
+
m_PreInfinity: 2
|
|
5543
|
+
m_PostInfinity: 2
|
|
5544
|
+
m_RotationOrder: 4
|
|
5545
|
+
reverbZoneMixCustomCurve:
|
|
5546
|
+
serializedVersion: 2
|
|
5547
|
+
m_Curve:
|
|
5548
|
+
- serializedVersion: 3
|
|
5549
|
+
time: 0
|
|
5550
|
+
value: 1
|
|
5551
|
+
inSlope: 0
|
|
5552
|
+
outSlope: 0
|
|
5553
|
+
tangentMode: 0
|
|
5554
|
+
weightedMode: 0
|
|
5555
|
+
inWeight: 0.33333334
|
|
5556
|
+
outWeight: 0.33333334
|
|
5557
|
+
m_PreInfinity: 2
|
|
5558
|
+
m_PostInfinity: 2
|
|
5559
|
+
m_RotationOrder: 4`
|
|
5560
|
+
};
|
|
5268
5561
|
var COMPONENT_DEFAULTS = {
|
|
5269
5562
|
20: ` serializedVersion: 2
|
|
5270
5563
|
m_ClearFlags: 1
|
|
@@ -5391,6 +5684,17 @@ var COMPONENT_DEFAULTS = {
|
|
|
5391
5684
|
m_IgnoreParentGroups: 0`
|
|
5392
5685
|
};
|
|
5393
5686
|
function createGenericComponentYAML(componentName, classId, componentId, gameObjectId) {
|
|
5687
|
+
const fullTemplate = COMPONENT_FULL_TEMPLATES[classId];
|
|
5688
|
+
if (fullTemplate) {
|
|
5689
|
+
return `--- !u!${classId} &${componentId}
|
|
5690
|
+
${componentName}:
|
|
5691
|
+
m_ObjectHideFlags: 0
|
|
5692
|
+
m_CorrespondingSourceObject: {fileID: 0}
|
|
5693
|
+
m_PrefabInstance: {fileID: 0}
|
|
5694
|
+
m_PrefabAsset: {fileID: 0}
|
|
5695
|
+
${fullTemplate(gameObjectId)}
|
|
5696
|
+
`;
|
|
5697
|
+
}
|
|
5394
5698
|
const defaults = COMPONENT_DEFAULTS[classId] ? `
|
|
5395
5699
|
` + COMPONENT_DEFAULTS[classId] + `
|
|
5396
5700
|
` : "";
|
|
@@ -5543,7 +5847,14 @@ function createGameObject(options) {
|
|
|
5543
5847
|
doc.add_child_to_parent(parentTransformIdStr, transformIdStr);
|
|
5544
5848
|
}
|
|
5545
5849
|
if (variantPiId && strippedSourceRef) {
|
|
5546
|
-
appendToAddedGameObjects(doc, variantPiId, strippedSourceRef, gameObjectIdStr);
|
|
5850
|
+
const appendResult = appendToAddedGameObjects(doc, variantPiId, strippedSourceRef, gameObjectIdStr);
|
|
5851
|
+
if (!appendResult.success) {
|
|
5852
|
+
return {
|
|
5853
|
+
success: false,
|
|
5854
|
+
file_path,
|
|
5855
|
+
error: appendResult.error || `Failed to update m_AddedGameObjects for PrefabInstance ${variantPiId}`
|
|
5856
|
+
};
|
|
5857
|
+
}
|
|
5547
5858
|
}
|
|
5548
5859
|
const saveResult = doc.save();
|
|
5549
5860
|
if (!saveResult.success) {
|
|
@@ -6026,6 +6337,7 @@ PrefabInstance:
|
|
|
6026
6337
|
m_ObjectHideFlags: 0
|
|
6027
6338
|
serializedVersion: 2
|
|
6028
6339
|
m_Modification:
|
|
6340
|
+
serializedVersion: 3
|
|
6029
6341
|
m_TransformParent: {fileID: 0}
|
|
6030
6342
|
m_Modifications:
|
|
6031
6343
|
- target: {fileID: ${rootInfo.game_object.file_id}, guid: ${sourceGuid}, type: 3}
|
|
@@ -6172,6 +6484,7 @@ PrefabInstance:
|
|
|
6172
6484
|
m_ObjectHideFlags: 0
|
|
6173
6485
|
serializedVersion: 2
|
|
6174
6486
|
m_Modification:
|
|
6487
|
+
serializedVersion: 3
|
|
6175
6488
|
m_TransformParent: {fileID: ${parentTransformIdStr}}
|
|
6176
6489
|
m_Modifications:
|
|
6177
6490
|
- target: {fileID: ${rootGoFileId}, guid: ${sourceGuid}, type: 3}
|
|
@@ -6476,6 +6789,8 @@ function is_valid_component_base(base_class, project_path, depth = 0) {
|
|
|
6476
6789
|
}
|
|
6477
6790
|
if (!fullPath.endsWith(".cs") || !import_fs8.existsSync(fullPath)) {
|
|
6478
6791
|
if (match.kind === "class") {
|
|
6792
|
+
if (fullPath.includes("Assembly-CSharp.dll"))
|
|
6793
|
+
return true;
|
|
6479
6794
|
return is_likely_component_base_name(base_class);
|
|
6480
6795
|
}
|
|
6481
6796
|
}
|
|
@@ -6620,11 +6935,11 @@ function addComponent(options) {
|
|
|
6620
6935
|
};
|
|
6621
6936
|
}
|
|
6622
6937
|
if (resolved.base_class && !COMPONENT_BASE_CLASSES.has(resolved.base_class) && !is_valid_component_base(resolved.base_class, project_path)) {
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
|
|
6938
|
+
const warn = `"${component_type}" extends ${resolved.base_class}, which does not inherit from MonoBehaviour. Adding anyway, but ensure the script is a valid component. (Re-run "setup" if the inheritance graph is stale).`;
|
|
6939
|
+
if (!extractionError)
|
|
6940
|
+
extractionError = warn;
|
|
6941
|
+
else
|
|
6942
|
+
extractionError += " " + warn;
|
|
6628
6943
|
}
|
|
6629
6944
|
let version;
|
|
6630
6945
|
if (project_path) {
|
|
@@ -6640,10 +6955,22 @@ function addComponent(options) {
|
|
|
6640
6955
|
componentYAML = createMonoBehaviourYAML(componentId, gameObjectId, resolved.guid, resolved.fields, version, scriptFileId, type_lookup_comp);
|
|
6641
6956
|
scriptGuid = resolved.guid;
|
|
6642
6957
|
scriptPath = resolved.path || undefined;
|
|
6643
|
-
|
|
6958
|
+
if (resolved.extraction_error) {
|
|
6959
|
+
if (!extractionError)
|
|
6960
|
+
extractionError = resolved.extraction_error;
|
|
6961
|
+
else
|
|
6962
|
+
extractionError += " " + resolved.extraction_error;
|
|
6963
|
+
}
|
|
6644
6964
|
}
|
|
6645
6965
|
if (variantInfo) {
|
|
6646
|
-
appendToAddedComponents(doc, variantInfo.prefab_instance_id, variantInfo.source_ref, componentIdStr);
|
|
6966
|
+
const appendResult = appendToAddedComponents(doc, variantInfo.prefab_instance_id, variantInfo.source_ref, componentIdStr);
|
|
6967
|
+
if (!appendResult.success) {
|
|
6968
|
+
return {
|
|
6969
|
+
success: false,
|
|
6970
|
+
file_path,
|
|
6971
|
+
error: appendResult.error || `Failed to update m_AddedComponents for PrefabInstance ${variantInfo.prefab_instance_id}`
|
|
6972
|
+
};
|
|
6973
|
+
}
|
|
6647
6974
|
} else {
|
|
6648
6975
|
const added = addComponentToGameObject(doc, gameObjectIdStr, componentIdStr);
|
|
6649
6976
|
if (!added) {
|
|
@@ -7615,7 +7942,7 @@ function editComponentByFileId(options) {
|
|
|
7615
7942
|
return {
|
|
7616
7943
|
success: false,
|
|
7617
7944
|
file_path,
|
|
7618
|
-
error: `Could not resolve "${new_value}" to asset reference. Ensure GUID cache exists (run "setup <
|
|
7945
|
+
error: `Could not resolve "${new_value}" to asset reference. Ensure GUID cache exists (run "setup" first, or "setup -p <path>").`
|
|
7619
7946
|
};
|
|
7620
7947
|
}
|
|
7621
7948
|
if (resolved !== undefined) {
|
|
@@ -8192,6 +8519,193 @@ function findPrefabInstanceBlock(doc, identifier) {
|
|
|
8192
8519
|
}
|
|
8193
8520
|
return null;
|
|
8194
8521
|
}
|
|
8522
|
+
function parsePrefabRef2(refText) {
|
|
8523
|
+
const fileIdMatch = refText.match(/fileID:[ \t]*(-?\d+)/i);
|
|
8524
|
+
if (!fileIdMatch)
|
|
8525
|
+
return null;
|
|
8526
|
+
const guidMatch = refText.match(/guid:[ \t]*([a-f0-9]{32})/i);
|
|
8527
|
+
const typeMatch = refText.match(/type:[ \t]*(-?\d+)/i);
|
|
8528
|
+
return {
|
|
8529
|
+
file_id: fileIdMatch[1],
|
|
8530
|
+
guid: guidMatch ? guidMatch[1].toLowerCase() : undefined,
|
|
8531
|
+
type: typeMatch ? typeMatch[1] : undefined
|
|
8532
|
+
};
|
|
8533
|
+
}
|
|
8534
|
+
function extractPrefabSourceGuid2(prefabInstanceRaw) {
|
|
8535
|
+
const sourceMatch = prefabInstanceRaw.match(/m_SourcePrefab:[ \t]*\{[^}]*guid:[ \t]*([a-f0-9]{32})/i);
|
|
8536
|
+
return sourceMatch ? sourceMatch[1].toLowerCase() : null;
|
|
8537
|
+
}
|
|
8538
|
+
function normalizePrefabRef2(refText, sourceGuid) {
|
|
8539
|
+
const parsed = parsePrefabRef2(refText);
|
|
8540
|
+
if (!parsed) {
|
|
8541
|
+
return { error: `Invalid reference "${refText}". Expected format: {fileID: N, guid: ..., type: T}` };
|
|
8542
|
+
}
|
|
8543
|
+
const guid = parsed.guid ?? sourceGuid;
|
|
8544
|
+
if (!guid) {
|
|
8545
|
+
return { error: `Reference "${refText}" is missing guid and source prefab guid could not be inferred.` };
|
|
8546
|
+
}
|
|
8547
|
+
if (!/^[a-f0-9]{32}$/i.test(guid)) {
|
|
8548
|
+
return { error: `Invalid guid in reference "${refText}". Expected 32-character hex GUID.` };
|
|
8549
|
+
}
|
|
8550
|
+
const type = parsed.type ?? "3";
|
|
8551
|
+
if (!/^-?\d+$/.test(type)) {
|
|
8552
|
+
return { error: `Invalid type in reference "${refText}". Expected an integer type value.` };
|
|
8553
|
+
}
|
|
8554
|
+
return {
|
|
8555
|
+
ref: {
|
|
8556
|
+
file_id: parsed.file_id,
|
|
8557
|
+
guid,
|
|
8558
|
+
type
|
|
8559
|
+
}
|
|
8560
|
+
};
|
|
8561
|
+
}
|
|
8562
|
+
function parsePrefabRefMatcher(refText) {
|
|
8563
|
+
const parsed = parsePrefabRef2(refText);
|
|
8564
|
+
if (!parsed) {
|
|
8565
|
+
return { error: `Invalid reference "${refText}". Expected format: {fileID: N, guid: ..., type: T}` };
|
|
8566
|
+
}
|
|
8567
|
+
if (parsed.guid && !/^[a-f0-9]{32}$/i.test(parsed.guid)) {
|
|
8568
|
+
return { error: `Invalid guid in reference "${refText}". Expected 32-character hex GUID.` };
|
|
8569
|
+
}
|
|
8570
|
+
if (parsed.type && !/^-?\d+$/.test(parsed.type)) {
|
|
8571
|
+
return { error: `Invalid type in reference "${refText}". Expected an integer type value.` };
|
|
8572
|
+
}
|
|
8573
|
+
return { matcher: parsed };
|
|
8574
|
+
}
|
|
8575
|
+
function prefabRefKey(ref) {
|
|
8576
|
+
return `${ref.file_id}|${ref.guid}|${ref.type}`;
|
|
8577
|
+
}
|
|
8578
|
+
function serializePrefabRef2(ref) {
|
|
8579
|
+
return `{fileID: ${ref.file_id}, guid: ${ref.guid}, type: ${ref.type}}`;
|
|
8580
|
+
}
|
|
8581
|
+
function splitPrefabArraySection2(rawText, key) {
|
|
8582
|
+
const lines = rawText.split(`
|
|
8583
|
+
`);
|
|
8584
|
+
const keyPattern = new RegExp(`^([ ]*)${key}:[ ]*(.*)$`);
|
|
8585
|
+
let keyIndex = -1;
|
|
8586
|
+
let indent = "";
|
|
8587
|
+
for (let i = 0;i < lines.length; i++) {
|
|
8588
|
+
const match = lines[i].match(keyPattern);
|
|
8589
|
+
if (match) {
|
|
8590
|
+
keyIndex = i;
|
|
8591
|
+
indent = match[1];
|
|
8592
|
+
break;
|
|
8593
|
+
}
|
|
8594
|
+
}
|
|
8595
|
+
if (keyIndex === -1) {
|
|
8596
|
+
return null;
|
|
8597
|
+
}
|
|
8598
|
+
const keyIndentLen = indent.length;
|
|
8599
|
+
let sectionEnd = keyIndex + 1;
|
|
8600
|
+
for (let i = keyIndex + 1;i < lines.length; i++) {
|
|
8601
|
+
const line = lines[i];
|
|
8602
|
+
const trimmed = line.trim();
|
|
8603
|
+
if (trimmed.length === 0) {
|
|
8604
|
+
sectionEnd = i + 1;
|
|
8605
|
+
continue;
|
|
8606
|
+
}
|
|
8607
|
+
const indentLen = (line.match(/^[ \t]*/) || [""])[0].length;
|
|
8608
|
+
if (indentLen < keyIndentLen) {
|
|
8609
|
+
break;
|
|
8610
|
+
}
|
|
8611
|
+
if (indentLen === keyIndentLen && !trimmed.startsWith("-") && /^[A-Za-z_][A-Za-z0-9_]*:/.test(trimmed)) {
|
|
8612
|
+
break;
|
|
8613
|
+
}
|
|
8614
|
+
sectionEnd = i + 1;
|
|
8615
|
+
}
|
|
8616
|
+
return {
|
|
8617
|
+
lines,
|
|
8618
|
+
key_index: keyIndex,
|
|
8619
|
+
section_end: sectionEnd,
|
|
8620
|
+
indent
|
|
8621
|
+
};
|
|
8622
|
+
}
|
|
8623
|
+
function collectNormalizedRefsFromSection(lines, key_index, section_end, sourceGuid) {
|
|
8624
|
+
const sectionText = lines.slice(key_index, section_end).join(`
|
|
8625
|
+
`);
|
|
8626
|
+
const refMatches = sectionText.match(/\{[^}]*\}/g) || [];
|
|
8627
|
+
const dedup = new Map;
|
|
8628
|
+
for (const token of refMatches) {
|
|
8629
|
+
const parsed = parsePrefabRef2(token);
|
|
8630
|
+
if (!parsed)
|
|
8631
|
+
continue;
|
|
8632
|
+
const guid = parsed.guid ?? sourceGuid;
|
|
8633
|
+
if (!guid || !/^[a-f0-9]{32}$/i.test(guid))
|
|
8634
|
+
continue;
|
|
8635
|
+
const type = parsed.type ?? "3";
|
|
8636
|
+
if (!/^-?\d+$/.test(type))
|
|
8637
|
+
continue;
|
|
8638
|
+
const normalized = {
|
|
8639
|
+
file_id: parsed.file_id,
|
|
8640
|
+
guid: guid.toLowerCase(),
|
|
8641
|
+
type
|
|
8642
|
+
};
|
|
8643
|
+
const key = prefabRefKey(normalized);
|
|
8644
|
+
if (!dedup.has(key)) {
|
|
8645
|
+
dedup.set(key, normalized);
|
|
8646
|
+
}
|
|
8647
|
+
}
|
|
8648
|
+
return [...dedup.values()];
|
|
8649
|
+
}
|
|
8650
|
+
function mutatePrefabReferenceList(options) {
|
|
8651
|
+
const { target_block, key, ref_text, action, item_label } = options;
|
|
8652
|
+
const split = splitPrefabArraySection2(target_block.raw, key);
|
|
8653
|
+
if (!split) {
|
|
8654
|
+
return { success: false, error: `${key} property not found in PrefabInstance` };
|
|
8655
|
+
}
|
|
8656
|
+
const sourceGuid = extractPrefabSourceGuid2(target_block.raw);
|
|
8657
|
+
const existing = collectNormalizedRefsFromSection(split.lines, split.key_index, split.section_end, sourceGuid);
|
|
8658
|
+
let next = existing;
|
|
8659
|
+
if (action === "add") {
|
|
8660
|
+
const normalized = normalizePrefabRef2(ref_text, sourceGuid);
|
|
8661
|
+
if (!normalized.ref) {
|
|
8662
|
+
return { success: false, error: normalized.error };
|
|
8663
|
+
}
|
|
8664
|
+
const keyText = prefabRefKey(normalized.ref);
|
|
8665
|
+
if (existing.some((entry) => prefabRefKey(entry) === keyText)) {
|
|
8666
|
+
return { success: true, changed: false };
|
|
8667
|
+
}
|
|
8668
|
+
next = [...existing, normalized.ref];
|
|
8669
|
+
} else {
|
|
8670
|
+
const matcherResult = parsePrefabRefMatcher(ref_text);
|
|
8671
|
+
const matcher = matcherResult.matcher;
|
|
8672
|
+
if (!matcher) {
|
|
8673
|
+
return { success: false, error: matcherResult.error };
|
|
8674
|
+
}
|
|
8675
|
+
next = existing.filter((entry) => {
|
|
8676
|
+
if (entry.file_id !== matcher.file_id)
|
|
8677
|
+
return true;
|
|
8678
|
+
if (matcher.guid && entry.guid !== matcher.guid.toLowerCase())
|
|
8679
|
+
return true;
|
|
8680
|
+
if (matcher.type && entry.type !== matcher.type)
|
|
8681
|
+
return true;
|
|
8682
|
+
return false;
|
|
8683
|
+
});
|
|
8684
|
+
if (next.length === existing.length) {
|
|
8685
|
+
return {
|
|
8686
|
+
success: false,
|
|
8687
|
+
error: `${item_label} reference "${ref_text}" not found in ${key}`
|
|
8688
|
+
};
|
|
8689
|
+
}
|
|
8690
|
+
}
|
|
8691
|
+
const replacement = [];
|
|
8692
|
+
if (next.length === 0) {
|
|
8693
|
+
replacement.push(`${split.indent}${key}: []`);
|
|
8694
|
+
} else {
|
|
8695
|
+
replacement.push(`${split.indent}${key}:`);
|
|
8696
|
+
for (const entry of next) {
|
|
8697
|
+
replacement.push(`${split.indent}- ${serializePrefabRef2(entry)}`);
|
|
8698
|
+
}
|
|
8699
|
+
}
|
|
8700
|
+
const updatedLines = [
|
|
8701
|
+
...split.lines.slice(0, split.key_index),
|
|
8702
|
+
...replacement,
|
|
8703
|
+
...split.lines.slice(split.section_end)
|
|
8704
|
+
];
|
|
8705
|
+
target_block.replace_raw(updatedLines.join(`
|
|
8706
|
+
`));
|
|
8707
|
+
return { success: true, changed: true };
|
|
8708
|
+
}
|
|
8195
8709
|
function editArray(options) {
|
|
8196
8710
|
const { file_path, file_id, array_property, action, value, index } = options;
|
|
8197
8711
|
if (!import_fs10.existsSync(file_path)) {
|
|
@@ -8402,9 +8916,6 @@ function addRemovedComponent(options) {
|
|
|
8402
8916
|
if (!import_fs10.existsSync(file_path)) {
|
|
8403
8917
|
return { success: false, file_path, error: `File not found: ${file_path}` };
|
|
8404
8918
|
}
|
|
8405
|
-
if (!/^\{fileID:\s*-?\d+/.test(component_ref)) {
|
|
8406
|
-
return { success: false, file_path, error: `Invalid component reference "${component_ref}". Expected format: {fileID: N, guid: ..., type: T}` };
|
|
8407
|
-
}
|
|
8408
8919
|
let doc;
|
|
8409
8920
|
try {
|
|
8410
8921
|
doc = UnityDocument.from_file(file_path);
|
|
@@ -8415,19 +8926,16 @@ function addRemovedComponent(options) {
|
|
|
8415
8926
|
if (!targetBlock) {
|
|
8416
8927
|
return { success: false, file_path, error: `PrefabInstance "${prefab_instance}" not found` };
|
|
8417
8928
|
}
|
|
8418
|
-
|
|
8419
|
-
|
|
8420
|
-
|
|
8421
|
-
|
|
8422
|
-
|
|
8423
|
-
|
|
8424
|
-
|
|
8425
|
-
|
|
8426
|
-
|
|
8427
|
-
} else {
|
|
8428
|
-
return { success: false, file_path, error: "m_RemovedComponents property not found in PrefabInstance" };
|
|
8929
|
+
const mutation = mutatePrefabReferenceList({
|
|
8930
|
+
target_block: targetBlock,
|
|
8931
|
+
key: "m_RemovedComponents",
|
|
8932
|
+
ref_text: component_ref,
|
|
8933
|
+
action: "add",
|
|
8934
|
+
item_label: "Component"
|
|
8935
|
+
});
|
|
8936
|
+
if (!mutation.success) {
|
|
8937
|
+
return { success: false, file_path, error: mutation.error };
|
|
8429
8938
|
}
|
|
8430
|
-
targetBlock.replace_raw(rawText);
|
|
8431
8939
|
if (!doc.validate()) {
|
|
8432
8940
|
return { success: false, file_path, error: "Validation failed after adding removed component" };
|
|
8433
8941
|
}
|
|
@@ -8456,13 +8964,16 @@ function removeRemovedComponent(options) {
|
|
|
8456
8964
|
if (!targetBlock) {
|
|
8457
8965
|
return { success: false, file_path, error: `PrefabInstance "${prefab_instance}" not found` };
|
|
8458
8966
|
}
|
|
8459
|
-
const
|
|
8460
|
-
|
|
8461
|
-
|
|
8462
|
-
|
|
8967
|
+
const mutation = mutatePrefabReferenceList({
|
|
8968
|
+
target_block: targetBlock,
|
|
8969
|
+
key: "m_RemovedComponents",
|
|
8970
|
+
ref_text: component_ref,
|
|
8971
|
+
action: "remove",
|
|
8972
|
+
item_label: "Component"
|
|
8973
|
+
});
|
|
8974
|
+
if (!mutation.success) {
|
|
8975
|
+
return { success: false, file_path, error: mutation.error };
|
|
8463
8976
|
}
|
|
8464
|
-
const updatedRaw = targetBlock.raw.replace(refPattern, "");
|
|
8465
|
-
targetBlock.replace_raw(updatedRaw);
|
|
8466
8977
|
if (!doc.validate()) {
|
|
8467
8978
|
return { success: false, file_path, error: "Validation failed after removing component" };
|
|
8468
8979
|
}
|
|
@@ -8481,9 +8992,6 @@ function addRemovedGameObject(options) {
|
|
|
8481
8992
|
if (!import_fs10.existsSync(file_path)) {
|
|
8482
8993
|
return { success: false, file_path, error: `File not found: ${file_path}` };
|
|
8483
8994
|
}
|
|
8484
|
-
if (!/^\{fileID:\s*-?\d+/.test(component_ref)) {
|
|
8485
|
-
return { success: false, file_path, error: `Invalid GameObject reference "${component_ref}". Expected format: {fileID: N, guid: ..., type: T}` };
|
|
8486
|
-
}
|
|
8487
8995
|
let doc;
|
|
8488
8996
|
try {
|
|
8489
8997
|
doc = UnityDocument.from_file(file_path);
|
|
@@ -8494,19 +9002,16 @@ function addRemovedGameObject(options) {
|
|
|
8494
9002
|
if (!targetBlock) {
|
|
8495
9003
|
return { success: false, file_path, error: `PrefabInstance "${prefab_instance}" not found` };
|
|
8496
9004
|
}
|
|
8497
|
-
|
|
8498
|
-
|
|
8499
|
-
|
|
8500
|
-
|
|
8501
|
-
|
|
8502
|
-
|
|
8503
|
-
|
|
8504
|
-
|
|
8505
|
-
|
|
8506
|
-
} else {
|
|
8507
|
-
return { success: false, file_path, error: "m_RemovedGameObjects property not found in PrefabInstance" };
|
|
9005
|
+
const mutation = mutatePrefabReferenceList({
|
|
9006
|
+
target_block: targetBlock,
|
|
9007
|
+
key: "m_RemovedGameObjects",
|
|
9008
|
+
ref_text: component_ref,
|
|
9009
|
+
action: "add",
|
|
9010
|
+
item_label: "GameObject"
|
|
9011
|
+
});
|
|
9012
|
+
if (!mutation.success) {
|
|
9013
|
+
return { success: false, file_path, error: mutation.error };
|
|
8508
9014
|
}
|
|
8509
|
-
targetBlock.replace_raw(rawText);
|
|
8510
9015
|
if (!doc.validate()) {
|
|
8511
9016
|
return { success: false, file_path, error: "Validation failed after adding removed GameObject" };
|
|
8512
9017
|
}
|
|
@@ -8535,13 +9040,16 @@ function removeRemovedGameObject(options) {
|
|
|
8535
9040
|
if (!targetBlock) {
|
|
8536
9041
|
return { success: false, file_path, error: `PrefabInstance "${prefab_instance}" not found` };
|
|
8537
9042
|
}
|
|
8538
|
-
const
|
|
8539
|
-
|
|
8540
|
-
|
|
8541
|
-
|
|
9043
|
+
const mutation = mutatePrefabReferenceList({
|
|
9044
|
+
target_block: targetBlock,
|
|
9045
|
+
key: "m_RemovedGameObjects",
|
|
9046
|
+
ref_text: component_ref,
|
|
9047
|
+
action: "remove",
|
|
9048
|
+
item_label: "GameObject"
|
|
9049
|
+
});
|
|
9050
|
+
if (!mutation.success) {
|
|
9051
|
+
return { success: false, file_path, error: mutation.error };
|
|
8542
9052
|
}
|
|
8543
|
-
const updatedRaw = targetBlock.raw.replace(refPattern, "");
|
|
8544
|
-
targetBlock.replace_raw(updatedRaw);
|
|
8545
9053
|
if (!doc.validate()) {
|
|
8546
9054
|
return { success: false, file_path, error: "Validation failed after removing GameObject" };
|
|
8547
9055
|
}
|
|
@@ -9398,6 +9906,7 @@ function removeComponent(options) {
|
|
|
9398
9906
|
return { success: false, file_path, error: "Cannot remove a Transform with remove-component. Use delete to remove the entire GameObject." };
|
|
9399
9907
|
}
|
|
9400
9908
|
const resolved_file_id = found.file_id;
|
|
9909
|
+
let removed_added_component_overrides = 0;
|
|
9401
9910
|
const goMatch = found.raw.match(/m_GameObject:[ \t]*\{fileID:[ \t]*(-?\d+)\}/);
|
|
9402
9911
|
if (goMatch) {
|
|
9403
9912
|
const parentGoId = goMatch[1];
|
|
@@ -9408,6 +9917,19 @@ function removeComponent(options) {
|
|
|
9408
9917
|
const modifiedRaw = goBlock.raw.replace(compLinePattern, "");
|
|
9409
9918
|
if (modifiedRaw === goBlock.raw) {}
|
|
9410
9919
|
goBlock.replace_raw(modifiedRaw);
|
|
9920
|
+
if (goBlock.is_stripped) {
|
|
9921
|
+
const piMatch = goBlock.raw.match(/m_PrefabInstance:[ \t]*\{fileID:[ \t]*(-?\d+)\}/);
|
|
9922
|
+
if (piMatch) {
|
|
9923
|
+
const piBlock = doc.find_by_file_id(piMatch[1]);
|
|
9924
|
+
if (piBlock && piBlock.class_id === 1001) {
|
|
9925
|
+
const updated = removeAddedComponentOverrideEntries(piBlock.raw, resolved_file_id);
|
|
9926
|
+
if (updated.removed_count > 0) {
|
|
9927
|
+
piBlock.replace_raw(updated.updated_raw);
|
|
9928
|
+
removed_added_component_overrides += updated.removed_count;
|
|
9929
|
+
}
|
|
9930
|
+
}
|
|
9931
|
+
}
|
|
9932
|
+
}
|
|
9411
9933
|
}
|
|
9412
9934
|
}
|
|
9413
9935
|
const dangling = [];
|
|
@@ -9431,7 +9953,7 @@ function removeComponent(options) {
|
|
|
9431
9953
|
file_path,
|
|
9432
9954
|
removed_file_id: resolved_file_id,
|
|
9433
9955
|
removed_class_id: found.class_id,
|
|
9434
|
-
warning: dangling.length > 0 ? `Dangling references to deleted component found in blocks: ${dangling.join(", ")}` : undefined
|
|
9956
|
+
warning: dangling.length > 0 ? `Dangling references to deleted component found in blocks: ${dangling.join(", ")}${removed_added_component_overrides > 0 ? ` (removed ${removed_added_component_overrides} m_AddedComponents override entr${removed_added_component_overrides === 1 ? "y" : "ies"})` : ""}` : undefined
|
|
9435
9957
|
};
|
|
9436
9958
|
}
|
|
9437
9959
|
function removeComponentBatch(options) {
|
|
@@ -9549,6 +10071,124 @@ function findPrefabInstanceBlock2(doc, identifier) {
|
|
|
9549
10071
|
}
|
|
9550
10072
|
return null;
|
|
9551
10073
|
}
|
|
10074
|
+
function splitPrefabArraySection3(rawText, key) {
|
|
10075
|
+
const lines = rawText.split(`
|
|
10076
|
+
`);
|
|
10077
|
+
const keyPattern = new RegExp(`^[ ]*${key}:[ ]*(.*)$`);
|
|
10078
|
+
let keyIndex = -1;
|
|
10079
|
+
let keyIndentLen = 0;
|
|
10080
|
+
for (let i = 0;i < lines.length; i++) {
|
|
10081
|
+
const match = lines[i].match(keyPattern);
|
|
10082
|
+
if (match) {
|
|
10083
|
+
keyIndex = i;
|
|
10084
|
+
keyIndentLen = (lines[i].match(/^[ \t]*/) || [""])[0].length;
|
|
10085
|
+
break;
|
|
10086
|
+
}
|
|
10087
|
+
}
|
|
10088
|
+
if (keyIndex === -1) {
|
|
10089
|
+
return null;
|
|
10090
|
+
}
|
|
10091
|
+
let sectionEnd = keyIndex + 1;
|
|
10092
|
+
for (let i = keyIndex + 1;i < lines.length; i++) {
|
|
10093
|
+
const line = lines[i];
|
|
10094
|
+
const trimmed = line.trim();
|
|
10095
|
+
if (trimmed.length === 0) {
|
|
10096
|
+
sectionEnd = i + 1;
|
|
10097
|
+
continue;
|
|
10098
|
+
}
|
|
10099
|
+
const indentLen = (line.match(/^[ \t]*/) || [""])[0].length;
|
|
10100
|
+
if (indentLen < keyIndentLen) {
|
|
10101
|
+
break;
|
|
10102
|
+
}
|
|
10103
|
+
if (indentLen === keyIndentLen && !trimmed.startsWith("-") && /^[A-Za-z_][A-Za-z0-9_]*:/.test(trimmed)) {
|
|
10104
|
+
break;
|
|
10105
|
+
}
|
|
10106
|
+
sectionEnd = i + 1;
|
|
10107
|
+
}
|
|
10108
|
+
return {
|
|
10109
|
+
lines,
|
|
10110
|
+
key_index: keyIndex,
|
|
10111
|
+
section_end: sectionEnd
|
|
10112
|
+
};
|
|
10113
|
+
}
|
|
10114
|
+
function collectAddedObjectFileIdsFromArray(rawText, key) {
|
|
10115
|
+
const section = splitPrefabArraySection3(rawText, key);
|
|
10116
|
+
if (!section)
|
|
10117
|
+
return [];
|
|
10118
|
+
const keyLine = section.lines[section.key_index].trim();
|
|
10119
|
+
if (new RegExp(`^${key}:[ ]*[]$`).test(keyLine)) {
|
|
10120
|
+
return [];
|
|
10121
|
+
}
|
|
10122
|
+
const sectionText = section.lines.slice(section.key_index, section.section_end).join(`
|
|
10123
|
+
`);
|
|
10124
|
+
const fileIds = new Set;
|
|
10125
|
+
const addedObjectPattern = /addedObject:[ \t]*\{[^}]*fileID:[ \t]*(-?\d+)/g;
|
|
10126
|
+
let match;
|
|
10127
|
+
while ((match = addedObjectPattern.exec(sectionText)) !== null) {
|
|
10128
|
+
fileIds.add(match[1]);
|
|
10129
|
+
}
|
|
10130
|
+
if (fileIds.size === 0) {
|
|
10131
|
+
const inlineEntryPattern = /^[ \t]*-[ \t]*\{[^}]*fileID:[ \t]*(-?\d+)/gm;
|
|
10132
|
+
while ((match = inlineEntryPattern.exec(sectionText)) !== null) {
|
|
10133
|
+
fileIds.add(match[1]);
|
|
10134
|
+
}
|
|
10135
|
+
}
|
|
10136
|
+
return [...fileIds];
|
|
10137
|
+
}
|
|
10138
|
+
function removeAddedComponentOverrideEntries(rawText, componentId) {
|
|
10139
|
+
const section = splitPrefabArraySection3(rawText, "m_AddedComponents");
|
|
10140
|
+
if (!section)
|
|
10141
|
+
return { updated_raw: rawText, removed_count: 0 };
|
|
10142
|
+
const keyLine = section.lines[section.key_index].trim();
|
|
10143
|
+
if (/^m_AddedComponents:[ \t]*\[\]$/.test(keyLine)) {
|
|
10144
|
+
return { updated_raw: rawText, removed_count: 0 };
|
|
10145
|
+
}
|
|
10146
|
+
const bodyLines = section.lines.slice(section.key_index + 1, section.section_end);
|
|
10147
|
+
const keptEntries = [];
|
|
10148
|
+
let removed = 0;
|
|
10149
|
+
let i = 0;
|
|
10150
|
+
while (i < bodyLines.length) {
|
|
10151
|
+
const line = bodyLines[i];
|
|
10152
|
+
const trimmed = line.trimStart();
|
|
10153
|
+
if (!trimmed.startsWith("-")) {
|
|
10154
|
+
i++;
|
|
10155
|
+
continue;
|
|
10156
|
+
}
|
|
10157
|
+
const entryIndent = (line.match(/^[ \t]*/) || [""])[0].length;
|
|
10158
|
+
const entryLines = [line];
|
|
10159
|
+
i++;
|
|
10160
|
+
while (i < bodyLines.length) {
|
|
10161
|
+
const nextLine = bodyLines[i];
|
|
10162
|
+
const nextTrimmed = nextLine.trim();
|
|
10163
|
+
const nextIndent = (nextLine.match(/^[ \t]*/) || [""])[0].length;
|
|
10164
|
+
if (nextTrimmed.length > 0 && nextIndent === entryIndent && nextTrimmed.startsWith("-")) {
|
|
10165
|
+
break;
|
|
10166
|
+
}
|
|
10167
|
+
entryLines.push(nextLine);
|
|
10168
|
+
i++;
|
|
10169
|
+
}
|
|
10170
|
+
const entryText = entryLines.join(`
|
|
10171
|
+
`);
|
|
10172
|
+
const addedObjectMatch = entryText.match(/addedObject:[ \t]*\{[^}]*fileID:[ \t]*(-?\d+)/);
|
|
10173
|
+
if (addedObjectMatch && addedObjectMatch[1] === componentId) {
|
|
10174
|
+
removed++;
|
|
10175
|
+
continue;
|
|
10176
|
+
}
|
|
10177
|
+
keptEntries.push(entryLines);
|
|
10178
|
+
}
|
|
10179
|
+
if (removed === 0) {
|
|
10180
|
+
return { updated_raw: rawText, removed_count: 0 };
|
|
10181
|
+
}
|
|
10182
|
+
const keyIndent = (section.lines[section.key_index].match(/^[ \t]*/) || [""])[0];
|
|
10183
|
+
const replacement = keptEntries.length === 0 ? [`${keyIndent}m_AddedComponents: []`] : [`${keyIndent}m_AddedComponents:`, ...keptEntries.flat()];
|
|
10184
|
+
const updatedLines = [
|
|
10185
|
+
...section.lines.slice(0, section.key_index),
|
|
10186
|
+
...replacement,
|
|
10187
|
+
...section.lines.slice(section.section_end)
|
|
10188
|
+
];
|
|
10189
|
+
return { updated_raw: updatedLines.join(`
|
|
10190
|
+
`), removed_count: removed };
|
|
10191
|
+
}
|
|
9552
10192
|
function deletePrefabInstance(options) {
|
|
9553
10193
|
const { file_path, prefab_instance } = options;
|
|
9554
10194
|
const pathError = validate_file_path(file_path, "write");
|
|
@@ -9576,36 +10216,23 @@ function deletePrefabInstance(options) {
|
|
|
9576
10216
|
allToRemove.add(block.file_id);
|
|
9577
10217
|
}
|
|
9578
10218
|
}
|
|
9579
|
-
const
|
|
9580
|
-
|
|
9581
|
-
|
|
9582
|
-
|
|
9583
|
-
|
|
9584
|
-
|
|
9585
|
-
|
|
9586
|
-
|
|
9587
|
-
|
|
9588
|
-
|
|
9589
|
-
|
|
9590
|
-
if (compMatch) {
|
|
9591
|
-
const transformId = compMatch[1];
|
|
9592
|
-
allToRemove.add(transformId);
|
|
9593
|
-
const descendants = doc.collect_hierarchy(transformId);
|
|
9594
|
-
for (const id of descendants) {
|
|
9595
|
-
allToRemove.add(id);
|
|
9596
|
-
}
|
|
10219
|
+
for (const goId of collectAddedObjectFileIdsFromArray(piBlock.raw, "m_AddedGameObjects")) {
|
|
10220
|
+
allToRemove.add(goId);
|
|
10221
|
+
const goBlock = doc.find_by_file_id(goId);
|
|
10222
|
+
if (goBlock) {
|
|
10223
|
+
const compMatch = goBlock.raw.match(/component:[ \t]*\{fileID:[ \t]*(\d+)\}/);
|
|
10224
|
+
if (compMatch) {
|
|
10225
|
+
const transformId = compMatch[1];
|
|
10226
|
+
allToRemove.add(transformId);
|
|
10227
|
+
const descendants = doc.collect_hierarchy(transformId);
|
|
10228
|
+
for (const id of descendants) {
|
|
10229
|
+
allToRemove.add(id);
|
|
9597
10230
|
}
|
|
9598
10231
|
}
|
|
9599
10232
|
}
|
|
9600
10233
|
}
|
|
9601
|
-
const
|
|
9602
|
-
|
|
9603
|
-
if (addedCompMatch) {
|
|
9604
|
-
const addedCompSection = addedCompMatch[1];
|
|
9605
|
-
const compMatches = addedCompSection.matchAll(/fileID:[ \t]*(\d+)/g);
|
|
9606
|
-
for (const match of compMatches) {
|
|
9607
|
-
allToRemove.add(match[1]);
|
|
9608
|
-
}
|
|
10234
|
+
for (const componentId of collectAddedObjectFileIdsFromArray(piBlock.raw, "m_AddedComponents")) {
|
|
10235
|
+
allToRemove.add(componentId);
|
|
9609
10236
|
}
|
|
9610
10237
|
const parentMatch = piBlock.raw.match(/m_TransformParent:[ \t]*\{fileID:[ \t]*(\d+)\}/);
|
|
9611
10238
|
const parentTransformId = parentMatch ? parentMatch[1] : "0";
|
|
@@ -10615,10 +11242,11 @@ function build_create_command() {
|
|
|
10615
11242
|
if (!result.success)
|
|
10616
11243
|
process.exitCode = 1;
|
|
10617
11244
|
});
|
|
10618
|
-
cmd.command("build <
|
|
11245
|
+
cmd.command("build <scene_path>").description("Add a scene to build settings").option("-p, --project <path>", "Unity project path (defaults to cwd)").option("--index <n>", "Insert at position (0-based)").option("-j, --json", "Output as JSON").action((scene_path, options) => {
|
|
10619
11246
|
try {
|
|
11247
|
+
const resolvedProjectPath = resolve_project_path(options.project);
|
|
10620
11248
|
const position = options.index !== undefined ? parseInt(options.index, 10) : undefined;
|
|
10621
|
-
const result = add_scene(
|
|
11249
|
+
const result = add_scene(resolvedProjectPath, scene_path, { position });
|
|
10622
11250
|
console.log(JSON.stringify(result, null, 2));
|
|
10623
11251
|
if (!result.success)
|
|
10624
11252
|
process.exitCode = 1;
|
|
@@ -10726,9 +11354,10 @@ NativeFormatImporter:
|
|
|
10726
11354
|
shader_guid
|
|
10727
11355
|
}, null, 2));
|
|
10728
11356
|
});
|
|
10729
|
-
cmd.command("package <
|
|
11357
|
+
cmd.command("package <name> <version>").description("Add a package to Packages/manifest.json").option("-p, --project <path>", "Unity project path (defaults to cwd)").option("-j, --json", "Output as JSON").action((name, version, options) => {
|
|
10730
11358
|
try {
|
|
10731
|
-
const
|
|
11359
|
+
const resolvedProjectPath = resolve_project_path(options.project);
|
|
11360
|
+
const result = add_package(resolvedProjectPath, name, version);
|
|
10732
11361
|
if ("error" in result) {
|
|
10733
11362
|
console.log(JSON.stringify({ success: false, error: result.error }, null, 2));
|
|
10734
11363
|
process.exitCode = 1;
|
|
@@ -11032,6 +11661,116 @@ init_scanner();
|
|
|
11032
11661
|
var import_fs18 = require("fs");
|
|
11033
11662
|
var import_path8 = require("path");
|
|
11034
11663
|
var import_os = require("os");
|
|
11664
|
+
function parse_unity_ref(ref_text) {
|
|
11665
|
+
const file_id_match = ref_text.match(/fileID:[ \t]*(-?\d+)/i);
|
|
11666
|
+
if (!file_id_match)
|
|
11667
|
+
return null;
|
|
11668
|
+
const guid_match = ref_text.match(/guid:[ \t]*([a-f0-9]{32})/i);
|
|
11669
|
+
const type_match = ref_text.match(/type:[ \t]*(-?\d+)/i);
|
|
11670
|
+
const parsed = { file_id: file_id_match[1] };
|
|
11671
|
+
if (guid_match)
|
|
11672
|
+
parsed.guid = guid_match[1].toLowerCase();
|
|
11673
|
+
if (type_match)
|
|
11674
|
+
parsed.type = parseInt(type_match[1], 10);
|
|
11675
|
+
return parsed;
|
|
11676
|
+
}
|
|
11677
|
+
function extract_prefab_list_section(raw, key) {
|
|
11678
|
+
const lines = raw.split(`
|
|
11679
|
+
`);
|
|
11680
|
+
const key_pattern = new RegExp(`^(\\s*)${key}:[ \\t]*(.*)$`);
|
|
11681
|
+
let key_index = -1;
|
|
11682
|
+
let key_indent = 0;
|
|
11683
|
+
for (let i = 0;i < lines.length; i++) {
|
|
11684
|
+
const match = lines[i].match(key_pattern);
|
|
11685
|
+
if (match) {
|
|
11686
|
+
key_index = i;
|
|
11687
|
+
key_indent = match[1].length;
|
|
11688
|
+
break;
|
|
11689
|
+
}
|
|
11690
|
+
}
|
|
11691
|
+
if (key_index === -1)
|
|
11692
|
+
return null;
|
|
11693
|
+
const section_lines = [lines[key_index]];
|
|
11694
|
+
for (let i = key_index + 1;i < lines.length; i++) {
|
|
11695
|
+
const line = lines[i];
|
|
11696
|
+
const trimmed = line.trim();
|
|
11697
|
+
if (trimmed.length === 0) {
|
|
11698
|
+
section_lines.push(line);
|
|
11699
|
+
continue;
|
|
11700
|
+
}
|
|
11701
|
+
const indent = (line.match(/^\s*/) || [""])[0].length;
|
|
11702
|
+
if (indent < key_indent)
|
|
11703
|
+
break;
|
|
11704
|
+
if (indent === key_indent && !trimmed.startsWith("-") && /^[A-Za-z_][A-Za-z0-9_]*:/.test(trimmed)) {
|
|
11705
|
+
break;
|
|
11706
|
+
}
|
|
11707
|
+
section_lines.push(line);
|
|
11708
|
+
}
|
|
11709
|
+
return { key_indent, section_lines };
|
|
11710
|
+
}
|
|
11711
|
+
function parse_removed_list(raw, key) {
|
|
11712
|
+
const section = extract_prefab_list_section(raw, key);
|
|
11713
|
+
if (!section)
|
|
11714
|
+
return [];
|
|
11715
|
+
const key_line = section.section_lines[0].trim();
|
|
11716
|
+
if (key_line.endsWith("[]"))
|
|
11717
|
+
return [];
|
|
11718
|
+
const refs = section.section_lines.join(`
|
|
11719
|
+
`).match(/\{[^}]*fileID:[^}]*\}/g) || [];
|
|
11720
|
+
const dedup = new Map;
|
|
11721
|
+
for (const ref of refs) {
|
|
11722
|
+
const parsed = parse_unity_ref(ref);
|
|
11723
|
+
if (!parsed)
|
|
11724
|
+
continue;
|
|
11725
|
+
const key_text = `${parsed.file_id}|${parsed.guid ?? ""}|${parsed.type ?? ""}`;
|
|
11726
|
+
if (!dedup.has(key_text))
|
|
11727
|
+
dedup.set(key_text, parsed);
|
|
11728
|
+
}
|
|
11729
|
+
return [...dedup.values()];
|
|
11730
|
+
}
|
|
11731
|
+
function parse_added_list(raw, key) {
|
|
11732
|
+
const section = extract_prefab_list_section(raw, key);
|
|
11733
|
+
if (!section)
|
|
11734
|
+
return [];
|
|
11735
|
+
const key_line = section.section_lines[0].trim();
|
|
11736
|
+
if (key_line.endsWith("[]"))
|
|
11737
|
+
return [];
|
|
11738
|
+
const lines = section.section_lines.slice(1);
|
|
11739
|
+
const entries = [];
|
|
11740
|
+
let i = 0;
|
|
11741
|
+
while (i < lines.length) {
|
|
11742
|
+
const line = lines[i];
|
|
11743
|
+
const trimmed = line.trimStart();
|
|
11744
|
+
if (!trimmed.startsWith("-")) {
|
|
11745
|
+
i++;
|
|
11746
|
+
continue;
|
|
11747
|
+
}
|
|
11748
|
+
const entry_indent = (line.match(/^\s*/) || [""])[0].length;
|
|
11749
|
+
const entry_lines = [line];
|
|
11750
|
+
i++;
|
|
11751
|
+
while (i < lines.length) {
|
|
11752
|
+
const next = lines[i];
|
|
11753
|
+
const next_trimmed = next.trim();
|
|
11754
|
+
const next_indent = (next.match(/^\s*/) || [""])[0].length;
|
|
11755
|
+
if (next_trimmed.length > 0 && next_indent === entry_indent && next_trimmed.startsWith("-")) {
|
|
11756
|
+
break;
|
|
11757
|
+
}
|
|
11758
|
+
entry_lines.push(next);
|
|
11759
|
+
i++;
|
|
11760
|
+
}
|
|
11761
|
+
const entry_text = entry_lines.join(`
|
|
11762
|
+
`);
|
|
11763
|
+
const target_match = entry_text.match(/targetCorrespondingSourceObject:[ \t]*(\{[^}]+\})/);
|
|
11764
|
+
const insert_match = entry_text.match(/insertIndex:[ \t]*(-?\d+)/);
|
|
11765
|
+
const added_match = entry_text.match(/addedObject:[ \t]*(\{[^}]+\})/);
|
|
11766
|
+
entries.push({
|
|
11767
|
+
target_corresponding_source_object: target_match ? parse_unity_ref(target_match[1]) : null,
|
|
11768
|
+
insert_index: insert_match ? parseInt(insert_match[1], 10) : null,
|
|
11769
|
+
added_object: added_match ? parse_unity_ref(added_match[1]) : null
|
|
11770
|
+
});
|
|
11771
|
+
}
|
|
11772
|
+
return entries;
|
|
11773
|
+
}
|
|
11035
11774
|
function parse_material_yaml(content) {
|
|
11036
11775
|
const lines = content.replace(/\r/g, "").split(`
|
|
11037
11776
|
`);
|
|
@@ -11735,9 +12474,16 @@ function build_read_command(getScanner) {
|
|
|
11735
12474
|
}
|
|
11736
12475
|
if (result.total === 0 && !result.error) {
|
|
11737
12476
|
const prefabInstances = result.prefabInstances;
|
|
12477
|
+
let variantDetected = false;
|
|
12478
|
+
let variantResolvedFromSource = false;
|
|
11738
12479
|
if (prefabInstances && prefabInstances.length > 0) {
|
|
12480
|
+
variantDetected = true;
|
|
11739
12481
|
try {
|
|
11740
12482
|
const doc = UnityDocument.from_file(file);
|
|
12483
|
+
const strippedGoCount = doc.blocks.filter((b) => b.class_id === 1 && b.is_stripped).length;
|
|
12484
|
+
if (strippedGoCount > 0) {
|
|
12485
|
+
variantDetected = true;
|
|
12486
|
+
}
|
|
11741
12487
|
const projectPath = find_unity_project_root(import_path8.dirname(file));
|
|
11742
12488
|
const resolved = resolve_source_prefab(doc, file, projectPath ?? undefined);
|
|
11743
12489
|
if (resolved) {
|
|
@@ -11772,6 +12518,7 @@ function build_read_command(getScanner) {
|
|
|
11772
12518
|
resultRecord.resolvedFromSource = true;
|
|
11773
12519
|
resultRecord.sourcePrefab = resolved.source_path;
|
|
11774
12520
|
resultRecord.sourceGuid = resolved.source_guid;
|
|
12521
|
+
variantResolvedFromSource = true;
|
|
11775
12522
|
const variantNote = `PrefabVariant resolved from source prefab: ${resolved.source_path}`;
|
|
11776
12523
|
result.warning = result.warning ? `${result.warning}; ${variantNote}` : variantNote;
|
|
11777
12524
|
}
|
|
@@ -11782,8 +12529,13 @@ function build_read_command(getScanner) {
|
|
|
11782
12529
|
try {
|
|
11783
12530
|
const fileSize = import_fs18.statSync(file).size;
|
|
11784
12531
|
if (fileSize > 100) {
|
|
11785
|
-
|
|
11786
|
-
|
|
12532
|
+
if (variantDetected && !variantResolvedFromSource) {
|
|
12533
|
+
const variantWarning = "PrefabVariant detected but source prefab hierarchy could not be resolved (missing project context or GUID cache). Use --project or run setup to resolve source hierarchy.";
|
|
12534
|
+
result.warning = result.warning ? `${result.warning}; ${variantWarning}` : variantWarning;
|
|
12535
|
+
} else {
|
|
12536
|
+
const corruptWarning = "File has valid Unity YAML header but contains no parseable GameObjects -- file may be corrupt or malformed";
|
|
12537
|
+
result.warning = result.warning ? `${result.warning}; ${corruptWarning}` : corruptWarning;
|
|
12538
|
+
}
|
|
11787
12539
|
}
|
|
11788
12540
|
} catch {}
|
|
11789
12541
|
}
|
|
@@ -12056,38 +12808,41 @@ function build_read_command(getScanner) {
|
|
|
12056
12808
|
by_type: options.unresolved ? undefined : byType
|
|
12057
12809
|
};
|
|
12058
12810
|
if (!cache) {
|
|
12059
|
-
output._hint = "Run 'setup <
|
|
12811
|
+
output._hint = "Run 'setup' (or 'setup -p <path>') to resolve GUID paths";
|
|
12060
12812
|
}
|
|
12061
12813
|
console.log(JSON.stringify(output, null, 2));
|
|
12062
12814
|
});
|
|
12063
|
-
cmd.command("settings
|
|
12815
|
+
cmd.command("settings").description("Read Unity project settings (TagManager, DynamicsManager, QualitySettings, TimeManager, etc.)").option("-p, --project <path>", "Unity project path (defaults to cwd)").option("-s, --setting <name>", "Setting name or alias (tags, physics, quality, time)", "TagManager").option("-j, --json", "Output as JSON").action((options) => {
|
|
12816
|
+
const resolvedProjectPath = resolve_project_path(options.project);
|
|
12064
12817
|
const result = read_settings({
|
|
12065
|
-
project_path,
|
|
12818
|
+
project_path: resolvedProjectPath,
|
|
12066
12819
|
setting: options.setting
|
|
12067
12820
|
});
|
|
12068
12821
|
console.log(JSON.stringify(result, null, 2));
|
|
12069
12822
|
if (!result.success)
|
|
12070
12823
|
process.exit(1);
|
|
12071
12824
|
});
|
|
12072
|
-
cmd.command("build
|
|
12825
|
+
cmd.command("build").description("Read build settings (scene list, build profiles)").option("-p, --project <path>", "Unity project path (defaults to cwd)").option("-j, --json", "Output as JSON").action((options) => {
|
|
12826
|
+
const resolvedProjectPath = resolve_project_path(options.project);
|
|
12073
12827
|
try {
|
|
12074
|
-
const result = get_build_settings(
|
|
12828
|
+
const result = get_build_settings(resolvedProjectPath);
|
|
12075
12829
|
console.log(JSON.stringify(result, null, 2));
|
|
12076
12830
|
} catch (err) {
|
|
12077
12831
|
console.log(JSON.stringify({ success: false, error: err instanceof Error ? err.message : String(err) }, null, 2));
|
|
12078
12832
|
process.exitCode = 1;
|
|
12079
12833
|
}
|
|
12080
12834
|
});
|
|
12081
|
-
cmd.command("scenes
|
|
12835
|
+
cmd.command("scenes").description('Read build scenes (alias for "read build")').option("-p, --project <path>", "Unity project path (defaults to cwd)").option("-j, --json", "Output as JSON").action((options) => {
|
|
12836
|
+
const resolvedProjectPath = resolve_project_path(options.project);
|
|
12082
12837
|
try {
|
|
12083
|
-
const result = get_build_settings(
|
|
12838
|
+
const result = get_build_settings(resolvedProjectPath);
|
|
12084
12839
|
console.log(JSON.stringify(result, null, 2));
|
|
12085
12840
|
} catch (err) {
|
|
12086
12841
|
console.log(JSON.stringify({ success: false, error: err instanceof Error ? err.message : String(err) }, null, 2));
|
|
12087
12842
|
process.exitCode = 1;
|
|
12088
12843
|
}
|
|
12089
12844
|
});
|
|
12090
|
-
cmd.command("overrides <file> <prefab_instance>").description("Read PrefabInstance
|
|
12845
|
+
cmd.command("overrides <file> <prefab_instance>").description("Read PrefabInstance overrides (modifications + removed/added state)").option("--flat", "Output simplified list").option("-j, --json", "Output as JSON").action((file, prefab_instance, options) => {
|
|
12091
12846
|
try {
|
|
12092
12847
|
const doc = UnityDocument.from_file(file);
|
|
12093
12848
|
let block = null;
|
|
@@ -12150,6 +12905,10 @@ function build_read_command(getScanner) {
|
|
|
12150
12905
|
i++;
|
|
12151
12906
|
}
|
|
12152
12907
|
}
|
|
12908
|
+
const removed_components = parse_removed_list(block.raw, "m_RemovedComponents");
|
|
12909
|
+
const removed_gameobjects = parse_removed_list(block.raw, "m_RemovedGameObjects");
|
|
12910
|
+
const added_gameobjects = parse_added_list(block.raw, "m_AddedGameObjects");
|
|
12911
|
+
const added_components = parse_added_list(block.raw, "m_AddedComponents");
|
|
12153
12912
|
if (options.flat) {
|
|
12154
12913
|
const flat = modifications.map((m) => ({
|
|
12155
12914
|
property_path: m.property_path,
|
|
@@ -12158,7 +12917,14 @@ function build_read_command(getScanner) {
|
|
|
12158
12917
|
}));
|
|
12159
12918
|
console.log(JSON.stringify(flat, null, 2));
|
|
12160
12919
|
} else {
|
|
12161
|
-
console.log(JSON.stringify(
|
|
12920
|
+
console.log(JSON.stringify({
|
|
12921
|
+
prefab_instance_id: block.file_id,
|
|
12922
|
+
modifications,
|
|
12923
|
+
removed_components,
|
|
12924
|
+
removed_gameobjects,
|
|
12925
|
+
added_gameobjects,
|
|
12926
|
+
added_components
|
|
12927
|
+
}, null, 2));
|
|
12162
12928
|
}
|
|
12163
12929
|
} catch (err) {
|
|
12164
12930
|
console.log(JSON.stringify({ error: err instanceof Error ? err.message : String(err) }, null, 2));
|
|
@@ -12418,9 +13184,7 @@ function build_read_command(getScanner) {
|
|
|
12418
13184
|
types: displayed
|
|
12419
13185
|
}, null, 2));
|
|
12420
13186
|
});
|
|
12421
|
-
cmd.command("log
|
|
12422
|
-
if (projectPath && !options.project)
|
|
12423
|
-
options.project = projectPath;
|
|
13187
|
+
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) => {
|
|
12424
13188
|
const logPath = options.path || get_editor_log_path();
|
|
12425
13189
|
if (!logPath || !import_fs18.existsSync(logPath)) {
|
|
12426
13190
|
console.log(JSON.stringify({ error: `Editor.log not found${logPath ? `: ${logPath}` : ". Could not detect platform log path."}` }, null, 2));
|
|
@@ -12429,9 +13193,9 @@ function build_read_command(getScanner) {
|
|
|
12429
13193
|
const content = import_fs18.readFileSync(logPath, "utf-8");
|
|
12430
13194
|
let lines = content.split(/\r?\n/);
|
|
12431
13195
|
if (options.project) {
|
|
12432
|
-
const
|
|
12433
|
-
const projectName = import_path8.basename(
|
|
12434
|
-
const escapedPath =
|
|
13196
|
+
const projectPath = import_path8.resolve(options.project);
|
|
13197
|
+
const projectName = import_path8.basename(projectPath);
|
|
13198
|
+
const escapedPath = projectPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
12435
13199
|
const escapedName = projectName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
12436
13200
|
const session_markers = [
|
|
12437
13201
|
new RegExp(`Loading project at '${escapedPath}'`),
|
|
@@ -12876,7 +13640,7 @@ function build_read_command(getScanner) {
|
|
|
12876
13640
|
}
|
|
12877
13641
|
const states_out = { file, states_by_layer: by_layer };
|
|
12878
13642
|
if (needs_setup_hint)
|
|
12879
|
-
states_out._hint = "Run 'setup <
|
|
13643
|
+
states_out._hint = "Run 'setup' (or 'setup -p <path>') to resolve motion paths";
|
|
12880
13644
|
console.log(JSON.stringify(states_out, null, 2));
|
|
12881
13645
|
return;
|
|
12882
13646
|
}
|
|
@@ -12925,14 +13689,15 @@ function build_read_command(getScanner) {
|
|
|
12925
13689
|
}))
|
|
12926
13690
|
};
|
|
12927
13691
|
if (needs_setup_hint)
|
|
12928
|
-
default_out._hint = "Run 'setup <
|
|
13692
|
+
default_out._hint = "Run 'setup' (or 'setup -p <path>') to resolve motion paths";
|
|
12929
13693
|
console.log(JSON.stringify(default_out, null, 2));
|
|
12930
13694
|
});
|
|
12931
|
-
cmd.command("dependents <
|
|
13695
|
+
cmd.command("dependents <guid>").description("Find which files reference a given GUID (reverse dependency lookup)").option("-p, --project <path>", "Unity project path (defaults to cwd)").option("--type <type>", "Filter to specific file types (scene, prefab, mat, etc.)").option("-j, --json", "Output as JSON").action((guid, options) => {
|
|
12932
13696
|
if (!/^[0-9a-f]{32}$/i.test(guid)) {
|
|
12933
13697
|
console.log(JSON.stringify({ error: "GUID must be a 32-character hexadecimal string" }, null, 2));
|
|
12934
13698
|
process.exit(1);
|
|
12935
13699
|
}
|
|
13700
|
+
const project_path = resolve_project_path(options.project);
|
|
12936
13701
|
const assetsDir = import_path8.join(import_path8.resolve(project_path), "Assets");
|
|
12937
13702
|
if (!import_fs18.existsSync(assetsDir)) {
|
|
12938
13703
|
console.log(JSON.stringify({ error: `Assets directory not found in "${project_path}"` }, null, 2));
|
|
@@ -12990,11 +13755,11 @@ function build_read_command(getScanner) {
|
|
|
12990
13755
|
by_type
|
|
12991
13756
|
}, null, 2));
|
|
12992
13757
|
});
|
|
12993
|
-
cmd.command("unused
|
|
12994
|
-
const resolvedProject =
|
|
13758
|
+
cmd.command("unused").description("Find potentially unused assets (zero inbound GUID references)").option("-p, --project <path>", "Unity project path (defaults to cwd)").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((options) => {
|
|
13759
|
+
const resolvedProject = resolve_project_path(options.project);
|
|
12995
13760
|
const assetsDir = import_path8.join(resolvedProject, "Assets");
|
|
12996
13761
|
if (!import_fs18.existsSync(assetsDir)) {
|
|
12997
|
-
console.log(JSON.stringify({ error: `Assets directory not found in "${
|
|
13762
|
+
console.log(JSON.stringify({ error: `Assets directory not found in "${resolvedProject}"` }, null, 2));
|
|
12998
13763
|
process.exit(1);
|
|
12999
13764
|
}
|
|
13000
13765
|
const guidCacheObj = load_guid_cache(resolvedProject);
|
|
@@ -13085,7 +13850,8 @@ function build_read_command(getScanner) {
|
|
|
13085
13850
|
by_type
|
|
13086
13851
|
}, null, 2));
|
|
13087
13852
|
});
|
|
13088
|
-
cmd.command("manifest
|
|
13853
|
+
cmd.command("manifest").description("List packages from Packages/manifest.json").option("-p, --project <path>", "Unity project path (defaults to cwd)").option("--search <pattern>", "Filter packages by name pattern").option("-j, --json", "Output as JSON").action((options) => {
|
|
13854
|
+
const project_path = resolve_project_path(options.project);
|
|
13089
13855
|
const result = list_packages(project_path, options.search);
|
|
13090
13856
|
if ("error" in result) {
|
|
13091
13857
|
console.log(JSON.stringify({ success: false, error: result.error }, null, 2));
|
|
@@ -13404,13 +14170,14 @@ function build_update_command(getScanner) {
|
|
|
13404
14170
|
if (!result.success)
|
|
13405
14171
|
process.exitCode = 1;
|
|
13406
14172
|
});
|
|
13407
|
-
cmd.command("settings
|
|
14173
|
+
cmd.command("settings").description("Edit a property in any ProjectSettings/*.asset file").option("-p, --project <path>", "Unity project path (defaults to cwd)").option("-s, --setting <name>", "Setting name or alias").option("--property <name>", "Property name to edit").option("--value <value>", "New value").option("-j, --json", "Output as JSON").action((options) => {
|
|
13408
14174
|
if (!options.setting || !options.property || !options.value) {
|
|
13409
14175
|
console.log(JSON.stringify({ success: false, error: "Required: --setting, --property, --value" }, null, 2));
|
|
13410
14176
|
process.exit(1);
|
|
13411
14177
|
}
|
|
14178
|
+
const resolvedProjectPath = resolve_project_path(options.project);
|
|
13412
14179
|
const result = edit_settings({
|
|
13413
|
-
project_path,
|
|
14180
|
+
project_path: resolvedProjectPath,
|
|
13414
14181
|
setting: options.setting,
|
|
13415
14182
|
property: options.property,
|
|
13416
14183
|
value: options.value
|
|
@@ -13419,13 +14186,14 @@ function build_update_command(getScanner) {
|
|
|
13419
14186
|
if (!result.success)
|
|
13420
14187
|
process.exitCode = 1;
|
|
13421
14188
|
});
|
|
13422
|
-
cmd.command("tag <
|
|
14189
|
+
cmd.command("tag <action> <tag>").description("Add or remove a tag in the TagManager").option("-p, --project <path>", "Unity project path (defaults to cwd)").option("-j, --json", "Output as JSON").action((action, tag, options) => {
|
|
13423
14190
|
if (action !== "add" && action !== "remove") {
|
|
13424
14191
|
console.log(JSON.stringify({ success: false, error: 'Action must be "add" or "remove"' }, null, 2));
|
|
13425
14192
|
process.exit(1);
|
|
13426
14193
|
}
|
|
14194
|
+
const resolvedProjectPath = resolve_project_path(options.project);
|
|
13427
14195
|
const result = edit_tag({
|
|
13428
|
-
project_path,
|
|
14196
|
+
project_path: resolvedProjectPath,
|
|
13429
14197
|
action,
|
|
13430
14198
|
tag
|
|
13431
14199
|
});
|
|
@@ -13433,9 +14201,10 @@ function build_update_command(getScanner) {
|
|
|
13433
14201
|
if (!result.success)
|
|
13434
14202
|
process.exitCode = 1;
|
|
13435
14203
|
});
|
|
13436
|
-
cmd.command("layer <
|
|
14204
|
+
cmd.command("layer <index> <name>").description("Set a named layer at a specific index (3-31)").option("-p, --project <path>", "Unity project path (defaults to cwd)").option("-j, --json", "Output as JSON").action((index, name, options) => {
|
|
14205
|
+
const resolvedProjectPath = resolve_project_path(options.project);
|
|
13437
14206
|
const result = edit_layer({
|
|
13438
|
-
project_path,
|
|
14207
|
+
project_path: resolvedProjectPath,
|
|
13439
14208
|
index: parseInt(index, 10),
|
|
13440
14209
|
name
|
|
13441
14210
|
});
|
|
@@ -13443,13 +14212,14 @@ function build_update_command(getScanner) {
|
|
|
13443
14212
|
if (!result.success)
|
|
13444
14213
|
process.exitCode = 1;
|
|
13445
14214
|
});
|
|
13446
|
-
cmd.command("sorting-layer <
|
|
14215
|
+
cmd.command("sorting-layer <action> <name>").description("Add or remove a sorting layer").option("-p, --project <path>", "Unity project path (defaults to cwd)").option("-j, --json", "Output as JSON").action((action, name, options) => {
|
|
13447
14216
|
if (action !== "add" && action !== "remove") {
|
|
13448
14217
|
console.log(JSON.stringify({ success: false, error: 'Action must be "add" or "remove"' }, null, 2));
|
|
13449
14218
|
process.exit(1);
|
|
13450
14219
|
}
|
|
14220
|
+
const resolvedProjectPath = resolve_project_path(options.project);
|
|
13451
14221
|
const result = edit_sorting_layer({
|
|
13452
|
-
project_path,
|
|
14222
|
+
project_path: resolvedProjectPath,
|
|
13453
14223
|
action,
|
|
13454
14224
|
name
|
|
13455
14225
|
});
|
|
@@ -13549,20 +14319,21 @@ function build_update_command(getScanner) {
|
|
|
13549
14319
|
if (!result.success)
|
|
13550
14320
|
process.exitCode = 1;
|
|
13551
14321
|
});
|
|
13552
|
-
cmd.command("build <
|
|
14322
|
+
cmd.command("build <scene_path>").description("Enable, disable, or move a scene in build settings").option("-p, --project <path>", "Unity project path (defaults to cwd)").option("--enable", "Enable the scene").option("--disable", "Disable the scene").option("--move <index>", "Move scene to position").option("-j, --json", "Output as JSON").action((scene_path, options) => {
|
|
13553
14323
|
try {
|
|
14324
|
+
const resolvedProjectPath = resolve_project_path(options.project);
|
|
13554
14325
|
if (options.move !== undefined) {
|
|
13555
|
-
const result = move_scene(
|
|
14326
|
+
const result = move_scene(resolvedProjectPath, scene_path, parseInt(options.move, 10));
|
|
13556
14327
|
console.log(JSON.stringify(result, null, 2));
|
|
13557
14328
|
if (!result.success)
|
|
13558
14329
|
process.exitCode = 1;
|
|
13559
14330
|
} else if (options.enable) {
|
|
13560
|
-
const result = enable_scene(
|
|
14331
|
+
const result = enable_scene(resolvedProjectPath, scene_path);
|
|
13561
14332
|
console.log(JSON.stringify(result, null, 2));
|
|
13562
14333
|
if (!result.success)
|
|
13563
14334
|
process.exitCode = 1;
|
|
13564
14335
|
} else if (options.disable) {
|
|
13565
|
-
const result = disable_scene(
|
|
14336
|
+
const result = disable_scene(resolvedProjectPath, scene_path);
|
|
13566
14337
|
console.log(JSON.stringify(result, null, 2));
|
|
13567
14338
|
if (!result.success)
|
|
13568
14339
|
process.exitCode = 1;
|
|
@@ -15256,9 +16027,10 @@ function build_delete_command() {
|
|
|
15256
16027
|
process.exitCode = 1;
|
|
15257
16028
|
}
|
|
15258
16029
|
});
|
|
15259
|
-
cmd.command("build <
|
|
16030
|
+
cmd.command("build <scene_path>").description("Remove a scene from build settings").option("-p, --project <path>", "Unity project path (defaults to cwd)").option("-j, --json", "Output as JSON").action((scene_path, options) => {
|
|
16031
|
+
const resolvedProjectPath = resolve_project_path(options.project);
|
|
15260
16032
|
try {
|
|
15261
|
-
const result = remove_scene(
|
|
16033
|
+
const result = remove_scene(resolvedProjectPath, scene_path);
|
|
15262
16034
|
console.log(JSON.stringify(result, null, 2));
|
|
15263
16035
|
if (!result.success)
|
|
15264
16036
|
process.exitCode = 1;
|
|
@@ -15276,9 +16048,10 @@ function build_delete_command() {
|
|
|
15276
16048
|
if (!result.success)
|
|
15277
16049
|
process.exitCode = 1;
|
|
15278
16050
|
});
|
|
15279
|
-
cmd.command("package <
|
|
16051
|
+
cmd.command("package <name>").description("Remove a package from Packages/manifest.json").option("-p, --project <path>", "Unity project path (defaults to cwd)").option("-j, --json", "Output as JSON").action((name, options) => {
|
|
15280
16052
|
try {
|
|
15281
|
-
const
|
|
16053
|
+
const resolvedProjectPath = resolve_project_path(options.project);
|
|
16054
|
+
const result = remove_package(resolvedProjectPath, name);
|
|
15282
16055
|
if ("error" in result) {
|
|
15283
16056
|
console.log(JSON.stringify({ success: false, error: result.error }, null, 2));
|
|
15284
16057
|
process.exitCode = 1;
|
|
@@ -15565,7 +16338,7 @@ function generate_id() {
|
|
|
15565
16338
|
var BRIDGE_PACKAGE_NAME = "com.unity-agentic-tools.editor-bridge";
|
|
15566
16339
|
var BRIDGE_PACKAGE_VERSION = "https://github.com/taconotsandwich/unity-agentic-tools.git?path=unity-package";
|
|
15567
16340
|
function get_common_options(cmd) {
|
|
15568
|
-
let current = cmd
|
|
16341
|
+
let current = cmd;
|
|
15569
16342
|
let project;
|
|
15570
16343
|
let timeout_str;
|
|
15571
16344
|
let port_str;
|
|
@@ -15757,9 +16530,9 @@ function build_editor_command() {
|
|
|
15757
16530
|
params.mode = options.mode;
|
|
15758
16531
|
await handle_rpc(this, "editor.tests.run", params);
|
|
15759
16532
|
});
|
|
15760
|
-
cmd.command("install
|
|
15761
|
-
const
|
|
15762
|
-
const result = add_package(
|
|
16533
|
+
cmd.command("install").description("Install the editor bridge package into a Unity project").option("-p, --project <path>", "Path to Unity project (defaults to cwd)").action(function() {
|
|
16534
|
+
const { project_path } = get_common_options(this);
|
|
16535
|
+
const result = add_package(project_path, BRIDGE_PACKAGE_NAME, BRIDGE_PACKAGE_VERSION);
|
|
15763
16536
|
if ("error" in result) {
|
|
15764
16537
|
console.log(JSON.stringify({ success: false, error: result.error }, null, 2));
|
|
15765
16538
|
process.exitCode = 1;
|
|
@@ -15767,9 +16540,9 @@ function build_editor_command() {
|
|
|
15767
16540
|
}
|
|
15768
16541
|
console.log(JSON.stringify(result, null, 2));
|
|
15769
16542
|
});
|
|
15770
|
-
cmd.command("uninstall
|
|
15771
|
-
const
|
|
15772
|
-
const result = remove_package(
|
|
16543
|
+
cmd.command("uninstall").description("Remove the editor bridge package from a Unity project").option("-p, --project <path>", "Path to Unity project (defaults to cwd)").action(function() {
|
|
16544
|
+
const { project_path } = get_common_options(this);
|
|
16545
|
+
const result = remove_package(project_path, BRIDGE_PACKAGE_NAME);
|
|
15773
16546
|
if ("error" in result) {
|
|
15774
16547
|
console.log(JSON.stringify({ success: false, error: result.error }, null, 2));
|
|
15775
16548
|
process.exitCode = 1;
|
|
@@ -16100,11 +16873,12 @@ program.command("search <path> [pattern]").description("Search for GameObjects.
|
|
|
16100
16873
|
console.log(JSON.stringify(result, null, 2));
|
|
16101
16874
|
}
|
|
16102
16875
|
});
|
|
16103
|
-
program.command("grep <
|
|
16876
|
+
program.command("grep <pattern>").description("Search for a regex pattern across project files").option("-p, --project <path>", "Unity project path (defaults to cwd)").option("--type <type>", "File type filter: cs, yaml, unity, prefab, asset, all", "all").option("-m, --max <n>", "Max results (default: 100)", "100").option("-C, --context <n>", "Context lines around matches", "0").option("-j, --json", "Output as JSON").action((pattern, options) => {
|
|
16104
16877
|
if (!pattern || pattern.trim() === "") {
|
|
16105
16878
|
console.log(JSON.stringify({ success: false, error: "Pattern must not be empty" }, null, 2));
|
|
16106
16879
|
process.exit(1);
|
|
16107
16880
|
}
|
|
16881
|
+
let project_path = resolve_project_path(options.project);
|
|
16108
16882
|
const abs_path = path9.resolve(project_path);
|
|
16109
16883
|
const project_root = find_unity_project_root(abs_path);
|
|
16110
16884
|
if (project_root) {
|
|
@@ -16132,8 +16906,9 @@ program.command("grep <project_path> <pattern>").description("Search for a regex
|
|
|
16132
16906
|
if (!result.success)
|
|
16133
16907
|
process.exitCode = 1;
|
|
16134
16908
|
});
|
|
16135
|
-
program.command("version
|
|
16909
|
+
program.command("version").description("Read Unity project version").option("-p, --project <path>", "Unity project path (defaults to cwd)").option("-j, --json", "Output as JSON").action((options) => {
|
|
16136
16910
|
try {
|
|
16911
|
+
const project_path = resolve_project_path(options.project);
|
|
16137
16912
|
const version = read_project_version(project_path);
|
|
16138
16913
|
console.log(JSON.stringify(version, null, 2));
|
|
16139
16914
|
} catch (err) {
|