unity-agentic-tools 0.3.1 → 0.3.3
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 +4 -4
- package/dist/cli.js +2155 -546
- package/dist/index.js +1036 -306
- 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/index.js
CHANGED
|
@@ -76,6 +76,7 @@ __export(exports_scanner, {
|
|
|
76
76
|
getNativeExtractCsharpTypes: () => getNativeExtractCsharpTypes,
|
|
77
77
|
getNativeBuildTypeRegistry: () => getNativeBuildTypeRegistry,
|
|
78
78
|
getNativeBuildPackageGuidCache: () => getNativeBuildPackageGuidCache,
|
|
79
|
+
getNativeBuildLocalPackageGuidCache: () => getNativeBuildLocalPackageGuidCache,
|
|
79
80
|
getNativeBuildGuidCache: () => getNativeBuildGuidCache,
|
|
80
81
|
UnityScanner: () => UnityScanner
|
|
81
82
|
});
|
|
@@ -156,13 +157,16 @@ function getNativeExtractDllTypes() {
|
|
|
156
157
|
function getNativeBuildPackageGuidCache() {
|
|
157
158
|
return nativeBuildPackageGuidCache;
|
|
158
159
|
}
|
|
160
|
+
function getNativeBuildLocalPackageGuidCache() {
|
|
161
|
+
return nativeBuildLocalPackageGuidCache;
|
|
162
|
+
}
|
|
159
163
|
function getNativeExtractSerializedFields() {
|
|
160
164
|
return nativeExtractSerializedFields;
|
|
161
165
|
}
|
|
162
166
|
function getNativeExtractDllFields() {
|
|
163
167
|
return nativeExtractDllFields;
|
|
164
168
|
}
|
|
165
|
-
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;
|
|
169
|
+
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;
|
|
166
170
|
var init_scanner = __esm(() => {
|
|
167
171
|
import_module = require("module");
|
|
168
172
|
import_fs = require("fs");
|
|
@@ -186,6 +190,7 @@ var init_scanner = __esm(() => {
|
|
|
186
190
|
nativeBuildTypeRegistry = rustModule.buildTypeRegistry || null;
|
|
187
191
|
nativeExtractDllTypes = rustModule.extractDllTypes || null;
|
|
188
192
|
nativeBuildPackageGuidCache = rustModule.buildPackageGuidCache || null;
|
|
193
|
+
nativeBuildLocalPackageGuidCache = rustModule.buildLocalPackageGuidCache || null;
|
|
189
194
|
nativeExtractSerializedFields = rustModule.extractSerializedFields || null;
|
|
190
195
|
nativeExtractDllFields = rustModule.extractDllFields || null;
|
|
191
196
|
} catch (err) {
|
|
@@ -200,7 +205,7 @@ var require_package = __commonJS((exports2, module2) => {
|
|
|
200
205
|
module2.exports = {
|
|
201
206
|
name: "unity-agentic-tools",
|
|
202
207
|
packageManager: "bun@latest",
|
|
203
|
-
version: "0.3.
|
|
208
|
+
version: "0.3.3",
|
|
204
209
|
description: "Fast, token-efficient Unity YAML parser for AI agents",
|
|
205
210
|
exports: {
|
|
206
211
|
".": {
|
|
@@ -330,6 +335,7 @@ var CONFIG_DIR = ".unity-agentic";
|
|
|
330
335
|
var CONFIG_FILE = "config.json";
|
|
331
336
|
var GUID_CACHE_FILE = "guid-cache.json";
|
|
332
337
|
var PACKAGE_CACHE_FILE = "package-cache.json";
|
|
338
|
+
var LOCAL_PACKAGE_CACHE_FILE = "local-package-cache.json";
|
|
333
339
|
var TYPE_REGISTRY_FILE = "type-registry.json";
|
|
334
340
|
var DOC_INDEX_FILE = "doc-index.json";
|
|
335
341
|
function setup(options = {}) {
|
|
@@ -373,6 +379,17 @@ function setup(options = {}) {
|
|
|
373
379
|
packageGuidCount = Object.keys(packageCache).length;
|
|
374
380
|
} catch {}
|
|
375
381
|
}
|
|
382
|
+
const nativeLocalPkgBuild = getNativeBuildLocalPackageGuidCache();
|
|
383
|
+
if (nativeLocalPkgBuild) {
|
|
384
|
+
try {
|
|
385
|
+
const localPkgCache = nativeLocalPkgBuild(projectPath);
|
|
386
|
+
const localPkgCount = Object.keys(localPkgCache).length;
|
|
387
|
+
if (localPkgCount > 0) {
|
|
388
|
+
const localPkgCachePath = import_path2.join(configPath, LOCAL_PACKAGE_CACHE_FILE);
|
|
389
|
+
import_fs2.writeFileSync(localPkgCachePath, JSON.stringify(localPkgCache, null, 2));
|
|
390
|
+
}
|
|
391
|
+
} catch {}
|
|
392
|
+
}
|
|
376
393
|
let typeRegistryCreated = false;
|
|
377
394
|
let typeCount;
|
|
378
395
|
const nativeRegistryBuild = getNativeBuildTypeRegistry();
|
|
@@ -555,31 +572,44 @@ function atomicWrite(filePath, content) {
|
|
|
555
572
|
};
|
|
556
573
|
}
|
|
557
574
|
}
|
|
558
|
-
const
|
|
575
|
+
const suffix = `${process.pid}-${Math.random().toString(36).slice(2, 8)}`;
|
|
576
|
+
const tmpPath = `${filePath}.${suffix}.tmp`;
|
|
577
|
+
const bakPath = `${filePath}.${suffix}.bak`;
|
|
578
|
+
let bakCreated = false;
|
|
559
579
|
try {
|
|
560
580
|
import_fs4.writeFileSync(tmpPath, content, "utf-8");
|
|
561
|
-
if (import_fs4.existsSync(filePath)) {
|
|
562
|
-
import_fs4.renameSync(filePath, `${filePath}.bak`);
|
|
563
|
-
}
|
|
564
|
-
import_fs4.renameSync(tmpPath, filePath);
|
|
565
581
|
try {
|
|
566
|
-
|
|
567
|
-
|
|
582
|
+
import_fs4.renameSync(filePath, bakPath);
|
|
583
|
+
bakCreated = true;
|
|
584
|
+
} catch (err) {
|
|
585
|
+
if (is_enoent(err)) {
|
|
586
|
+
bakCreated = false;
|
|
587
|
+
} else {
|
|
588
|
+
throw err;
|
|
568
589
|
}
|
|
569
|
-
}
|
|
590
|
+
}
|
|
591
|
+
import_fs4.renameSync(tmpPath, filePath);
|
|
592
|
+
if (bakCreated) {
|
|
593
|
+
try {
|
|
594
|
+
import_fs4.unlinkSync(bakPath);
|
|
595
|
+
} catch {}
|
|
596
|
+
}
|
|
570
597
|
return {
|
|
571
598
|
success: true,
|
|
572
599
|
file_path: filePath,
|
|
573
600
|
bytes_written: Buffer.byteLength(content, "utf-8")
|
|
574
601
|
};
|
|
575
602
|
} catch (error) {
|
|
576
|
-
if (
|
|
603
|
+
if (bakCreated) {
|
|
577
604
|
try {
|
|
578
|
-
import_fs4.renameSync(
|
|
605
|
+
import_fs4.renameSync(bakPath, filePath);
|
|
579
606
|
} catch (restoreError) {
|
|
580
607
|
console.error("Failed to restore backup:", restoreError);
|
|
581
608
|
}
|
|
582
609
|
}
|
|
610
|
+
try {
|
|
611
|
+
import_fs4.unlinkSync(tmpPath);
|
|
612
|
+
} catch {}
|
|
583
613
|
return {
|
|
584
614
|
success: false,
|
|
585
615
|
file_path: filePath,
|
|
@@ -587,6 +617,12 @@ function atomicWrite(filePath, content) {
|
|
|
587
617
|
};
|
|
588
618
|
}
|
|
589
619
|
}
|
|
620
|
+
function is_enoent(err) {
|
|
621
|
+
return err instanceof Error && "code" in err && err.code === "ENOENT";
|
|
622
|
+
}
|
|
623
|
+
function normalize_property_path(path) {
|
|
624
|
+
return path.replace(/\.Array\.data\.(\d+)/g, ".Array.data[$1]");
|
|
625
|
+
}
|
|
590
626
|
function is_match_all(pattern) {
|
|
591
627
|
return pattern === "*" || pattern === "." || pattern === "**" || pattern === ".*";
|
|
592
628
|
}
|
|
@@ -2076,6 +2112,31 @@ function extractGuidFromMeta(metaPath) {
|
|
|
2076
2112
|
return null;
|
|
2077
2113
|
}
|
|
2078
2114
|
}
|
|
2115
|
+
function resolve_source_prefab(doc, file_path, project_path) {
|
|
2116
|
+
const pi_blocks = doc.find_by_class_id(1001);
|
|
2117
|
+
if (pi_blocks.length === 0)
|
|
2118
|
+
return null;
|
|
2119
|
+
const pi_block = pi_blocks[0];
|
|
2120
|
+
const source_match = pi_block.raw.match(/m_SourcePrefab:[ \t]*\{[^}]*guid:[ \t]*([a-f0-9]{32})/);
|
|
2121
|
+
if (!source_match)
|
|
2122
|
+
return null;
|
|
2123
|
+
const source_guid = source_match[1];
|
|
2124
|
+
const resolved_project = project_path || find_unity_project_root(path3.dirname(file_path));
|
|
2125
|
+
if (!resolved_project)
|
|
2126
|
+
return null;
|
|
2127
|
+
const cache = load_guid_cache_for_file(file_path, resolved_project);
|
|
2128
|
+
if (!cache)
|
|
2129
|
+
return null;
|
|
2130
|
+
const source_path = cache.resolve_absolute(source_guid);
|
|
2131
|
+
if (!source_path || !import_fs8.existsSync(source_path))
|
|
2132
|
+
return null;
|
|
2133
|
+
return {
|
|
2134
|
+
source_guid,
|
|
2135
|
+
source_path,
|
|
2136
|
+
prefab_instance_id: pi_block.file_id,
|
|
2137
|
+
prefab_instance_block: pi_block
|
|
2138
|
+
};
|
|
2139
|
+
}
|
|
2079
2140
|
function resolveScriptGuid(script, projectPath) {
|
|
2080
2141
|
if (/^[a-f0-9]{32}$/i.test(script)) {
|
|
2081
2142
|
return { guid: script.toLowerCase(), path: null };
|
|
@@ -2125,27 +2186,122 @@ function resolveScriptGuid(script, projectPath) {
|
|
|
2125
2186
|
return false;
|
|
2126
2187
|
return true;
|
|
2127
2188
|
});
|
|
2128
|
-
if (matches.length === 1
|
|
2129
|
-
|
|
2189
|
+
if (matches.length === 1) {
|
|
2190
|
+
if (matches[0].guid) {
|
|
2191
|
+
return { guid: matches[0].guid, path: matches[0].filePath };
|
|
2192
|
+
}
|
|
2193
|
+
if (matches[0].filePath && projectPath) {
|
|
2194
|
+
const fullFilePath = path3.isAbsolute(matches[0].filePath) ? matches[0].filePath : path3.join(projectPath, matches[0].filePath);
|
|
2195
|
+
const metaPath = fullFilePath + ".meta";
|
|
2196
|
+
if (import_fs8.existsSync(metaPath)) {
|
|
2197
|
+
const guid = extractGuidFromMeta(metaPath);
|
|
2198
|
+
if (guid)
|
|
2199
|
+
return { guid, path: matches[0].filePath };
|
|
2200
|
+
}
|
|
2201
|
+
if (matches[0].filePath.startsWith("Packages/")) {
|
|
2202
|
+
const pkgPath = path3.join(projectPath, matches[0].filePath);
|
|
2203
|
+
const pkgMetaPath = pkgPath + ".meta";
|
|
2204
|
+
if (import_fs8.existsSync(pkgMetaPath)) {
|
|
2205
|
+
const guid = extractGuidFromMeta(pkgMetaPath);
|
|
2206
|
+
if (guid)
|
|
2207
|
+
return { guid, path: matches[0].filePath };
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
if (matches[0].filePath?.endsWith(".dll")) {
|
|
2211
|
+
const dllBasename = path3.basename(matches[0].filePath).toLowerCase();
|
|
2212
|
+
for (const cacheName of ["package-cache.json", "local-package-cache.json"]) {
|
|
2213
|
+
const cachePath = path3.join(projectPath, ".unity-agentic", cacheName);
|
|
2214
|
+
if (!import_fs8.existsSync(cachePath))
|
|
2215
|
+
continue;
|
|
2216
|
+
try {
|
|
2217
|
+
const cache = JSON.parse(import_fs8.readFileSync(cachePath, "utf-8"));
|
|
2218
|
+
for (const [guid, assetPath] of Object.entries(cache)) {
|
|
2219
|
+
if (assetPath.toLowerCase().endsWith(".dll") && path3.basename(assetPath).toLowerCase() === dllBasename) {
|
|
2220
|
+
return { guid, path: assetPath };
|
|
2221
|
+
}
|
|
2222
|
+
}
|
|
2223
|
+
} catch {}
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2130
2227
|
}
|
|
2131
2228
|
if (matches.length > 1) {
|
|
2132
2229
|
const withGuid = matches.filter((m) => m.guid);
|
|
2133
2230
|
if (withGuid.length === 1) {
|
|
2134
2231
|
return { guid: withGuid[0].guid, path: withGuid[0].filePath };
|
|
2135
2232
|
}
|
|
2233
|
+
const resolvedFromMeta = matches.filter((m) => !m.guid && m.filePath).map((m) => {
|
|
2234
|
+
const fullPath = path3.isAbsolute(m.filePath) ? m.filePath : path3.join(projectPath, m.filePath);
|
|
2235
|
+
let guid = import_fs8.existsSync(fullPath + ".meta") ? extractGuidFromMeta(fullPath + ".meta") : null;
|
|
2236
|
+
if (!guid && m.filePath.startsWith("Packages/")) {
|
|
2237
|
+
const pkgPath = path3.join(projectPath, m.filePath);
|
|
2238
|
+
if (import_fs8.existsSync(pkgPath + ".meta")) {
|
|
2239
|
+
guid = extractGuidFromMeta(pkgPath + ".meta");
|
|
2240
|
+
}
|
|
2241
|
+
}
|
|
2242
|
+
if (!guid && m.filePath?.endsWith(".dll")) {
|
|
2243
|
+
const dllBase = path3.basename(m.filePath).toLowerCase();
|
|
2244
|
+
for (const cn of ["package-cache.json", "local-package-cache.json"]) {
|
|
2245
|
+
const cp = path3.join(projectPath, ".unity-agentic", cn);
|
|
2246
|
+
if (!import_fs8.existsSync(cp))
|
|
2247
|
+
continue;
|
|
2248
|
+
try {
|
|
2249
|
+
const c = JSON.parse(import_fs8.readFileSync(cp, "utf-8"));
|
|
2250
|
+
for (const [g, p] of Object.entries(c)) {
|
|
2251
|
+
if (p.toLowerCase().endsWith(".dll") && path3.basename(p).toLowerCase() === dllBase) {
|
|
2252
|
+
guid = g;
|
|
2253
|
+
break;
|
|
2254
|
+
}
|
|
2255
|
+
}
|
|
2256
|
+
} catch {}
|
|
2257
|
+
if (guid)
|
|
2258
|
+
break;
|
|
2259
|
+
}
|
|
2260
|
+
}
|
|
2261
|
+
return guid ? { guid, path: m.filePath } : null;
|
|
2262
|
+
}).filter((r) => r !== null);
|
|
2263
|
+
const allResolved = [...withGuid.map((m) => ({ guid: m.guid, path: m.filePath })), ...resolvedFromMeta];
|
|
2264
|
+
if (allResolved.length === 1) {
|
|
2265
|
+
return allResolved[0];
|
|
2266
|
+
}
|
|
2267
|
+
if (allResolved.length > 1) {
|
|
2268
|
+
const pkgCachePaths = [
|
|
2269
|
+
path3.join(projectPath, ".unity-agentic", "package-cache.json"),
|
|
2270
|
+
path3.join(projectPath, ".unity-agentic", "local-package-cache.json")
|
|
2271
|
+
];
|
|
2272
|
+
for (const cachePath of pkgCachePaths) {
|
|
2273
|
+
if (!import_fs8.existsSync(cachePath))
|
|
2274
|
+
continue;
|
|
2275
|
+
try {
|
|
2276
|
+
const cache = JSON.parse(import_fs8.readFileSync(cachePath, "utf-8"));
|
|
2277
|
+
const inCache = allResolved.filter((r) => (r.guid in cache));
|
|
2278
|
+
if (inCache.length === 1)
|
|
2279
|
+
return inCache[0];
|
|
2280
|
+
} catch {}
|
|
2281
|
+
}
|
|
2282
|
+
const paths = allResolved.map((m) => m.path).join(", ");
|
|
2283
|
+
throw new Error(`Ambiguous type "${script}": found ${allResolved.length} matches (${paths}). ` + `Use a qualified name (e.g., "Namespace.${targetName}") or provide the full path.`);
|
|
2284
|
+
}
|
|
2136
2285
|
}
|
|
2137
2286
|
} catch {}
|
|
2138
2287
|
}
|
|
2139
|
-
const
|
|
2140
|
-
|
|
2288
|
+
const scriptNameLower = script.toLowerCase().replace(/\.cs$/, "");
|
|
2289
|
+
const dotIdx = scriptNameLower.lastIndexOf(".");
|
|
2290
|
+
const classNameOnly = dotIdx > 0 ? scriptNameLower.substring(dotIdx + 1) : null;
|
|
2291
|
+
const cachePaths = [
|
|
2292
|
+
path3.join(projectPath, ".unity-agentic", "package-cache.json"),
|
|
2293
|
+
path3.join(projectPath, ".unity-agentic", "local-package-cache.json")
|
|
2294
|
+
];
|
|
2295
|
+
for (const cachePath of cachePaths) {
|
|
2296
|
+
if (!import_fs8.existsSync(cachePath))
|
|
2297
|
+
continue;
|
|
2141
2298
|
try {
|
|
2142
|
-
const
|
|
2143
|
-
const
|
|
2144
|
-
for (const [guid, assetPath] of Object.entries(packageCache)) {
|
|
2299
|
+
const cache = JSON.parse(import_fs8.readFileSync(cachePath, "utf-8"));
|
|
2300
|
+
for (const [guid, assetPath] of Object.entries(cache)) {
|
|
2145
2301
|
if (!assetPath.endsWith(".cs"))
|
|
2146
2302
|
continue;
|
|
2147
2303
|
const fileName = path3.basename(assetPath, ".cs").toLowerCase();
|
|
2148
|
-
if (fileName === scriptNameLower) {
|
|
2304
|
+
if (fileName === scriptNameLower || classNameOnly && fileName === classNameOnly) {
|
|
2149
2305
|
return { guid, path: assetPath };
|
|
2150
2306
|
}
|
|
2151
2307
|
}
|
|
@@ -2196,6 +2352,8 @@ function resolve_script_with_fields(script, project_path) {
|
|
|
2196
2352
|
result.fields = chosen.fields;
|
|
2197
2353
|
result.base_class = chosen.baseClass ?? undefined;
|
|
2198
2354
|
result.kind = chosen.kind;
|
|
2355
|
+
result.namespace = chosen.namespace ?? undefined;
|
|
2356
|
+
result.class_name = chosen.name;
|
|
2199
2357
|
}
|
|
2200
2358
|
} else {
|
|
2201
2359
|
result.extraction_error = "Native extractDllFields function not available";
|
|
@@ -2244,178 +2402,61 @@ function resolve_enum_fields(fields, project_path) {
|
|
|
2244
2402
|
}
|
|
2245
2403
|
} catch {}
|
|
2246
2404
|
}
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
String: "",
|
|
2268
|
-
Byte: "0",
|
|
2269
|
-
SByte: "0",
|
|
2270
|
-
Int16: "0",
|
|
2271
|
-
UInt16: "0",
|
|
2272
|
-
UInt32: "0",
|
|
2273
|
-
Int64: "0",
|
|
2274
|
-
UInt64: "0",
|
|
2275
|
-
Char: "0"
|
|
2276
|
-
};
|
|
2277
|
-
var STRUCT_DEFAULTS = {
|
|
2278
|
-
Vector2: "{x: 0, y: 0}",
|
|
2279
|
-
Vector3: "{x: 0, y: 0, z: 0}",
|
|
2280
|
-
Vector4: "{x: 0, y: 0, z: 0, w: 0}",
|
|
2281
|
-
Vector2Int: "{x: 0, y: 0}",
|
|
2282
|
-
Vector3Int: "{x: 0, y: 0, z: 0}",
|
|
2283
|
-
Quaternion: "{x: 0, y: 0, z: 0, w: 1}",
|
|
2284
|
-
Color: "{r: 0, g: 0, b: 0, a: 0}",
|
|
2285
|
-
Color32: "{r: 0, g: 0, b: 0, a: 0}",
|
|
2286
|
-
Rect: `serializedVersion: 2
|
|
2287
|
-
x: 0
|
|
2288
|
-
y: 0
|
|
2289
|
-
width: 0
|
|
2290
|
-
height: 0`,
|
|
2291
|
-
RectInt: "{x: 0, y: 0, width: 0, height: 0}",
|
|
2292
|
-
RectOffset: "{m_Left: 0, m_Right: 0, m_Top: 0, m_Bottom: 0}",
|
|
2293
|
-
Matrix4x4: "{e00: 1, e01: 0, e02: 0, e03: 0, e10: 0, e11: 1, e12: 0, e13: 0, e20: 0, e21: 0, e22: 1, e23: 0, e30: 0, e31: 0, e32: 0, e33: 1}",
|
|
2294
|
-
LayerMask: `serializedVersion: 2
|
|
2295
|
-
m_Bits: 0`
|
|
2296
|
-
};
|
|
2297
|
-
var VERSION_GATED_STRUCT_DEFAULTS = {
|
|
2298
|
-
Hash128: { value: `serializedVersion: 2
|
|
2299
|
-
Hash: 00000000000000000000000000000000`, min_major: 2021, min_minor: 1 },
|
|
2300
|
-
RenderingLayerMask: { value: `serializedVersion: 2
|
|
2301
|
-
m_Bits: 0`, min_major: 6000, min_minor: 0 }
|
|
2302
|
-
};
|
|
2303
|
-
var BLOCK_STRUCT_DEFAULTS = {
|
|
2304
|
-
Bounds: `m_Center: {x: 0, y: 0, z: 0}
|
|
2305
|
-
m_Extent: {x: 0, y: 0, z: 0}`,
|
|
2306
|
-
BoundsInt: `m_Position: {x: 0, y: 0, z: 0}
|
|
2307
|
-
m_Size: {x: 0, y: 0, z: 0}`
|
|
2308
|
-
};
|
|
2309
|
-
var OBJECT_REF_TYPES = new Set([
|
|
2310
|
-
"GameObject",
|
|
2311
|
-
"Transform",
|
|
2312
|
-
"RectTransform",
|
|
2313
|
-
"Material",
|
|
2314
|
-
"Texture",
|
|
2315
|
-
"Texture2D",
|
|
2316
|
-
"Texture3D",
|
|
2317
|
-
"RenderTexture",
|
|
2318
|
-
"Sprite",
|
|
2319
|
-
"AudioClip",
|
|
2320
|
-
"VideoClip",
|
|
2321
|
-
"Mesh",
|
|
2322
|
-
"Shader",
|
|
2323
|
-
"ComputeShader",
|
|
2324
|
-
"AnimationClip",
|
|
2325
|
-
"AnimatorController",
|
|
2326
|
-
"RuntimeAnimatorController",
|
|
2327
|
-
"PhysicMaterial",
|
|
2328
|
-
"PhysicsMaterial",
|
|
2329
|
-
"PhysicsMaterial2D",
|
|
2330
|
-
"Font",
|
|
2331
|
-
"TMP_FontAsset",
|
|
2332
|
-
"Object",
|
|
2333
|
-
"Component",
|
|
2334
|
-
"Behaviour",
|
|
2335
|
-
"MonoBehaviour",
|
|
2336
|
-
"ScriptableObject",
|
|
2337
|
-
"Rigidbody",
|
|
2338
|
-
"Rigidbody2D",
|
|
2339
|
-
"Collider",
|
|
2340
|
-
"Collider2D",
|
|
2341
|
-
"Camera",
|
|
2342
|
-
"Light",
|
|
2343
|
-
"Canvas",
|
|
2344
|
-
"CanvasGroup",
|
|
2345
|
-
"EventSystem",
|
|
2346
|
-
"AudioSource",
|
|
2347
|
-
"ParticleSystem",
|
|
2348
|
-
"TextAsset",
|
|
2349
|
-
"TerrainData"
|
|
2350
|
-
]);
|
|
2351
|
-
function version_at_least(version, min_major, min_minor) {
|
|
2352
|
-
if (!version)
|
|
2353
|
-
return false;
|
|
2354
|
-
if (version.major > min_major)
|
|
2355
|
-
return true;
|
|
2356
|
-
if (version.major === min_major)
|
|
2357
|
-
return version.minor >= min_minor;
|
|
2358
|
-
return false;
|
|
2359
|
-
}
|
|
2360
|
-
function yaml_default_for_type(csharp_type, version) {
|
|
2361
|
-
if (csharp_type.endsWith("?")) {
|
|
2362
|
-
return null;
|
|
2363
|
-
}
|
|
2364
|
-
if (csharp_type in PRIMITIVE_DEFAULTS) {
|
|
2365
|
-
return PRIMITIVE_DEFAULTS[csharp_type];
|
|
2366
|
-
}
|
|
2367
|
-
if (csharp_type in STRUCT_DEFAULTS) {
|
|
2368
|
-
return STRUCT_DEFAULTS[csharp_type];
|
|
2369
|
-
}
|
|
2370
|
-
if (csharp_type in VERSION_GATED_STRUCT_DEFAULTS) {
|
|
2371
|
-
const gated = VERSION_GATED_STRUCT_DEFAULTS[csharp_type];
|
|
2372
|
-
if (version_at_least(version, gated.min_major, gated.min_minor)) {
|
|
2373
|
-
return gated.value;
|
|
2405
|
+
function build_type_lookup(project_path) {
|
|
2406
|
+
let extractFn = null;
|
|
2407
|
+
try {
|
|
2408
|
+
const { getNativeExtractSerializedFields: getNativeExtractSerializedFields2 } = (init_scanner(), __toCommonJS(exports_scanner));
|
|
2409
|
+
extractFn = getNativeExtractSerializedFields2();
|
|
2410
|
+
} catch {}
|
|
2411
|
+
if (!extractFn)
|
|
2412
|
+
return () => null;
|
|
2413
|
+
const assetsDir = path3.join(project_path, "Assets");
|
|
2414
|
+
const csIndex = new Map;
|
|
2415
|
+
try {
|
|
2416
|
+
const { readdirSync: readdirSync4 } = require("fs");
|
|
2417
|
+
const entries = readdirSync4(assetsDir, { recursive: true, withFileTypes: false });
|
|
2418
|
+
for (const entry of entries) {
|
|
2419
|
+
if (typeof entry === "string" && entry.endsWith(".cs")) {
|
|
2420
|
+
const basename4 = entry.substring(entry.lastIndexOf("/") + 1).replace(/\.cs$/, "");
|
|
2421
|
+
if (!csIndex.has(basename4)) {
|
|
2422
|
+
csIndex.set(basename4, path3.join(assetsDir, entry));
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2374
2425
|
}
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
return "{fileID: 0}";
|
|
2388
|
-
}
|
|
2389
|
-
return "{fileID: 0}";
|
|
2390
|
-
}
|
|
2391
|
-
function generate_field_yaml(fields, version, indent = " ") {
|
|
2392
|
-
const lines = [];
|
|
2393
|
-
for (const field of fields) {
|
|
2394
|
-
const default_value = yaml_default_for_type(field.typeName, version);
|
|
2395
|
-
if (default_value === null) {
|
|
2396
|
-
continue;
|
|
2426
|
+
} catch {}
|
|
2427
|
+
if (csIndex.size === 0)
|
|
2428
|
+
return () => null;
|
|
2429
|
+
const cache = new Map;
|
|
2430
|
+
return (typeName) => {
|
|
2431
|
+
if (cache.has(typeName))
|
|
2432
|
+
return cache.get(typeName) ?? null;
|
|
2433
|
+
const shortName = typeName.includes(".") ? typeName.substring(typeName.lastIndexOf(".") + 1) : typeName;
|
|
2434
|
+
const csPath = csIndex.get(shortName);
|
|
2435
|
+
if (!csPath || !import_fs8.existsSync(csPath)) {
|
|
2436
|
+
cache.set(typeName, null);
|
|
2437
|
+
return null;
|
|
2397
2438
|
}
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
lines.push(`${indent}${sub_line}`);
|
|
2439
|
+
try {
|
|
2440
|
+
const typeInfos = extractFn(csPath);
|
|
2441
|
+
if (!typeInfos || typeInfos.length === 0) {
|
|
2442
|
+
cache.set(typeName, null);
|
|
2443
|
+
return null;
|
|
2404
2444
|
}
|
|
2405
|
-
|
|
2406
|
-
|
|
2445
|
+
const match = typeInfos.find((t) => t.name === shortName);
|
|
2446
|
+
if (match && match.fields && match.fields.length > 0) {
|
|
2447
|
+
resolve_enum_fields(match.fields, project_path);
|
|
2448
|
+
cache.set(typeName, match.fields);
|
|
2449
|
+
return match.fields;
|
|
2450
|
+
}
|
|
2451
|
+
cache.set(typeName, null);
|
|
2452
|
+
return null;
|
|
2453
|
+
} catch {
|
|
2454
|
+
cache.set(typeName, null);
|
|
2455
|
+
return null;
|
|
2407
2456
|
}
|
|
2408
|
-
}
|
|
2409
|
-
return lines.length > 0 ? `
|
|
2410
|
-
` + lines.join(`
|
|
2411
|
-
`) + `
|
|
2412
|
-
` : `
|
|
2413
|
-
`;
|
|
2457
|
+
};
|
|
2414
2458
|
}
|
|
2415
2459
|
|
|
2416
|
-
// src/editor/unity-document.ts
|
|
2417
|
-
var import_fs9 = require("fs");
|
|
2418
|
-
|
|
2419
2460
|
// src/editor/unity-block.ts
|
|
2420
2461
|
var HEADER_PATTERN = /^--- !u!(\d+) &(-?\d+)(\s+stripped)?/;
|
|
2421
2462
|
function parse_header(raw) {
|
|
@@ -2434,6 +2475,17 @@ function parse_header(raw) {
|
|
|
2434
2475
|
function escape_regex(str) {
|
|
2435
2476
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2436
2477
|
}
|
|
2478
|
+
function yaml_quote_if_needed(value) {
|
|
2479
|
+
if (value === "")
|
|
2480
|
+
return value;
|
|
2481
|
+
if (value.startsWith("{") && value.endsWith("}") || value.startsWith("[") && value.endsWith("]")) {
|
|
2482
|
+
return value;
|
|
2483
|
+
}
|
|
2484
|
+
if (value.includes(": ") || value.includes(" #") || /^[#\{\[*&!|>'"]/.test(value) || value !== value.trim()) {
|
|
2485
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
2486
|
+
}
|
|
2487
|
+
return value;
|
|
2488
|
+
}
|
|
2437
2489
|
|
|
2438
2490
|
class UnityBlock {
|
|
2439
2491
|
_raw;
|
|
@@ -2469,6 +2521,7 @@ class UnityBlock {
|
|
|
2469
2521
|
return this._dirty;
|
|
2470
2522
|
}
|
|
2471
2523
|
get_property(path4) {
|
|
2524
|
+
path4 = normalize_property_path(path4);
|
|
2472
2525
|
if (path4.includes("Array.data[")) {
|
|
2473
2526
|
return this._get_array_element(path4);
|
|
2474
2527
|
}
|
|
@@ -2495,13 +2548,43 @@ class UnityBlock {
|
|
|
2495
2548
|
return match ? match[1].trim() : null;
|
|
2496
2549
|
}
|
|
2497
2550
|
set_property(path4, value, object_reference) {
|
|
2551
|
+
path4 = normalize_property_path(path4);
|
|
2498
2552
|
const old_raw = this._raw;
|
|
2499
2553
|
const effective_ref = object_reference && object_reference !== "{fileID: 0}" ? object_reference : undefined;
|
|
2500
2554
|
if (!path4.includes(".") && !path4.includes("Array")) {
|
|
2501
|
-
const prop_pattern = new RegExp(`(^\\s*${escape_regex(path4)}
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2555
|
+
const prop_pattern = new RegExp(`(^\\s*${escape_regex(path4)}:[ \\t]*)(.*)$`, "m");
|
|
2556
|
+
const match = this._raw.match(prop_pattern);
|
|
2557
|
+
if (match && match.index !== undefined) {
|
|
2558
|
+
const replacement_value = effective_ref ?? yaml_quote_if_needed(value);
|
|
2559
|
+
const current_inline = match[2];
|
|
2560
|
+
if (current_inline.trim() === "") {
|
|
2561
|
+
const key_indent = (match[0].match(/^[ \t]*/)?.[0] || "").length;
|
|
2562
|
+
const after = match.index + match[0].length;
|
|
2563
|
+
let end = after;
|
|
2564
|
+
const rest = this._raw.slice(after);
|
|
2565
|
+
const rest_lines = rest.split(`
|
|
2566
|
+
`);
|
|
2567
|
+
for (let i = 1;i < rest_lines.length; i++) {
|
|
2568
|
+
const line = rest_lines[i];
|
|
2569
|
+
if (line.trim() === "") {
|
|
2570
|
+
end += 1 + line.length;
|
|
2571
|
+
continue;
|
|
2572
|
+
}
|
|
2573
|
+
const line_indent = (line.match(/^[ \t]*/)?.[0] || "").length;
|
|
2574
|
+
if (line_indent > key_indent) {
|
|
2575
|
+
end += 1 + line.length;
|
|
2576
|
+
} else {
|
|
2577
|
+
break;
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
const prefix = match[1].trimEnd() + " ";
|
|
2581
|
+
this._raw = this._raw.slice(0, match.index) + prefix + replacement_value + this._raw.slice(end);
|
|
2582
|
+
} else {
|
|
2583
|
+
this._raw = this._raw.replace(prop_pattern, (_match, prefix) => prefix + replacement_value);
|
|
2584
|
+
}
|
|
2585
|
+
} else {
|
|
2586
|
+
const insert_value = effective_ref ?? yaml_quote_if_needed(value);
|
|
2587
|
+
this._insert_property(path4, insert_value);
|
|
2505
2588
|
}
|
|
2506
2589
|
return this._check_dirty(old_raw);
|
|
2507
2590
|
}
|
|
@@ -2516,8 +2599,8 @@ class UnityBlock {
|
|
|
2516
2599
|
const fields = inline_match[2];
|
|
2517
2600
|
const field_pattern = new RegExp(`(${escape_regex(sub_field)}:\\s*)([^,}]+)`);
|
|
2518
2601
|
if (field_pattern.test(fields)) {
|
|
2519
|
-
const updated_fields = fields.replace(field_pattern,
|
|
2520
|
-
this._raw = this._raw.replace(inline_pattern,
|
|
2602
|
+
const updated_fields = fields.replace(field_pattern, (_m, prefix) => prefix + value);
|
|
2603
|
+
this._raw = this._raw.replace(inline_pattern, (_m, g1, _g2, g3) => g1 + updated_fields + g3);
|
|
2521
2604
|
inline_applied = true;
|
|
2522
2605
|
}
|
|
2523
2606
|
}
|
|
@@ -2526,6 +2609,8 @@ class UnityBlock {
|
|
|
2526
2609
|
const block_result = this._resolve_block_style_path(parts, effective_value);
|
|
2527
2610
|
if (block_result !== null) {
|
|
2528
2611
|
this._raw = block_result;
|
|
2612
|
+
} else if (parts.length === 2) {
|
|
2613
|
+
this._insert_struct_property(parent_prop, sub_field, effective_value);
|
|
2529
2614
|
}
|
|
2530
2615
|
}
|
|
2531
2616
|
return this._check_dirty(old_raw);
|
|
@@ -2543,7 +2628,7 @@ class UnityBlock {
|
|
|
2543
2628
|
`).filter((l) => l.trim().startsWith("-"));
|
|
2544
2629
|
if (index < lines.length) {
|
|
2545
2630
|
const old_line = lines[index];
|
|
2546
|
-
const new_line = old_line.replace(/-\s*.*/, `- ${ref_value}`);
|
|
2631
|
+
const new_line = old_line.replace(/-\s*.*/, () => `- ${ref_value}`);
|
|
2547
2632
|
this._raw = this._raw.replace(old_line, new_line);
|
|
2548
2633
|
}
|
|
2549
2634
|
}
|
|
@@ -2552,6 +2637,49 @@ class UnityBlock {
|
|
|
2552
2637
|
}
|
|
2553
2638
|
return false;
|
|
2554
2639
|
}
|
|
2640
|
+
_insert_property(path4, value) {
|
|
2641
|
+
const alt = path4.startsWith("m_") ? path4.slice(2) : "m_" + path4;
|
|
2642
|
+
const alt_pattern = new RegExp(`^\\s*${escape_regex(alt)}:`, "m");
|
|
2643
|
+
if (alt_pattern.test(this._raw)) {
|
|
2644
|
+
return;
|
|
2645
|
+
}
|
|
2646
|
+
const indented_line = ` ${path4}: ${value}`;
|
|
2647
|
+
const eci_pattern = /^([ \t]*m_EditorClassIdentifier:[ \t]*[^\n]*)/m;
|
|
2648
|
+
const eci_match = this._raw.match(eci_pattern);
|
|
2649
|
+
if (eci_match && eci_match.index !== undefined) {
|
|
2650
|
+
const insert_after = eci_match.index + eci_match[0].length;
|
|
2651
|
+
this._raw = this._raw.slice(0, insert_after) + `
|
|
2652
|
+
` + indented_line + this._raw.slice(insert_after);
|
|
2653
|
+
return;
|
|
2654
|
+
}
|
|
2655
|
+
this._raw = this._raw.trimEnd() + `
|
|
2656
|
+
` + indented_line + `
|
|
2657
|
+
`;
|
|
2658
|
+
}
|
|
2659
|
+
_insert_struct_property(parent, child, value) {
|
|
2660
|
+
const parent_pattern = new RegExp(`^[ ]*${escape_regex(parent)}:`, "m");
|
|
2661
|
+
if (parent_pattern.test(this._raw)) {
|
|
2662
|
+
return;
|
|
2663
|
+
}
|
|
2664
|
+
const alt = parent.startsWith("m_") ? parent.slice(2) : "m_" + parent;
|
|
2665
|
+
const alt_pattern = new RegExp(`^[ \\t]*${escape_regex(alt)}:`, "m");
|
|
2666
|
+
if (alt_pattern.test(this._raw)) {
|
|
2667
|
+
return;
|
|
2668
|
+
}
|
|
2669
|
+
const struct_block = ` ${parent}:
|
|
2670
|
+
${child}: ${value}`;
|
|
2671
|
+
const eci_pattern = /^([ \t]*m_EditorClassIdentifier:[ \t]*[^\n]*)/m;
|
|
2672
|
+
const eci_match = this._raw.match(eci_pattern);
|
|
2673
|
+
if (eci_match && eci_match.index !== undefined) {
|
|
2674
|
+
const insert_after = eci_match.index + eci_match[0].length;
|
|
2675
|
+
this._raw = this._raw.slice(0, insert_after) + `
|
|
2676
|
+
` + struct_block + this._raw.slice(insert_after);
|
|
2677
|
+
return;
|
|
2678
|
+
}
|
|
2679
|
+
this._raw = this._raw.trimEnd() + `
|
|
2680
|
+
` + struct_block + `
|
|
2681
|
+
`;
|
|
2682
|
+
}
|
|
2555
2683
|
has_property(path4) {
|
|
2556
2684
|
return this.get_property(path4) !== null;
|
|
2557
2685
|
}
|
|
@@ -2607,7 +2735,7 @@ class UnityBlock {
|
|
|
2607
2735
|
if (empty_match) {
|
|
2608
2736
|
const base_indent = empty_match[2];
|
|
2609
2737
|
const element_indent2 = base_indent + " ";
|
|
2610
|
-
this._raw = this._raw.replace(empty_pattern, `$
|
|
2738
|
+
this._raw = this._raw.replace(empty_pattern, (_m, g1) => `${g1}
|
|
2611
2739
|
${element_indent2}- ${value}`);
|
|
2612
2740
|
return this._check_dirty(old_raw);
|
|
2613
2741
|
}
|
|
@@ -2840,81 +2968,359 @@ ${element_indent2}- ${value}`);
|
|
|
2840
2968
|
}
|
|
2841
2969
|
return null;
|
|
2842
2970
|
}
|
|
2843
|
-
_resolve_block_style_path(segments, value) {
|
|
2844
|
-
const lines = this._raw.split(`
|
|
2971
|
+
_resolve_block_style_path(segments, value) {
|
|
2972
|
+
const lines = this._raw.split(`
|
|
2973
|
+
`);
|
|
2974
|
+
let search_start = 0;
|
|
2975
|
+
let search_end = lines.length;
|
|
2976
|
+
for (let seg = 0;seg < segments.length - 1; seg++) {
|
|
2977
|
+
const segment = segments[seg];
|
|
2978
|
+
let parent_idx = -1;
|
|
2979
|
+
let parent_indent = -1;
|
|
2980
|
+
for (let i = search_start;i < search_end; i++) {
|
|
2981
|
+
const match = lines[i].match(new RegExp(`^(\\s*)${escape_regex(segment)}:\\s*(.*)$`));
|
|
2982
|
+
if (match) {
|
|
2983
|
+
const trailing = match[2].trim();
|
|
2984
|
+
if (trailing === "") {
|
|
2985
|
+
parent_idx = i;
|
|
2986
|
+
parent_indent = match[1].length;
|
|
2987
|
+
break;
|
|
2988
|
+
}
|
|
2989
|
+
for (let j = i + 1;j < search_end; j++) {
|
|
2990
|
+
if (lines[j].trim() === "")
|
|
2991
|
+
continue;
|
|
2992
|
+
const nextLeading = lines[j].match(/^(\s*)/);
|
|
2993
|
+
if (nextLeading && nextLeading[1].length > match[1].length) {
|
|
2994
|
+
parent_idx = i;
|
|
2995
|
+
parent_indent = match[1].length;
|
|
2996
|
+
}
|
|
2997
|
+
break;
|
|
2998
|
+
}
|
|
2999
|
+
if (parent_idx !== -1)
|
|
3000
|
+
break;
|
|
3001
|
+
}
|
|
3002
|
+
}
|
|
3003
|
+
if (parent_idx === -1)
|
|
3004
|
+
return null;
|
|
3005
|
+
let child_indent = -1;
|
|
3006
|
+
for (let i = parent_idx + 1;i < search_end; i++) {
|
|
3007
|
+
if (lines[i].trim() === "")
|
|
3008
|
+
continue;
|
|
3009
|
+
const leading_spaces = lines[i].match(/^(\s*)/);
|
|
3010
|
+
if (leading_spaces) {
|
|
3011
|
+
const indent = leading_spaces[1].length;
|
|
3012
|
+
if (indent > parent_indent) {
|
|
3013
|
+
child_indent = indent;
|
|
3014
|
+
break;
|
|
3015
|
+
}
|
|
3016
|
+
}
|
|
3017
|
+
break;
|
|
3018
|
+
}
|
|
3019
|
+
if (child_indent === -1)
|
|
3020
|
+
return null;
|
|
3021
|
+
search_start = parent_idx + 1;
|
|
3022
|
+
for (let i = parent_idx + 1;i < search_end; i++) {
|
|
3023
|
+
if (lines[i].trim() === "")
|
|
3024
|
+
continue;
|
|
3025
|
+
const leading_spaces = lines[i].match(/^(\s*)/);
|
|
3026
|
+
if (leading_spaces && leading_spaces[1].length < child_indent) {
|
|
3027
|
+
search_end = i;
|
|
3028
|
+
break;
|
|
3029
|
+
}
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3032
|
+
const final_prop = segments[segments.length - 1];
|
|
3033
|
+
for (let i = search_start;i < search_end; i++) {
|
|
3034
|
+
const match = lines[i].match(new RegExp(`^(\\s*${escape_regex(final_prop)}:\\s*).+$`));
|
|
3035
|
+
if (match) {
|
|
3036
|
+
lines[i] = match[1] + value;
|
|
3037
|
+
return lines.join(`
|
|
3038
|
+
`);
|
|
3039
|
+
}
|
|
3040
|
+
}
|
|
3041
|
+
return null;
|
|
3042
|
+
}
|
|
3043
|
+
}
|
|
3044
|
+
|
|
3045
|
+
// src/editor/yaml-fields.ts
|
|
3046
|
+
var PRIMITIVE_DEFAULTS = {
|
|
3047
|
+
int: "0",
|
|
3048
|
+
float: "0",
|
|
3049
|
+
double: "0",
|
|
3050
|
+
bool: "0",
|
|
3051
|
+
string: "",
|
|
3052
|
+
byte: "0",
|
|
3053
|
+
sbyte: "0",
|
|
3054
|
+
short: "0",
|
|
3055
|
+
ushort: "0",
|
|
3056
|
+
uint: "0",
|
|
3057
|
+
long: "0",
|
|
3058
|
+
ulong: "0",
|
|
3059
|
+
char: "0",
|
|
3060
|
+
Int32: "0",
|
|
3061
|
+
Single: "0",
|
|
3062
|
+
Double: "0",
|
|
3063
|
+
Boolean: "0",
|
|
3064
|
+
String: "",
|
|
3065
|
+
Byte: "0",
|
|
3066
|
+
SByte: "0",
|
|
3067
|
+
Int16: "0",
|
|
3068
|
+
UInt16: "0",
|
|
3069
|
+
UInt32: "0",
|
|
3070
|
+
Int64: "0",
|
|
3071
|
+
UInt64: "0",
|
|
3072
|
+
Char: "0"
|
|
3073
|
+
};
|
|
3074
|
+
var STRUCT_DEFAULTS = {
|
|
3075
|
+
Vector2: "{x: 0, y: 0}",
|
|
3076
|
+
Vector3: "{x: 0, y: 0, z: 0}",
|
|
3077
|
+
Vector4: "{x: 0, y: 0, z: 0, w: 0}",
|
|
3078
|
+
Vector2Int: "{x: 0, y: 0}",
|
|
3079
|
+
Vector3Int: "{x: 0, y: 0, z: 0}",
|
|
3080
|
+
Quaternion: "{x: 0, y: 0, z: 0, w: 1}",
|
|
3081
|
+
Color: "{r: 0, g: 0, b: 0, a: 0}",
|
|
3082
|
+
Color32: "{r: 0, g: 0, b: 0, a: 0}",
|
|
3083
|
+
Rect: `serializedVersion: 2
|
|
3084
|
+
x: 0
|
|
3085
|
+
y: 0
|
|
3086
|
+
width: 0
|
|
3087
|
+
height: 0`,
|
|
3088
|
+
RectInt: "{x: 0, y: 0, width: 0, height: 0}",
|
|
3089
|
+
RectOffset: "{m_Left: 0, m_Right: 0, m_Top: 0, m_Bottom: 0}",
|
|
3090
|
+
Matrix4x4: "{e00: 1, e01: 0, e02: 0, e03: 0, e10: 0, e11: 1, e12: 0, e13: 0, e20: 0, e21: 0, e22: 1, e23: 0, e30: 0, e31: 0, e32: 0, e33: 1}",
|
|
3091
|
+
LayerMask: `serializedVersion: 2
|
|
3092
|
+
m_Bits: 0`
|
|
3093
|
+
};
|
|
3094
|
+
var VERSION_GATED_STRUCT_DEFAULTS = {
|
|
3095
|
+
Hash128: { value: `serializedVersion: 2
|
|
3096
|
+
Hash: 00000000000000000000000000000000`, min_major: 2021, min_minor: 1 },
|
|
3097
|
+
RenderingLayerMask: { value: `serializedVersion: 2
|
|
3098
|
+
m_Bits: 0`, min_major: 6000, min_minor: 0 }
|
|
3099
|
+
};
|
|
3100
|
+
var BLOCK_STRUCT_DEFAULTS = {
|
|
3101
|
+
Bounds: `m_Center: {x: 0, y: 0, z: 0}
|
|
3102
|
+
m_Extent: {x: 0, y: 0, z: 0}`,
|
|
3103
|
+
BoundsInt: `m_Position: {x: 0, y: 0, z: 0}
|
|
3104
|
+
m_Size: {x: 0, y: 0, z: 0}`
|
|
3105
|
+
};
|
|
3106
|
+
var OBJECT_REF_TYPES = new Set([
|
|
3107
|
+
"GameObject",
|
|
3108
|
+
"Transform",
|
|
3109
|
+
"RectTransform",
|
|
3110
|
+
"Material",
|
|
3111
|
+
"Texture",
|
|
3112
|
+
"Texture2D",
|
|
3113
|
+
"Texture3D",
|
|
3114
|
+
"RenderTexture",
|
|
3115
|
+
"Sprite",
|
|
3116
|
+
"AudioClip",
|
|
3117
|
+
"VideoClip",
|
|
3118
|
+
"Mesh",
|
|
3119
|
+
"Shader",
|
|
3120
|
+
"ComputeShader",
|
|
3121
|
+
"AnimationClip",
|
|
3122
|
+
"AnimatorController",
|
|
3123
|
+
"RuntimeAnimatorController",
|
|
3124
|
+
"PhysicMaterial",
|
|
3125
|
+
"PhysicsMaterial",
|
|
3126
|
+
"PhysicsMaterial2D",
|
|
3127
|
+
"Font",
|
|
3128
|
+
"TMP_FontAsset",
|
|
3129
|
+
"Object",
|
|
3130
|
+
"Component",
|
|
3131
|
+
"Behaviour",
|
|
3132
|
+
"MonoBehaviour",
|
|
3133
|
+
"ScriptableObject",
|
|
3134
|
+
"Rigidbody",
|
|
3135
|
+
"Rigidbody2D",
|
|
3136
|
+
"Collider",
|
|
3137
|
+
"Collider2D",
|
|
3138
|
+
"Camera",
|
|
3139
|
+
"Light",
|
|
3140
|
+
"Canvas",
|
|
3141
|
+
"CanvasGroup",
|
|
3142
|
+
"EventSystem",
|
|
3143
|
+
"AudioSource",
|
|
3144
|
+
"ParticleSystem",
|
|
3145
|
+
"TextAsset",
|
|
3146
|
+
"TerrainData"
|
|
3147
|
+
]);
|
|
3148
|
+
function version_at_least(version, min_major, min_minor) {
|
|
3149
|
+
if (!version)
|
|
3150
|
+
return false;
|
|
3151
|
+
if (version.major > min_major)
|
|
3152
|
+
return true;
|
|
3153
|
+
if (version.major === min_major)
|
|
3154
|
+
return version.minor >= min_minor;
|
|
3155
|
+
return false;
|
|
3156
|
+
}
|
|
3157
|
+
function yaml_default_for_type(csharp_type, version) {
|
|
3158
|
+
if (csharp_type.endsWith("?")) {
|
|
3159
|
+
return null;
|
|
3160
|
+
}
|
|
3161
|
+
if (csharp_type in PRIMITIVE_DEFAULTS) {
|
|
3162
|
+
return PRIMITIVE_DEFAULTS[csharp_type];
|
|
3163
|
+
}
|
|
3164
|
+
if (csharp_type in STRUCT_DEFAULTS) {
|
|
3165
|
+
return STRUCT_DEFAULTS[csharp_type];
|
|
3166
|
+
}
|
|
3167
|
+
if (csharp_type in VERSION_GATED_STRUCT_DEFAULTS) {
|
|
3168
|
+
const gated = VERSION_GATED_STRUCT_DEFAULTS[csharp_type];
|
|
3169
|
+
if (version_at_least(version, gated.min_major, gated.min_minor)) {
|
|
3170
|
+
return gated.value;
|
|
3171
|
+
}
|
|
3172
|
+
return null;
|
|
3173
|
+
}
|
|
3174
|
+
if (csharp_type in BLOCK_STRUCT_DEFAULTS) {
|
|
3175
|
+
return BLOCK_STRUCT_DEFAULTS[csharp_type];
|
|
3176
|
+
}
|
|
3177
|
+
if (csharp_type.endsWith("[]")) {
|
|
3178
|
+
return "[]";
|
|
3179
|
+
}
|
|
3180
|
+
if (csharp_type.startsWith("List<") && csharp_type.endsWith(">")) {
|
|
3181
|
+
return "[]";
|
|
3182
|
+
}
|
|
3183
|
+
if (OBJECT_REF_TYPES.has(csharp_type)) {
|
|
3184
|
+
return "{fileID: 0}";
|
|
3185
|
+
}
|
|
3186
|
+
return "{fileID: 0}";
|
|
3187
|
+
}
|
|
3188
|
+
function generate_field_yaml(fields, version, indent = " ", type_lookup) {
|
|
3189
|
+
const lines = [];
|
|
3190
|
+
for (const field of fields) {
|
|
3191
|
+
if (field.hasSerializeReference) {
|
|
3192
|
+
const t = field.typeName;
|
|
3193
|
+
if (t.endsWith("[]") || t.startsWith("List<") && t.endsWith(">")) {
|
|
3194
|
+
lines.push(`${indent}${field.name}: []`);
|
|
3195
|
+
} else {
|
|
3196
|
+
lines.push(`${indent}${field.name}:`);
|
|
3197
|
+
lines.push(`${indent} rid: 0`);
|
|
3198
|
+
}
|
|
3199
|
+
continue;
|
|
3200
|
+
}
|
|
3201
|
+
const default_value = yaml_default_for_type(field.typeName, version);
|
|
3202
|
+
if (default_value === null) {
|
|
3203
|
+
continue;
|
|
3204
|
+
}
|
|
3205
|
+
if (default_value === "{fileID: 0}" && type_lookup) {
|
|
3206
|
+
const struct_fields = type_lookup(field.typeName);
|
|
3207
|
+
if (struct_fields && struct_fields.length > 0) {
|
|
3208
|
+
lines.push(`${indent}${field.name}:`);
|
|
3209
|
+
const nested = generate_field_yaml(struct_fields, version, indent + " ", type_lookup);
|
|
3210
|
+
const nested_lines = nested.slice(1).replace(/\n$/, "").split(`
|
|
2845
3211
|
`);
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
for (let seg = 0;seg < segments.length - 1; seg++) {
|
|
2849
|
-
const segment = segments[seg];
|
|
2850
|
-
let parent_idx = -1;
|
|
2851
|
-
let parent_indent = -1;
|
|
2852
|
-
for (let i = search_start;i < search_end; i++) {
|
|
2853
|
-
const match = lines[i].match(new RegExp(`^(\\s*)${escape_regex(segment)}:\\s*(.*)$`));
|
|
2854
|
-
if (match) {
|
|
2855
|
-
const trailing = match[2].trim();
|
|
2856
|
-
if (trailing === "") {
|
|
2857
|
-
parent_idx = i;
|
|
2858
|
-
parent_indent = match[1].length;
|
|
2859
|
-
break;
|
|
2860
|
-
}
|
|
2861
|
-
for (let j = i + 1;j < search_end; j++) {
|
|
2862
|
-
if (lines[j].trim() === "")
|
|
2863
|
-
continue;
|
|
2864
|
-
const nextLeading = lines[j].match(/^(\s*)/);
|
|
2865
|
-
if (nextLeading && nextLeading[1].length > match[1].length) {
|
|
2866
|
-
parent_idx = i;
|
|
2867
|
-
parent_indent = match[1].length;
|
|
2868
|
-
}
|
|
2869
|
-
break;
|
|
2870
|
-
}
|
|
2871
|
-
if (parent_idx !== -1)
|
|
2872
|
-
break;
|
|
3212
|
+
for (const nl of nested_lines) {
|
|
3213
|
+
lines.push(nl);
|
|
2873
3214
|
}
|
|
3215
|
+
continue;
|
|
2874
3216
|
}
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
if (leading_spaces) {
|
|
2883
|
-
const indent = leading_spaces[1].length;
|
|
2884
|
-
if (indent > parent_indent) {
|
|
2885
|
-
child_indent = indent;
|
|
2886
|
-
break;
|
|
2887
|
-
}
|
|
2888
|
-
}
|
|
2889
|
-
break;
|
|
3217
|
+
}
|
|
3218
|
+
if (default_value.includes(`
|
|
3219
|
+
`)) {
|
|
3220
|
+
lines.push(`${indent}${field.name}:`);
|
|
3221
|
+
for (const sub_line of default_value.split(`
|
|
3222
|
+
`)) {
|
|
3223
|
+
lines.push(`${indent}${sub_line}`);
|
|
2890
3224
|
}
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
3225
|
+
} else {
|
|
3226
|
+
lines.push(`${indent}${field.name}: ${default_value}`);
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3229
|
+
return lines.length > 0 ? `
|
|
3230
|
+
` + lines.join(`
|
|
3231
|
+
`) + `
|
|
3232
|
+
` : `
|
|
3233
|
+
`;
|
|
3234
|
+
}
|
|
3235
|
+
function json_value_to_yaml_lines(value, indent = " ") {
|
|
3236
|
+
if (value === null || value === undefined) {
|
|
3237
|
+
return [""];
|
|
3238
|
+
}
|
|
3239
|
+
if (typeof value === "string") {
|
|
3240
|
+
return [yaml_quote_if_needed(value)];
|
|
3241
|
+
}
|
|
3242
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
3243
|
+
return [String(value)];
|
|
3244
|
+
}
|
|
3245
|
+
if (Array.isArray(value)) {
|
|
3246
|
+
if (value.length === 0)
|
|
3247
|
+
return ["[]"];
|
|
3248
|
+
const lines = [];
|
|
3249
|
+
for (const item of value) {
|
|
3250
|
+
if (is_scalar(item) || is_empty_collection(item)) {
|
|
3251
|
+
const scalar = json_value_to_yaml_lines(item);
|
|
3252
|
+
lines.push(`${indent}- ${scalar[0]}`);
|
|
3253
|
+
} else if (is_flow_mappable(item)) {
|
|
3254
|
+
lines.push(`${indent}- ${to_flow_mapping(item)}`);
|
|
3255
|
+
} else {
|
|
3256
|
+
const child_lines = json_value_to_yaml_lines(item, indent + " ");
|
|
3257
|
+
lines.push(`${indent}- ${child_lines[0].trimStart()}`);
|
|
3258
|
+
for (let i = 1;i < child_lines.length; i++) {
|
|
3259
|
+
lines.push(child_lines[i]);
|
|
2901
3260
|
}
|
|
2902
3261
|
}
|
|
2903
3262
|
}
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
3263
|
+
return lines;
|
|
3264
|
+
}
|
|
3265
|
+
if (typeof value === "object") {
|
|
3266
|
+
const entries = Object.entries(value);
|
|
3267
|
+
if (entries.length === 0)
|
|
3268
|
+
return ["{}"];
|
|
3269
|
+
const lines = [];
|
|
3270
|
+
for (const [key, val] of entries) {
|
|
3271
|
+
if (is_scalar(val) || is_empty_collection(val)) {
|
|
3272
|
+
const scalar = json_value_to_yaml_lines(val);
|
|
3273
|
+
lines.push(`${indent}${key}: ${scalar[0]}`);
|
|
3274
|
+
} else if (is_flow_mappable(val)) {
|
|
3275
|
+
lines.push(`${indent}${key}: ${to_flow_mapping(val)}`);
|
|
3276
|
+
} else {
|
|
3277
|
+
const child_indent = Array.isArray(val) ? indent : indent + " ";
|
|
3278
|
+
lines.push(`${indent}${key}:`);
|
|
3279
|
+
const child_lines = json_value_to_yaml_lines(val, child_indent);
|
|
3280
|
+
for (const cl of child_lines) {
|
|
3281
|
+
lines.push(cl);
|
|
3282
|
+
}
|
|
2911
3283
|
}
|
|
2912
3284
|
}
|
|
2913
|
-
return
|
|
3285
|
+
return lines;
|
|
2914
3286
|
}
|
|
3287
|
+
return [String(value)];
|
|
3288
|
+
}
|
|
3289
|
+
function is_scalar(value) {
|
|
3290
|
+
return value === null || value === undefined || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
3291
|
+
}
|
|
3292
|
+
function is_empty_collection(value) {
|
|
3293
|
+
if (Array.isArray(value))
|
|
3294
|
+
return value.length === 0;
|
|
3295
|
+
if (typeof value === "object" && value !== null)
|
|
3296
|
+
return Object.keys(value).length === 0;
|
|
3297
|
+
return false;
|
|
3298
|
+
}
|
|
3299
|
+
function is_flow_mappable(value) {
|
|
3300
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
3301
|
+
return false;
|
|
3302
|
+
const entries = Object.entries(value);
|
|
3303
|
+
if (entries.length === 0)
|
|
3304
|
+
return false;
|
|
3305
|
+
return entries.every(([, v]) => is_scalar(v) || is_empty_collection(v));
|
|
3306
|
+
}
|
|
3307
|
+
function to_flow_mapping(obj) {
|
|
3308
|
+
const parts = Object.entries(obj).map(([k, v]) => {
|
|
3309
|
+
if (v === null || v === undefined)
|
|
3310
|
+
return `${k}: `;
|
|
3311
|
+
if (typeof v === "string")
|
|
3312
|
+
return `${k}: ${yaml_quote_if_needed(v)}`;
|
|
3313
|
+
if (Array.isArray(v) && v.length === 0)
|
|
3314
|
+
return `${k}: []`;
|
|
3315
|
+
if (typeof v === "object" && v !== null && Object.keys(v).length === 0)
|
|
3316
|
+
return `${k}: {}`;
|
|
3317
|
+
return `${k}: ${String(v)}`;
|
|
3318
|
+
});
|
|
3319
|
+
return `{${parts.join(", ")}}`;
|
|
2915
3320
|
}
|
|
2916
3321
|
|
|
2917
3322
|
// src/editor/unity-document.ts
|
|
3323
|
+
var import_fs9 = require("fs");
|
|
2918
3324
|
class UnityDocument {
|
|
2919
3325
|
file_path;
|
|
2920
3326
|
_header;
|
|
@@ -3531,6 +3937,20 @@ function read_project_version(projectPath) {
|
|
|
3531
3937
|
}
|
|
3532
3938
|
|
|
3533
3939
|
// src/editor/create.ts
|
|
3940
|
+
function compute_dll_script_file_id(namespace, class_name) {
|
|
3941
|
+
const { createHash } = require("crypto");
|
|
3942
|
+
const full_name = namespace ? `${namespace}.${class_name}` : class_name;
|
|
3943
|
+
const name_bytes = Buffer.from(full_name, "utf-8");
|
|
3944
|
+
const input = Buffer.alloc(4 + name_bytes.length);
|
|
3945
|
+
input.writeInt32LE(114, 0);
|
|
3946
|
+
name_bytes.copy(input, 4);
|
|
3947
|
+
const hash = createHash("md4").update(input).digest();
|
|
3948
|
+
const a = hash.readInt32LE(0);
|
|
3949
|
+
const b = hash.readInt32LE(4);
|
|
3950
|
+
const c = hash.readInt32LE(8);
|
|
3951
|
+
const d = hash.readInt32LE(12);
|
|
3952
|
+
return a ^ b ^ c ^ d;
|
|
3953
|
+
}
|
|
3534
3954
|
function get_layer_from_parent(doc, parentTransformId) {
|
|
3535
3955
|
if (parentTransformId === "0")
|
|
3536
3956
|
return 0;
|
|
@@ -3546,7 +3966,7 @@ function get_layer_from_parent(doc, parentTransformId) {
|
|
|
3546
3966
|
const layerMatch = parentGo.raw.match(/m_Layer:\s*(\d+)/);
|
|
3547
3967
|
return layerMatch ? parseInt(layerMatch[1], 10) : 0;
|
|
3548
3968
|
}
|
|
3549
|
-
function createGameObjectYAML(gameObjectId, transformId, name, parentTransformId = 0, rootOrder = 0, layer = 0) {
|
|
3969
|
+
function createGameObjectYAML(gameObjectId, transformId, name, parentTransformId = "0", rootOrder = 0, layer = 0) {
|
|
3550
3970
|
return `--- !u!1 &${gameObjectId}
|
|
3551
3971
|
GameObject:
|
|
3552
3972
|
m_ObjectHideFlags: 0
|
|
@@ -3607,9 +4027,9 @@ function findStrippedRootTransform(doc, prefabInstanceId) {
|
|
|
3607
4027
|
for (const block of doc.blocks) {
|
|
3608
4028
|
if (block.class_id !== 4 || !block.is_stripped)
|
|
3609
4029
|
continue;
|
|
3610
|
-
const piMatch = block.raw.match(/m_PrefabInstance
|
|
4030
|
+
const piMatch = block.raw.match(/m_PrefabInstance:[ \t]*\{fileID:[ \t]*(-?\d+)\}/);
|
|
3611
4031
|
if (piMatch && piMatch[1] === prefabInstanceId) {
|
|
3612
|
-
const sourceMatch = block.raw.match(/m_CorrespondingSourceObject
|
|
4032
|
+
const sourceMatch = block.raw.match(/m_CorrespondingSourceObject:[ \t]*(\{[^}]+\})/);
|
|
3613
4033
|
if (sourceMatch) {
|
|
3614
4034
|
return {
|
|
3615
4035
|
transformId: block.file_id,
|
|
@@ -3620,6 +4040,66 @@ function findStrippedRootTransform(doc, prefabInstanceId) {
|
|
|
3620
4040
|
}
|
|
3621
4041
|
return null;
|
|
3622
4042
|
}
|
|
4043
|
+
function find_game_object_in_variant(doc, name, file_path, project_path) {
|
|
4044
|
+
const pi_blocks = doc.find_by_class_id(1001);
|
|
4045
|
+
for (const pi_block of pi_blocks) {
|
|
4046
|
+
const mod_pattern = /- target:[ \t]*(\{[^}]+\})\s*propertyPath:[ \t]*m_Name\s*value:[ \t]*([^\n]*)/g;
|
|
4047
|
+
let mod_match;
|
|
4048
|
+
while ((mod_match = mod_pattern.exec(pi_block.raw)) !== null) {
|
|
4049
|
+
const target_ref = mod_match[1];
|
|
4050
|
+
const mod_value = mod_match[2].trim();
|
|
4051
|
+
if (mod_value !== name)
|
|
4052
|
+
continue;
|
|
4053
|
+
for (const block of doc.blocks) {
|
|
4054
|
+
if (block.class_id !== 1 || !block.is_stripped)
|
|
4055
|
+
continue;
|
|
4056
|
+
const source_match = block.raw.match(/m_CorrespondingSourceObject:[ \t]*(\{[^}]+\})/);
|
|
4057
|
+
if (!source_match)
|
|
4058
|
+
continue;
|
|
4059
|
+
const normalized_source = source_match[1].replace(/\s+/g, " ");
|
|
4060
|
+
const normalized_target = target_ref.replace(/\s+/g, " ");
|
|
4061
|
+
if (normalized_source === normalized_target) {
|
|
4062
|
+
return {
|
|
4063
|
+
stripped_go_id: block.file_id,
|
|
4064
|
+
source_ref: target_ref,
|
|
4065
|
+
prefab_instance_id: pi_block.file_id
|
|
4066
|
+
};
|
|
4067
|
+
}
|
|
4068
|
+
}
|
|
4069
|
+
}
|
|
4070
|
+
}
|
|
4071
|
+
const source_info = resolve_source_prefab(doc, file_path, project_path);
|
|
4072
|
+
if (!source_info)
|
|
4073
|
+
return null;
|
|
4074
|
+
let source_doc;
|
|
4075
|
+
try {
|
|
4076
|
+
source_doc = UnityDocument.from_file(source_info.source_path);
|
|
4077
|
+
} catch {
|
|
4078
|
+
return null;
|
|
4079
|
+
}
|
|
4080
|
+
const source_gos = source_doc.find_game_objects_by_name(name);
|
|
4081
|
+
if (source_gos.length !== 1)
|
|
4082
|
+
return null;
|
|
4083
|
+
const source_go = source_gos[0];
|
|
4084
|
+
const source_go_file_id = source_go.file_id;
|
|
4085
|
+
const source_guid = source_info.source_guid;
|
|
4086
|
+
for (const block of doc.blocks) {
|
|
4087
|
+
if (block.class_id !== 1 || !block.is_stripped)
|
|
4088
|
+
continue;
|
|
4089
|
+
const source_match = block.raw.match(/m_CorrespondingSourceObject:[ \t]*\{[^}]*fileID:[ \t]*(-?\d+)[^}]*guid:[ \t]*([a-f0-9]{32})/);
|
|
4090
|
+
if (!source_match)
|
|
4091
|
+
continue;
|
|
4092
|
+
if (source_match[1] === source_go_file_id && source_match[2] === source_guid) {
|
|
4093
|
+
const source_ref = `{fileID: ${source_go_file_id}, guid: ${source_guid}, type: 3}`;
|
|
4094
|
+
return {
|
|
4095
|
+
stripped_go_id: block.file_id,
|
|
4096
|
+
source_ref,
|
|
4097
|
+
prefab_instance_id: source_info.prefab_instance_id
|
|
4098
|
+
};
|
|
4099
|
+
}
|
|
4100
|
+
}
|
|
4101
|
+
return null;
|
|
4102
|
+
}
|
|
3623
4103
|
function appendToAddedGameObjects(doc, piId, targetSourceRef, newGoId) {
|
|
3624
4104
|
const piBlock = doc.find_by_file_id(piId);
|
|
3625
4105
|
if (!piBlock)
|
|
@@ -3629,13 +4109,34 @@ function appendToAddedGameObjects(doc, piId, targetSourceRef, newGoId) {
|
|
|
3629
4109
|
insertIndex: -1
|
|
3630
4110
|
addedObject: {fileID: ${newGoId}}`;
|
|
3631
4111
|
let raw = piBlock.raw;
|
|
3632
|
-
const emptyPattern = /m_AddedGameObjects
|
|
4112
|
+
const emptyPattern = /m_AddedGameObjects:[ \t]*\[\]/;
|
|
3633
4113
|
if (emptyPattern.test(raw)) {
|
|
3634
4114
|
raw = raw.replace(emptyPattern, `m_AddedGameObjects:${entry}`);
|
|
3635
4115
|
piBlock.replace_raw(raw);
|
|
3636
4116
|
return;
|
|
3637
4117
|
}
|
|
3638
|
-
const existingPattern = /(m_AddedGameObjects
|
|
4118
|
+
const existingPattern = /(m_AddedGameObjects:[ \t]*\n(?:[ \t]+-[\s\S]*?(?=\n[ \t]+m_|$))*)/;
|
|
4119
|
+
if (existingPattern.test(raw)) {
|
|
4120
|
+
raw = raw.replace(existingPattern, `$1${entry}`);
|
|
4121
|
+
piBlock.replace_raw(raw);
|
|
4122
|
+
}
|
|
4123
|
+
}
|
|
4124
|
+
function appendToAddedComponents(doc, piId, targetSourceRef, newComponentId) {
|
|
4125
|
+
const piBlock = doc.find_by_file_id(piId);
|
|
4126
|
+
if (!piBlock)
|
|
4127
|
+
return;
|
|
4128
|
+
const entry = `
|
|
4129
|
+
- targetCorrespondingSourceObject: ${targetSourceRef}
|
|
4130
|
+
insertIndex: -1
|
|
4131
|
+
addedObject: {fileID: ${newComponentId}}`;
|
|
4132
|
+
let raw = piBlock.raw;
|
|
4133
|
+
const emptyPattern = /m_AddedComponents:[ \t]*\[\]/;
|
|
4134
|
+
if (emptyPattern.test(raw)) {
|
|
4135
|
+
raw = raw.replace(emptyPattern, `m_AddedComponents:${entry}`);
|
|
4136
|
+
piBlock.replace_raw(raw);
|
|
4137
|
+
return;
|
|
4138
|
+
}
|
|
4139
|
+
const existingPattern = /(m_AddedComponents:[ \t]*\n(?:[ \t]+-[\s\S]*?(?=\n[ \t]+m_|$))*)/;
|
|
3639
4140
|
if (existingPattern.test(raw)) {
|
|
3640
4141
|
raw = raw.replace(existingPattern, `$1${entry}`);
|
|
3641
4142
|
piBlock.replace_raw(raw);
|
|
@@ -3658,11 +4159,31 @@ var COMPONENT_DEFAULTS = {
|
|
|
3658
4159
|
m_Materials:
|
|
3659
4160
|
- {fileID: 0}`,
|
|
3660
4161
|
33: ` m_Mesh: {fileID: 0}`,
|
|
4162
|
+
50: ` m_BodyType: 0
|
|
4163
|
+
m_Mass: 1
|
|
4164
|
+
m_LinearDrag: 0
|
|
4165
|
+
m_AngularDrag: 0.05
|
|
4166
|
+
m_GravityScale: 1
|
|
4167
|
+
m_Interpolate: 0
|
|
4168
|
+
m_SleepingMode: 1
|
|
4169
|
+
m_CollisionDetection: 0`,
|
|
3661
4170
|
54: ` m_Mass: 1
|
|
3662
4171
|
m_Drag: 0
|
|
3663
4172
|
m_AngularDrag: 0.05
|
|
3664
4173
|
m_UseGravity: 1
|
|
3665
4174
|
m_IsKinematic: 0`,
|
|
4175
|
+
58: ` m_IsTrigger: 0
|
|
4176
|
+
m_Material: {fileID: 0}
|
|
4177
|
+
m_Offset: {x: 0, y: 0}
|
|
4178
|
+
m_Radius: 0.5`,
|
|
4179
|
+
60: ` m_IsTrigger: 0
|
|
4180
|
+
m_Material: {fileID: 0}
|
|
4181
|
+
m_Offset: {x: 0, y: 0}
|
|
4182
|
+
m_Points: []`,
|
|
4183
|
+
61: ` m_IsTrigger: 0
|
|
4184
|
+
m_Material: {fileID: 0}
|
|
4185
|
+
m_Offset: {x: 0, y: 0}
|
|
4186
|
+
m_Size: {x: 1, y: 1}`,
|
|
3666
4187
|
64: ` m_IsTrigger: 0
|
|
3667
4188
|
m_Convex: 0
|
|
3668
4189
|
m_CookingOptions: 30
|
|
@@ -3671,6 +4192,19 @@ var COMPONENT_DEFAULTS = {
|
|
|
3671
4192
|
m_Material: {fileID: 0}
|
|
3672
4193
|
m_Center: {x: 0, y: 0, z: 0}
|
|
3673
4194
|
m_Size: {x: 1, y: 1, z: 1}`,
|
|
4195
|
+
66: ` m_IsTrigger: 0
|
|
4196
|
+
m_Material: {fileID: 0}
|
|
4197
|
+
m_Offset: {x: 0, y: 0}
|
|
4198
|
+
m_GeometryType: 0`,
|
|
4199
|
+
68: ` m_IsTrigger: 0
|
|
4200
|
+
m_Material: {fileID: 0}
|
|
4201
|
+
m_Offset: {x: 0, y: 0}
|
|
4202
|
+
m_Points: []`,
|
|
4203
|
+
70: ` m_IsTrigger: 0
|
|
4204
|
+
m_Material: {fileID: 0}
|
|
4205
|
+
m_Offset: {x: 0, y: 0}
|
|
4206
|
+
m_Size: {x: 1, y: 1}
|
|
4207
|
+
m_Direction: 0`,
|
|
3674
4208
|
82: ` m_PlayOnAwake: 1
|
|
3675
4209
|
m_Volume: 1
|
|
3676
4210
|
m_Pitch: 1
|
|
@@ -3756,9 +4290,14 @@ function addComponentToGameObject(doc, gameObjectId, componentId) {
|
|
|
3756
4290
|
`);
|
|
3757
4291
|
goBlock.replace_raw(raw);
|
|
3758
4292
|
}
|
|
3759
|
-
function createMonoBehaviourYAML(componentId, gameObjectId, scriptGuid, fields, version) {
|
|
3760
|
-
const field_yaml = fields && fields.length > 0 ? generate_field_yaml(fields, version) : `
|
|
4293
|
+
function createMonoBehaviourYAML(componentId, gameObjectId, scriptGuid, fields, version, scriptFileId = 11500000, type_lookup) {
|
|
4294
|
+
const field_yaml = fields && fields.length > 0 ? generate_field_yaml(fields, version, " ", type_lookup) : `
|
|
3761
4295
|
`;
|
|
4296
|
+
const has_serialize_ref = fields?.some((f) => f.hasSerializeReference) ?? false;
|
|
4297
|
+
const references_section = has_serialize_ref ? ` references:
|
|
4298
|
+
version: 2
|
|
4299
|
+
RefIds: []
|
|
4300
|
+
` : "";
|
|
3762
4301
|
return `--- !u!114 &${componentId}
|
|
3763
4302
|
MonoBehaviour:
|
|
3764
4303
|
m_ObjectHideFlags: 0
|
|
@@ -3768,9 +4307,9 @@ MonoBehaviour:
|
|
|
3768
4307
|
m_GameObject: {fileID: ${gameObjectId}}
|
|
3769
4308
|
m_Enabled: 1
|
|
3770
4309
|
m_EditorHideFlags: 0
|
|
3771
|
-
m_Script: {fileID:
|
|
4310
|
+
m_Script: {fileID: ${scriptFileId}, guid: ${scriptGuid}, type: 3}
|
|
3772
4311
|
m_Name:
|
|
3773
|
-
m_EditorClassIdentifier:${field_yaml}`;
|
|
4312
|
+
m_EditorClassIdentifier:${field_yaml}${references_section}`;
|
|
3774
4313
|
}
|
|
3775
4314
|
function createGameObject(options) {
|
|
3776
4315
|
const { file_path, name, parent } = options;
|
|
@@ -3869,9 +4408,9 @@ function createGameObject(options) {
|
|
|
3869
4408
|
const layer = get_layer_from_parent(doc, parentTransformIdStr);
|
|
3870
4409
|
const gameObjectIdStr = doc.generate_file_id();
|
|
3871
4410
|
const transformIdStr = doc.generate_file_id();
|
|
3872
|
-
const gameObjectId =
|
|
3873
|
-
const transformId =
|
|
3874
|
-
const parentTransformId =
|
|
4411
|
+
const gameObjectId = gameObjectIdStr;
|
|
4412
|
+
const transformId = transformIdStr;
|
|
4413
|
+
const parentTransformId = parentTransformIdStr;
|
|
3875
4414
|
const newBlocks = createGameObjectYAML(gameObjectId, transformId, name.trim(), parentTransformId, rootOrder, layer);
|
|
3876
4415
|
doc.append_raw(newBlocks);
|
|
3877
4416
|
if (parentTransformIdStr !== "0" && !variantPiId) {
|
|
@@ -3893,7 +4432,7 @@ function createGameObject(options) {
|
|
|
3893
4432
|
file_path,
|
|
3894
4433
|
game_object_id: gameObjectId,
|
|
3895
4434
|
transform_id: transformId,
|
|
3896
|
-
prefab_instance_id: variantPiId
|
|
4435
|
+
prefab_instance_id: variantPiId || undefined
|
|
3897
4436
|
};
|
|
3898
4437
|
}
|
|
3899
4438
|
function createScene(options) {
|
|
@@ -4339,9 +4878,9 @@ function createPrefabVariant(options) {
|
|
|
4339
4878
|
const tempDoc = UnityDocument.from_string(`%YAML 1.1
|
|
4340
4879
|
%TAG !u! tag:unity3d.com,2011:
|
|
4341
4880
|
`);
|
|
4342
|
-
const prefabInstanceId =
|
|
4343
|
-
const strippedGoId =
|
|
4344
|
-
const strippedTransformId =
|
|
4881
|
+
const prefabInstanceId = tempDoc.generate_file_id();
|
|
4882
|
+
const strippedGoId = tempDoc.generate_file_id();
|
|
4883
|
+
const strippedTransformId = tempDoc.generate_file_id();
|
|
4345
4884
|
const finalName = variant_name || `${rootInfo.name} Variant`;
|
|
4346
4885
|
const variantYaml = `%YAML 1.1
|
|
4347
4886
|
%TAG !u! tag:unity3d.com,2011:
|
|
@@ -4455,9 +4994,10 @@ function createScriptableObject(options) {
|
|
|
4455
4994
|
} catch {}
|
|
4456
4995
|
}
|
|
4457
4996
|
const baseName = path5.basename(output_path, ".asset");
|
|
4458
|
-
const
|
|
4997
|
+
const type_lookup = project_path ? build_type_lookup(project_path) : undefined;
|
|
4998
|
+
const field_yaml = resolved.fields && resolved.fields.length > 0 ? generate_field_yaml(resolved.fields, version, " ", type_lookup) : `
|
|
4459
4999
|
`;
|
|
4460
|
-
|
|
5000
|
+
let assetYaml = `%YAML 1.1
|
|
4461
5001
|
%TAG !u! tag:unity3d.com,2011:
|
|
4462
5002
|
--- !u!114 &11400000
|
|
4463
5003
|
MonoBehaviour:
|
|
@@ -4471,6 +5011,66 @@ MonoBehaviour:
|
|
|
4471
5011
|
m_Script: {fileID: 11500000, guid: ${resolved.guid}, type: 3}
|
|
4472
5012
|
m_Name: ${baseName}
|
|
4473
5013
|
m_EditorClassIdentifier:${field_yaml}`;
|
|
5014
|
+
if (options.initial_values && Object.keys(options.initial_values).length > 0) {
|
|
5015
|
+
const doc = UnityDocument.from_string(assetYaml);
|
|
5016
|
+
const block = doc.blocks[0];
|
|
5017
|
+
if (block) {
|
|
5018
|
+
const complex_entries = [];
|
|
5019
|
+
for (const [key, val] of Object.entries(options.initial_values)) {
|
|
5020
|
+
if (val === null || val === undefined || typeof val === "string" || typeof val === "number" || typeof val === "boolean") {
|
|
5021
|
+
block.set_property(key, String(val ?? ""));
|
|
5022
|
+
} else if (Array.isArray(val) && val.length === 0) {
|
|
5023
|
+
block.set_property(key, "[]");
|
|
5024
|
+
} else if (typeof val === "object" && val !== null && !Array.isArray(val) && Object.keys(val).length === 0) {
|
|
5025
|
+
block.set_property(key, "{}");
|
|
5026
|
+
} else {
|
|
5027
|
+
complex_entries.push([key, val]);
|
|
5028
|
+
}
|
|
5029
|
+
}
|
|
5030
|
+
if (complex_entries.length > 0) {
|
|
5031
|
+
let raw = block.raw;
|
|
5032
|
+
for (const [key, val] of complex_entries) {
|
|
5033
|
+
const yaml_lines = json_value_to_yaml_lines(val, " ");
|
|
5034
|
+
const key_pattern = new RegExp(`^([ \\t]*${key}:)[^\\n]*$`, "m");
|
|
5035
|
+
const key_match = raw.match(key_pattern);
|
|
5036
|
+
if (key_match && key_match.index !== undefined) {
|
|
5037
|
+
const key_indent = key_match[0].match(/^[ \t]*/)?.[0].length ?? 0;
|
|
5038
|
+
const after_key = key_match.index + key_match[0].length;
|
|
5039
|
+
let end = after_key;
|
|
5040
|
+
const remaining = raw.slice(after_key);
|
|
5041
|
+
const remaining_lines = remaining.split(`
|
|
5042
|
+
`);
|
|
5043
|
+
for (let i = 1;i < remaining_lines.length; i++) {
|
|
5044
|
+
const line = remaining_lines[i];
|
|
5045
|
+
if (line.trim() === "") {
|
|
5046
|
+
end += 1 + line.length;
|
|
5047
|
+
continue;
|
|
5048
|
+
}
|
|
5049
|
+
const line_indent = line.match(/^[ \t]*/)?.[0].length ?? 0;
|
|
5050
|
+
if (line_indent > key_indent) {
|
|
5051
|
+
end += 1 + line.length;
|
|
5052
|
+
} else {
|
|
5053
|
+
break;
|
|
5054
|
+
}
|
|
5055
|
+
}
|
|
5056
|
+
const block_yaml = ` ${key}:
|
|
5057
|
+
${yaml_lines.join(`
|
|
5058
|
+
`)}`;
|
|
5059
|
+
raw = raw.slice(0, key_match.index) + block_yaml + raw.slice(end);
|
|
5060
|
+
} else {
|
|
5061
|
+
const block_yaml = ` ${key}:
|
|
5062
|
+
${yaml_lines.join(`
|
|
5063
|
+
`)}`;
|
|
5064
|
+
raw = raw.trimEnd() + `
|
|
5065
|
+
` + block_yaml + `
|
|
5066
|
+
`;
|
|
5067
|
+
}
|
|
5068
|
+
}
|
|
5069
|
+
block.replace_raw(raw);
|
|
5070
|
+
}
|
|
5071
|
+
assetYaml = doc.serialize();
|
|
5072
|
+
}
|
|
5073
|
+
}
|
|
4474
5074
|
try {
|
|
4475
5075
|
import_fs10.writeFileSync(output_path, assetYaml, "utf-8");
|
|
4476
5076
|
} catch (err) {
|
|
@@ -4551,6 +5151,80 @@ MonoImporter:
|
|
|
4551
5151
|
guid
|
|
4552
5152
|
};
|
|
4553
5153
|
}
|
|
5154
|
+
var COMPONENT_BASE_CLASSES = new Set([
|
|
5155
|
+
"MonoBehaviour",
|
|
5156
|
+
"NetworkBehaviour",
|
|
5157
|
+
"StateMachineBehaviour"
|
|
5158
|
+
]);
|
|
5159
|
+
function is_valid_component_base(base_class, project_path, depth = 0) {
|
|
5160
|
+
if (depth > 5)
|
|
5161
|
+
return false;
|
|
5162
|
+
if (COMPONENT_BASE_CLASSES.has(base_class))
|
|
5163
|
+
return true;
|
|
5164
|
+
if (!project_path)
|
|
5165
|
+
return false;
|
|
5166
|
+
const registryPath = path5.join(project_path, ".unity-agentic", "type-registry.json");
|
|
5167
|
+
if (import_fs10.existsSync(registryPath)) {
|
|
5168
|
+
try {
|
|
5169
|
+
const registry = JSON.parse(import_fs10.readFileSync(registryPath, "utf-8"));
|
|
5170
|
+
const match = registry.find((t) => t.name === base_class && t.kind === "class");
|
|
5171
|
+
if (match?.filePath) {
|
|
5172
|
+
const fullPath = path5.isAbsolute(match.filePath) ? match.filePath : path5.join(project_path, match.filePath);
|
|
5173
|
+
if (fullPath.endsWith(".cs") && import_fs10.existsSync(fullPath)) {
|
|
5174
|
+
const { getNativeExtractSerializedFields: getNativeExtractSerializedFields2 } = (init_scanner(), __toCommonJS(exports_scanner));
|
|
5175
|
+
const extract = getNativeExtractSerializedFields2();
|
|
5176
|
+
if (extract) {
|
|
5177
|
+
const typeInfos = extract(fullPath);
|
|
5178
|
+
const info = typeInfos?.find((t) => t.name === base_class);
|
|
5179
|
+
if (info?.baseClass) {
|
|
5180
|
+
return is_valid_component_base(info.baseClass, project_path, depth + 1);
|
|
5181
|
+
}
|
|
5182
|
+
}
|
|
5183
|
+
}
|
|
5184
|
+
if (!fullPath.endsWith(".cs") || !import_fs10.existsSync(fullPath)) {
|
|
5185
|
+
if (match.kind === "class") {
|
|
5186
|
+
return is_likely_component_base_name(base_class);
|
|
5187
|
+
}
|
|
5188
|
+
}
|
|
5189
|
+
}
|
|
5190
|
+
} catch {}
|
|
5191
|
+
}
|
|
5192
|
+
const cachePaths = [
|
|
5193
|
+
path5.join(project_path, ".unity-agentic", "package-cache.json"),
|
|
5194
|
+
path5.join(project_path, ".unity-agentic", "local-package-cache.json")
|
|
5195
|
+
];
|
|
5196
|
+
for (const cachePath of cachePaths) {
|
|
5197
|
+
if (!import_fs10.existsSync(cachePath))
|
|
5198
|
+
continue;
|
|
5199
|
+
try {
|
|
5200
|
+
const cache = JSON.parse(import_fs10.readFileSync(cachePath, "utf-8"));
|
|
5201
|
+
const baseClassLower = base_class.toLowerCase();
|
|
5202
|
+
for (const [, assetPath] of Object.entries(cache)) {
|
|
5203
|
+
if (!assetPath.endsWith(".cs"))
|
|
5204
|
+
continue;
|
|
5205
|
+
if (path5.basename(assetPath, ".cs").toLowerCase() !== baseClassLower)
|
|
5206
|
+
continue;
|
|
5207
|
+
const fullPath = path5.join(project_path, assetPath);
|
|
5208
|
+
if (!import_fs10.existsSync(fullPath))
|
|
5209
|
+
continue;
|
|
5210
|
+
const { getNativeExtractSerializedFields: getNativeExtractSerializedFields2 } = (init_scanner(), __toCommonJS(exports_scanner));
|
|
5211
|
+
const extract = getNativeExtractSerializedFields2();
|
|
5212
|
+
if (!extract)
|
|
5213
|
+
continue;
|
|
5214
|
+
const typeInfos = extract(fullPath);
|
|
5215
|
+
const info = typeInfos?.find((t) => t.name === base_class);
|
|
5216
|
+
if (info?.baseClass) {
|
|
5217
|
+
return is_valid_component_base(info.baseClass, project_path, depth + 1);
|
|
5218
|
+
}
|
|
5219
|
+
}
|
|
5220
|
+
} catch {}
|
|
5221
|
+
}
|
|
5222
|
+
return false;
|
|
5223
|
+
}
|
|
5224
|
+
function is_likely_component_base_name(name) {
|
|
5225
|
+
const lower = name.toLowerCase();
|
|
5226
|
+
return lower.endsWith("behaviour") || lower.endsWith("behavior") || lower.includes("monobehaviour") || lower.includes("networkbehaviour");
|
|
5227
|
+
}
|
|
4554
5228
|
function addComponent(options) {
|
|
4555
5229
|
const { file_path, game_object_name, component_type } = options;
|
|
4556
5230
|
const project_path = options.project_path || find_unity_project_root(path5.dirname(file_path)) || undefined;
|
|
@@ -4576,11 +5250,19 @@ function addComponent(options) {
|
|
|
4576
5250
|
};
|
|
4577
5251
|
}
|
|
4578
5252
|
const goResult = doc.require_unique_game_object(game_object_name);
|
|
5253
|
+
let gameObjectIdStr;
|
|
5254
|
+
let variantInfo = null;
|
|
4579
5255
|
if ("error" in goResult) {
|
|
4580
|
-
|
|
5256
|
+
const vResult = find_game_object_in_variant(doc, game_object_name, file_path, project_path);
|
|
5257
|
+
if (!vResult) {
|
|
5258
|
+
return { success: false, file_path, error: goResult.error };
|
|
5259
|
+
}
|
|
5260
|
+
gameObjectIdStr = vResult.stripped_go_id;
|
|
5261
|
+
variantInfo = { source_ref: vResult.source_ref, prefab_instance_id: vResult.prefab_instance_id };
|
|
5262
|
+
} else {
|
|
5263
|
+
gameObjectIdStr = goResult.file_id;
|
|
4581
5264
|
}
|
|
4582
|
-
const
|
|
4583
|
-
const gameObjectId = parseInt(gameObjectIdStr, 10);
|
|
5265
|
+
const gameObjectId = gameObjectIdStr;
|
|
4584
5266
|
const classId = get_class_id(component_type);
|
|
4585
5267
|
let duplicateWarning;
|
|
4586
5268
|
const goBlock = doc.find_by_file_id(gameObjectIdStr);
|
|
@@ -4595,7 +5277,7 @@ function addComponent(options) {
|
|
|
4595
5277
|
}
|
|
4596
5278
|
}
|
|
4597
5279
|
const componentIdStr = doc.generate_file_id();
|
|
4598
|
-
const componentId =
|
|
5280
|
+
const componentId = componentIdStr;
|
|
4599
5281
|
let componentYAML;
|
|
4600
5282
|
let scriptGuid;
|
|
4601
5283
|
let scriptPath;
|
|
@@ -4604,7 +5286,16 @@ function addComponent(options) {
|
|
|
4604
5286
|
const componentName = UNITY_CLASS_IDS[classId] || component_type;
|
|
4605
5287
|
componentYAML = createGenericComponentYAML(componentName, classId, componentId, gameObjectId);
|
|
4606
5288
|
} else {
|
|
4607
|
-
|
|
5289
|
+
let resolved;
|
|
5290
|
+
try {
|
|
5291
|
+
resolved = resolve_script_with_fields(component_type, project_path);
|
|
5292
|
+
} catch (e) {
|
|
5293
|
+
return {
|
|
5294
|
+
success: false,
|
|
5295
|
+
file_path,
|
|
5296
|
+
error: e instanceof Error ? e.message : String(e)
|
|
5297
|
+
};
|
|
5298
|
+
}
|
|
4608
5299
|
if (!resolved) {
|
|
4609
5300
|
const hints = [];
|
|
4610
5301
|
if (project_path) {
|
|
@@ -4631,11 +5322,11 @@ function addComponent(options) {
|
|
|
4631
5322
|
error: `"${component_type}" is ${resolved.kind === "enum" ? "an enum" : "an interface"}, not a MonoBehaviour. Cannot add as a component.`
|
|
4632
5323
|
};
|
|
4633
5324
|
}
|
|
4634
|
-
if (resolved.base_class && !
|
|
5325
|
+
if (resolved.base_class && !COMPONENT_BASE_CLASSES.has(resolved.base_class) && !is_valid_component_base(resolved.base_class, project_path)) {
|
|
4635
5326
|
return {
|
|
4636
5327
|
success: false,
|
|
4637
5328
|
file_path,
|
|
4638
|
-
error: `"${component_type}" extends ${resolved.base_class}, not MonoBehaviour. Cannot add as a component.`
|
|
5329
|
+
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).`
|
|
4639
5330
|
};
|
|
4640
5331
|
}
|
|
4641
5332
|
let version;
|
|
@@ -4644,12 +5335,21 @@ function addComponent(options) {
|
|
|
4644
5335
|
version = read_project_version(project_path);
|
|
4645
5336
|
} catch {}
|
|
4646
5337
|
}
|
|
4647
|
-
|
|
5338
|
+
let scriptFileId = 11500000;
|
|
5339
|
+
if (resolved.path?.endsWith(".dll") && resolved.class_name) {
|
|
5340
|
+
scriptFileId = compute_dll_script_file_id(resolved.namespace ?? "", resolved.class_name);
|
|
5341
|
+
}
|
|
5342
|
+
const type_lookup_comp = project_path ? build_type_lookup(project_path) : undefined;
|
|
5343
|
+
componentYAML = createMonoBehaviourYAML(componentId, gameObjectId, resolved.guid, resolved.fields, version, scriptFileId, type_lookup_comp);
|
|
4648
5344
|
scriptGuid = resolved.guid;
|
|
4649
5345
|
scriptPath = resolved.path || undefined;
|
|
4650
5346
|
extractionError = resolved.extraction_error;
|
|
4651
5347
|
}
|
|
4652
|
-
|
|
5348
|
+
if (variantInfo) {
|
|
5349
|
+
appendToAddedComponents(doc, variantInfo.prefab_instance_id, variantInfo.source_ref, componentIdStr);
|
|
5350
|
+
} else {
|
|
5351
|
+
addComponentToGameObject(doc, gameObjectIdStr, componentIdStr);
|
|
5352
|
+
}
|
|
4653
5353
|
doc.append_raw(componentYAML);
|
|
4654
5354
|
const saveResult = doc.save();
|
|
4655
5355
|
if (!saveResult.success) {
|
|
@@ -4726,6 +5426,14 @@ function copyComponent(options) {
|
|
|
4726
5426
|
}
|
|
4727
5427
|
// src/editor/update.ts
|
|
4728
5428
|
var import_fs11 = require("fs");
|
|
5429
|
+
function enrich_target_ref(targetRef, blockRaw) {
|
|
5430
|
+
if (/guid:/.test(targetRef))
|
|
5431
|
+
return targetRef;
|
|
5432
|
+
const sourceMatch = blockRaw.match(/m_SourcePrefab:[ \t]*\{[^}]*guid:[ \t]*([a-f0-9]{32})/);
|
|
5433
|
+
if (!sourceMatch)
|
|
5434
|
+
return null;
|
|
5435
|
+
return targetRef.replace(/\}$/, `, guid: ${sourceMatch[1]}, type: 3}`);
|
|
5436
|
+
}
|
|
4729
5437
|
function eulerToQuaternion(euler) {
|
|
4730
5438
|
const deg2rad = Math.PI / 180;
|
|
4731
5439
|
const x = euler.x * deg2rad;
|
|
@@ -4748,6 +5456,9 @@ function validate_value_type(current_value, new_value) {
|
|
|
4748
5456
|
const current = current_value.trim();
|
|
4749
5457
|
const incoming = new_value.trim();
|
|
4750
5458
|
if (/^\{fileID:/.test(current)) {
|
|
5459
|
+
if (/^\{fileID:[ \t]*0[ \t]*\}$/.test(current)) {
|
|
5460
|
+
return null;
|
|
5461
|
+
}
|
|
4751
5462
|
if (!/^\{fileID:/.test(incoming)) {
|
|
4752
5463
|
return `Expected a reference value ({fileID: ...}), got "${incoming}"`;
|
|
4753
5464
|
}
|
|
@@ -4932,10 +5643,10 @@ function safeUnityYAMLEdit(filePath, objectName, propertyName, newValue, project
|
|
|
4932
5643
|
const propertyPattern = new RegExp(`(^\\s*m_${normalizedProperty}:\\s*)([^\\n]*)`, "m");
|
|
4933
5644
|
let updatedRaw = targetBlock.raw;
|
|
4934
5645
|
if (propertyPattern.test(updatedRaw)) {
|
|
4935
|
-
updatedRaw = updatedRaw.replace(propertyPattern,
|
|
5646
|
+
updatedRaw = updatedRaw.replace(propertyPattern, (_m, prefix) => prefix + newValue);
|
|
4936
5647
|
} else {
|
|
4937
|
-
updatedRaw = updatedRaw.replace(/(\n)(--- !u!|$)/, `
|
|
4938
|
-
m_${normalizedProperty}: ${newValue}$
|
|
5648
|
+
updatedRaw = updatedRaw.replace(/(\n)(--- !u!|$)/, (_m, g1, g2) => `
|
|
5649
|
+
m_${normalizedProperty}: ${newValue}${g1}${g2}`);
|
|
4939
5650
|
}
|
|
4940
5651
|
targetBlock.replace_raw(updatedRaw);
|
|
4941
5652
|
const saveResult = doc.save();
|
|
@@ -5021,7 +5732,9 @@ function editComponentByFileId(options) {
|
|
|
5021
5732
|
};
|
|
5022
5733
|
}
|
|
5023
5734
|
}
|
|
5024
|
-
const
|
|
5735
|
+
const exactValue = targetBlock.get_property(exactProperty);
|
|
5736
|
+
const resolvedProperty = exactValue !== null ? exactProperty : exactProperty !== prefixedProperty && targetBlock.get_property(prefixedProperty) !== null ? prefixedProperty : null;
|
|
5737
|
+
const currentValue = exactValue ?? (resolvedProperty === prefixedProperty ? targetBlock.get_property(prefixedProperty) : null);
|
|
5025
5738
|
if (currentValue !== null) {
|
|
5026
5739
|
const typeError = validate_value_type(currentValue, new_value);
|
|
5027
5740
|
if (typeError) {
|
|
@@ -5032,9 +5745,14 @@ function editComponentByFileId(options) {
|
|
|
5032
5745
|
};
|
|
5033
5746
|
}
|
|
5034
5747
|
}
|
|
5035
|
-
let modified
|
|
5036
|
-
if (
|
|
5037
|
-
modified = targetBlock.set_property(
|
|
5748
|
+
let modified;
|
|
5749
|
+
if (resolvedProperty) {
|
|
5750
|
+
modified = targetBlock.set_property(resolvedProperty, new_value, "{fileID: 0}");
|
|
5751
|
+
} else {
|
|
5752
|
+
modified = targetBlock.set_property(exactProperty, new_value, "{fileID: 0}");
|
|
5753
|
+
if (!modified && exactProperty !== prefixedProperty) {
|
|
5754
|
+
modified = targetBlock.set_property(prefixedProperty, new_value, "{fileID: 0}");
|
|
5755
|
+
}
|
|
5038
5756
|
}
|
|
5039
5757
|
if (!modified) {
|
|
5040
5758
|
if (currentValue !== null) {
|
|
@@ -5071,8 +5789,10 @@ function editComponentByFileId(options) {
|
|
|
5071
5789
|
};
|
|
5072
5790
|
}
|
|
5073
5791
|
function editPrefabOverride(options) {
|
|
5074
|
-
const { file_path, prefab_instance,
|
|
5075
|
-
const
|
|
5792
|
+
const { file_path, prefab_instance, new_value, object_reference, target, managed_reference } = options;
|
|
5793
|
+
const property_path = /[\[\]]/.test(options.property_path) && !options.property_path.startsWith("'") ? `'${options.property_path}'` : options.property_path;
|
|
5794
|
+
const effectiveValue = managed_reference ?? new_value;
|
|
5795
|
+
const objRef = managed_reference ? "{fileID: 0}" : object_reference ?? "{fileID: 0}";
|
|
5076
5796
|
if (!import_fs11.existsSync(file_path)) {
|
|
5077
5797
|
return { success: false, file_path, error: `File not found: ${file_path}` };
|
|
5078
5798
|
}
|
|
@@ -5086,11 +5806,16 @@ function editPrefabOverride(options) {
|
|
|
5086
5806
|
if (!targetBlock) {
|
|
5087
5807
|
return { success: false, file_path, error: `PrefabInstance "${prefab_instance}" not found` };
|
|
5088
5808
|
}
|
|
5089
|
-
const
|
|
5090
|
-
const
|
|
5809
|
+
const unquotedPath = property_path.replace(/^'|'$/g, "");
|
|
5810
|
+
const quotedPath = `'${unquotedPath}'`;
|
|
5811
|
+
const escapedUnquoted = unquotedPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
5812
|
+
const escapedQuoted = quotedPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
5813
|
+
const pathAlternation = escapedUnquoted === escapedQuoted ? escapedUnquoted : `(?:${escapedQuoted}|${escapedUnquoted})`;
|
|
5814
|
+
const entryPattern = new RegExp(`(- target:\\s*\\{[^}]+\\}\\s*\\n\\s*propertyPath:\\s*)${pathAlternation}(\\s*\\n\\s*value:\\s*)(.*)(\\s*\\n\\s*objectReference:\\s*)(.*)`, "m");
|
|
5091
5815
|
const entryMatch = targetBlock.raw.match(entryPattern);
|
|
5092
5816
|
if (entryMatch) {
|
|
5093
|
-
const
|
|
5817
|
+
const quotedValue = yaml_quote_if_needed(effectiveValue);
|
|
5818
|
+
const updatedText2 = targetBlock.raw.replace(entryPattern, (_m, g1, g2, _g3, g4) => g1 + property_path + g2 + quotedValue + g4 + objRef);
|
|
5094
5819
|
targetBlock.replace_raw(updatedText2);
|
|
5095
5820
|
const saveResult2 = doc.save();
|
|
5096
5821
|
if (!saveResult2.success) {
|
|
@@ -5127,9 +5852,13 @@ function editPrefabOverride(options) {
|
|
|
5127
5852
|
error: `Invalid target reference "${targetRef}". Expected format: {fileID: N, guid: ..., type: T}`
|
|
5128
5853
|
};
|
|
5129
5854
|
}
|
|
5855
|
+
const enriched = enrich_target_ref(targetRef, targetBlock.raw);
|
|
5856
|
+
if (enriched)
|
|
5857
|
+
targetRef = enriched;
|
|
5858
|
+
const quotedNewValue = yaml_quote_if_needed(effectiveValue);
|
|
5130
5859
|
const newEntry = ` - target: ${targetRef}
|
|
5131
5860
|
propertyPath: ${property_path}
|
|
5132
|
-
value: ${
|
|
5861
|
+
value: ${quotedNewValue}
|
|
5133
5862
|
objectReference: ${objRef}`;
|
|
5134
5863
|
const removedPattern = /(\n\s*m_RemovedComponents:)/m;
|
|
5135
5864
|
const removedMatch = targetBlock.raw.match(removedPattern);
|
|
@@ -5272,10 +6001,10 @@ function batchEditProperties(filePath, edits) {
|
|
|
5272
6001
|
const propertyPattern = new RegExp(`(^\\s*m_${normalizedProperty}:\\s*)([^\\n]*)`, "m");
|
|
5273
6002
|
let updatedRaw = targetBlock.raw;
|
|
5274
6003
|
if (propertyPattern.test(updatedRaw)) {
|
|
5275
|
-
updatedRaw = updatedRaw.replace(propertyPattern,
|
|
6004
|
+
updatedRaw = updatedRaw.replace(propertyPattern, (_m, prefix) => prefix + edit.new_value);
|
|
5276
6005
|
} else {
|
|
5277
|
-
updatedRaw = updatedRaw.replace(/(\n)(--- !u!|$)/, `
|
|
5278
|
-
m_${normalizedProperty}: ${edit.new_value}$
|
|
6006
|
+
updatedRaw = updatedRaw.replace(/(\n)(--- !u!|$)/, (_m, g1, g2) => `
|
|
6007
|
+
m_${normalizedProperty}: ${edit.new_value}${g1}${g2}`);
|
|
5279
6008
|
}
|
|
5280
6009
|
targetBlock.replace_raw(updatedRaw);
|
|
5281
6010
|
}
|
|
@@ -5380,9 +6109,9 @@ function reparentGameObject(options) {
|
|
|
5380
6109
|
return {
|
|
5381
6110
|
success: true,
|
|
5382
6111
|
file_path,
|
|
5383
|
-
child_transform_id:
|
|
5384
|
-
old_parent_transform_id:
|
|
5385
|
-
new_parent_transform_id:
|
|
6112
|
+
child_transform_id: childTransformId,
|
|
6113
|
+
old_parent_transform_id: oldParentTransformId,
|
|
6114
|
+
new_parent_transform_id: newParentTransformId
|
|
5386
6115
|
};
|
|
5387
6116
|
}
|
|
5388
6117
|
function findPrefabInstanceBlock(doc, identifier) {
|
|
@@ -5751,9 +6480,9 @@ function removeRemovedGameObject(options) {
|
|
|
5751
6480
|
if (!doc.validate()) {
|
|
5752
6481
|
return { success: false, file_path, error: "Validation failed after removing GameObject" };
|
|
5753
6482
|
}
|
|
5754
|
-
const
|
|
5755
|
-
if (!
|
|
5756
|
-
return { success: false, file_path, error:
|
|
6483
|
+
const restoreGoSaveResult = doc.save();
|
|
6484
|
+
if (!restoreGoSaveResult.success) {
|
|
6485
|
+
return { success: false, file_path, error: restoreGoSaveResult.error };
|
|
5757
6486
|
}
|
|
5758
6487
|
return {
|
|
5759
6488
|
success: true,
|
|
@@ -5793,7 +6522,8 @@ function removeComponent(options) {
|
|
|
5793
6522
|
const parentGoId = goMatch[1];
|
|
5794
6523
|
const goBlock = doc.find_by_file_id(parentGoId);
|
|
5795
6524
|
if (goBlock) {
|
|
5796
|
-
const
|
|
6525
|
+
const escaped = file_id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6526
|
+
const compLinePattern = new RegExp(`^[ \\t]*- component: \\{fileID: ${escaped}\\}[ \\t]*\\n`, "m");
|
|
5797
6527
|
const modifiedRaw = goBlock.raw.replace(compLinePattern, "");
|
|
5798
6528
|
goBlock.replace_raw(modifiedRaw);
|
|
5799
6529
|
}
|