unity-agentic-tools 0.2.0

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/index.js ADDED
@@ -0,0 +1,2499 @@
1
+ // @bun @bun-cjs
2
+ (function(exports, require, module, __filename, __dirname) {var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __toESM = (mod, isNodeMode, target) => {
9
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
10
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
11
+ for (let key of __getOwnPropNames(mod))
12
+ if (!__hasOwnProp.call(to, key))
13
+ __defProp(to, key, {
14
+ get: () => mod[key],
15
+ enumerable: true
16
+ });
17
+ return to;
18
+ };
19
+ var __moduleCache = /* @__PURE__ */ new WeakMap;
20
+ var __toCommonJS = (from) => {
21
+ var entry = __moduleCache.get(from), desc;
22
+ if (entry)
23
+ return entry;
24
+ entry = __defProp({}, "__esModule", { value: true });
25
+ if (from && typeof from === "object" || typeof from === "function")
26
+ __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
27
+ get: () => from[key],
28
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
29
+ }));
30
+ __moduleCache.set(from, entry);
31
+ return entry;
32
+ };
33
+ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
34
+ var __export = (target, all) => {
35
+ for (var name in all)
36
+ __defProp(target, name, {
37
+ get: all[name],
38
+ enumerable: true,
39
+ configurable: true,
40
+ set: (newValue) => all[name] = () => newValue
41
+ });
42
+ };
43
+
44
+ // package.json
45
+ var require_package = __commonJS((exports2, module2) => {
46
+ module2.exports = {
47
+ name: "unity-agentic-tools",
48
+ packageManager: "bun@latest",
49
+ version: "0.2.0",
50
+ description: "Fast, token-efficient Unity YAML parser for AI agents",
51
+ exports: {
52
+ ".": {
53
+ import: "./dist/index.js",
54
+ types: "./dist/index.d.ts"
55
+ },
56
+ "./cli": "./dist/cli.js",
57
+ "./scanner": "./dist/scanner.js"
58
+ },
59
+ files: [
60
+ "dist",
61
+ "native",
62
+ "README.md",
63
+ "LICENSE"
64
+ ],
65
+ scripts: {
66
+ build: "bun run build:lib && bun run build:cli && cp ../doc-indexer/dist/cli.js dist/doc-indexer-cli.js",
67
+ "build:lib": "bun build src/index.ts --outdir=dist --target=bun --format=cjs --external unity-file-tools",
68
+ "build:cli": "bun build src/cli.ts --outdir=dist --target=bun --format=cjs --external unity-file-tools",
69
+ "build:rust": "cd ../rust-core && bun run build",
70
+ "build:all": "bun run build:rust || echo 'Rust build skipped' && bun run build",
71
+ dev: "bun build src/index.ts --watch",
72
+ clean: "rm -rf dist",
73
+ rebuild: "bun run clean && bun run build",
74
+ test: "bun test",
75
+ "test:watch": "bun test --watch",
76
+ "test:coverage": "bun test --coverage"
77
+ },
78
+ dependencies: {
79
+ commander: "^14.0.2"
80
+ },
81
+ devDependencies: {
82
+ "@types/node": "^25.0.0",
83
+ "@vitest/ui": "^4.0.16",
84
+ typescript: "^5.3.0",
85
+ "unity-file-tools": "workspace:*",
86
+ vitest: "^4.0.16"
87
+ },
88
+ type: "commonjs",
89
+ bin: {
90
+ "unity-agentic-tools": "./dist/cli.js"
91
+ },
92
+ engines: {
93
+ bun: ">=1.0.0"
94
+ },
95
+ repository: {
96
+ type: "git",
97
+ url: "https://github.com/taconotsandwich/unity-agentic-tools"
98
+ },
99
+ keywords: [
100
+ "unity",
101
+ "yaml",
102
+ "parser",
103
+ "scene",
104
+ "prefab",
105
+ "gameobject",
106
+ "ai",
107
+ "cli"
108
+ ],
109
+ license: "Apache-2.0"
110
+ };
111
+ });
112
+
113
+ // src/index.ts
114
+ var exports_src = {};
115
+ __export(exports_src, {
116
+ walk_project_files: () => walk_project_files,
117
+ setup: () => setup,
118
+ search_project: () => search_project,
119
+ read_settings: () => read_settings,
120
+ isNativeModuleAvailable: () => isNativeModuleAvailable,
121
+ grep_project: () => grep_project,
122
+ getNativeModuleError: () => getNativeModuleError,
123
+ generateGuid: () => generateGuid,
124
+ edit_tag: () => edit_tag,
125
+ edit_sorting_layer: () => edit_sorting_layer,
126
+ edit_settings: () => edit_settings,
127
+ edit_layer: () => edit_layer,
128
+ createScene: () => createScene,
129
+ cleanup: () => cleanup,
130
+ atomicWrite: () => atomicWrite,
131
+ UnityScanner: () => UnityScanner
132
+ });
133
+ module.exports = __toCommonJS(exports_src);
134
+
135
+ // src/scanner.ts
136
+ var import_module = require("module");
137
+ var import_fs = require("fs");
138
+ var import_path = require("path");
139
+ var __dirname = "/home/runner/work/unity-agentic-tools/unity-agentic-tools/unity-agentic-tools/src";
140
+ var RustScanner = null;
141
+ var nativeModuleError = null;
142
+ var nativeWalkProjectFiles = null;
143
+ var nativeGrepProject = null;
144
+ var nativeBuildGuidCache = null;
145
+ try {
146
+ const scriptDir = process.argv[1] ? import_path.dirname(import_path.resolve(process.argv[1])) : __dirname;
147
+ let rustModule;
148
+ const nativeLoaderPath = import_path.join(scriptDir, "..", "native", "index.js");
149
+ if (import_fs.existsSync(nativeLoaderPath)) {
150
+ const nativeRequire = import_module.createRequire(nativeLoaderPath);
151
+ rustModule = nativeRequire(nativeLoaderPath);
152
+ } else {
153
+ const wsRequire = import_module.createRequire(import_path.join(scriptDir, "_"));
154
+ rustModule = wsRequire("unity-file-tools");
155
+ }
156
+ RustScanner = rustModule.Scanner;
157
+ nativeWalkProjectFiles = rustModule.walkProjectFiles || null;
158
+ nativeGrepProject = rustModule.grepProject || null;
159
+ nativeBuildGuidCache = rustModule.buildGuidCache || null;
160
+ } catch (err) {
161
+ nativeModuleError = `Failed to load native Rust module.
162
+ ` + `Run: bun install (in the project root)
163
+ ` + `Original error: ${err.message}`;
164
+ }
165
+ function isNativeModuleAvailable() {
166
+ return RustScanner !== null;
167
+ }
168
+ function getNativeModuleError() {
169
+ return nativeModuleError;
170
+ }
171
+
172
+ class UnityScanner {
173
+ scanner;
174
+ constructor() {
175
+ if (!RustScanner) {
176
+ throw new Error(nativeModuleError || "Native module not available");
177
+ }
178
+ this.scanner = new RustScanner;
179
+ }
180
+ setProjectRoot(path) {
181
+ this.scanner.setProjectRoot(path);
182
+ }
183
+ scan_scene_minimal(file) {
184
+ return this.scanner.scanSceneMinimal(file);
185
+ }
186
+ scan_scene_with_components(file, options) {
187
+ return this.scanner.scanSceneWithComponents(file, options);
188
+ }
189
+ find_by_name(file, pattern, fuzzy = true) {
190
+ return this.scanner.findByName(file, pattern, fuzzy);
191
+ }
192
+ inspect(options) {
193
+ return this.scanner.inspect({
194
+ file: options.file,
195
+ identifier: options.identifier,
196
+ includeProperties: options.include_properties,
197
+ verbose: options.verbose
198
+ });
199
+ }
200
+ inspect_all(file, include_properties = false, verbose = false) {
201
+ return this.scanner.inspectAll(file, include_properties, verbose);
202
+ }
203
+ inspect_all_paginated(options) {
204
+ return this.scanner.inspectAllPaginated({
205
+ file: options.file,
206
+ includeProperties: options.include_properties,
207
+ verbose: options.verbose,
208
+ pageSize: options.page_size,
209
+ cursor: options.cursor,
210
+ maxDepth: options.max_depth,
211
+ filterComponent: options.filter_component
212
+ });
213
+ }
214
+ read_asset(file) {
215
+ return this.scanner.readAsset(file);
216
+ }
217
+ }
218
+ function getNativeWalkProjectFiles() {
219
+ return nativeWalkProjectFiles;
220
+ }
221
+ function getNativeGrepProject() {
222
+ return nativeGrepProject;
223
+ }
224
+ function getNativeBuildGuidCache() {
225
+ return nativeBuildGuidCache;
226
+ }
227
+ // src/setup.ts
228
+ var import_fs2 = require("fs");
229
+ var import_path2 = require("path");
230
+ var VERSION = require_package().version;
231
+ var CONFIG_DIR = ".unity-agentic";
232
+ var CONFIG_FILE = "config.json";
233
+ var GUID_CACHE_FILE = "guid-cache.json";
234
+ var DOC_INDEX_FILE = "doc-index.json";
235
+ function setup(options = {}) {
236
+ const projectPath = import_path2.resolve(options.project || process.cwd());
237
+ const assetsPath = import_path2.join(projectPath, "Assets");
238
+ if (!import_fs2.existsSync(assetsPath)) {
239
+ return {
240
+ success: false,
241
+ project_path: projectPath,
242
+ config_path: "",
243
+ guid_cache_created: false,
244
+ doc_index_created: false,
245
+ error: `Not a Unity project: Assets folder not found at ${assetsPath}`
246
+ };
247
+ }
248
+ const configPath = import_path2.join(projectPath, CONFIG_DIR);
249
+ if (!import_fs2.existsSync(configPath)) {
250
+ import_fs2.mkdirSync(configPath, { recursive: true });
251
+ }
252
+ const config = {
253
+ version: VERSION,
254
+ project_path: projectPath,
255
+ created_at: new Date().toISOString(),
256
+ rust_enabled: isRustAvailable()
257
+ };
258
+ import_fs2.writeFileSync(import_path2.join(configPath, CONFIG_FILE), JSON.stringify(config, null, 2));
259
+ const guidCache = buildGuidCache(projectPath);
260
+ const guidCachePath = import_path2.join(configPath, GUID_CACHE_FILE);
261
+ import_fs2.writeFileSync(guidCachePath, JSON.stringify(guidCache, null, 2));
262
+ let docIndexCreated = false;
263
+ if (options.indexDocs) {
264
+ const docIndex = { chunks: {}, last_updated: Date.now() };
265
+ import_fs2.writeFileSync(import_path2.join(configPath, DOC_INDEX_FILE), JSON.stringify(docIndex, null, 2));
266
+ docIndexCreated = true;
267
+ }
268
+ return {
269
+ success: true,
270
+ project_path: projectPath,
271
+ config_path: configPath,
272
+ guid_cache_created: true,
273
+ doc_index_created: docIndexCreated,
274
+ guid_count: Object.keys(guidCache).length
275
+ };
276
+ }
277
+ function buildGuidCache(projectRoot) {
278
+ const nativeBuild = getNativeBuildGuidCache();
279
+ if (nativeBuild) {
280
+ try {
281
+ return nativeBuild(projectRoot);
282
+ } catch {}
283
+ }
284
+ return buildGuidCacheJs(projectRoot);
285
+ }
286
+ function buildGuidCacheJs(projectRoot) {
287
+ const cache = {};
288
+ const assetsDir = import_path2.join(projectRoot, "Assets");
289
+ if (!import_fs2.existsSync(assetsDir)) {
290
+ return cache;
291
+ }
292
+ scanMetaFiles(assetsDir, projectRoot, cache);
293
+ return cache;
294
+ }
295
+ function scanMetaFiles(dir, projectRoot, cache) {
296
+ try {
297
+ const entries = import_fs2.readdirSync(dir);
298
+ for (const entry of entries) {
299
+ const fullPath = import_path2.join(dir, entry);
300
+ const stat = import_fs2.statSync(fullPath);
301
+ if (stat.isDirectory()) {
302
+ scanMetaFiles(fullPath, projectRoot, cache);
303
+ } else if (entry.endsWith(".meta")) {
304
+ try {
305
+ const content = import_fs2.readFileSync(fullPath, "utf-8");
306
+ const guidMatch = content.match(/^guid:\s*([a-f0-9]{32})/m);
307
+ if (guidMatch) {
308
+ const guid = guidMatch[1];
309
+ const assetPath = fullPath.slice(0, -5);
310
+ const relativePath = import_path2.relative(projectRoot, assetPath);
311
+ cache[guid] = relativePath;
312
+ }
313
+ } catch {}
314
+ }
315
+ }
316
+ } catch {}
317
+ }
318
+ function isRustAvailable() {
319
+ return isNativeModuleAvailable();
320
+ }
321
+ // src/cleanup.ts
322
+ var import_fs3 = require("fs");
323
+ var import_path3 = require("path");
324
+ var CONFIG_DIR2 = ".unity-agentic";
325
+ var CONFIG_FILE2 = "config.json";
326
+ var GUID_CACHE_FILE2 = "guid-cache.json";
327
+ var DOC_INDEX_FILE2 = "doc-index.json";
328
+ function cleanup(options = {}) {
329
+ const projectPath = import_path3.resolve(options.project || process.cwd());
330
+ const configPath = import_path3.join(projectPath, CONFIG_DIR2);
331
+ if (!import_fs3.existsSync(configPath)) {
332
+ return {
333
+ success: true,
334
+ project_path: projectPath,
335
+ files_removed: [],
336
+ directory_removed: false,
337
+ error: `No ${CONFIG_DIR2} directory found`
338
+ };
339
+ }
340
+ const filesRemoved = [];
341
+ let directoryRemoved = false;
342
+ if (options.all) {
343
+ try {
344
+ removeDirectoryRecursive(configPath);
345
+ directoryRemoved = true;
346
+ filesRemoved.push(CONFIG_DIR2);
347
+ } catch (err) {
348
+ return {
349
+ success: false,
350
+ project_path: projectPath,
351
+ files_removed: filesRemoved,
352
+ directory_removed: false,
353
+ error: `Failed to remove directory: ${err}`
354
+ };
355
+ }
356
+ } else {
357
+ const filesToRemove = [GUID_CACHE_FILE2, DOC_INDEX_FILE2];
358
+ for (const file of filesToRemove) {
359
+ const filePath = import_path3.join(configPath, file);
360
+ if (import_fs3.existsSync(filePath)) {
361
+ try {
362
+ import_fs3.unlinkSync(filePath);
363
+ filesRemoved.push(file);
364
+ } catch {}
365
+ }
366
+ }
367
+ const remaining = import_fs3.readdirSync(configPath);
368
+ if (remaining.length === 0 || remaining.length === 1 && remaining[0] === CONFIG_FILE2) {}
369
+ }
370
+ return {
371
+ success: true,
372
+ project_path: projectPath,
373
+ files_removed: filesRemoved,
374
+ directory_removed: directoryRemoved
375
+ };
376
+ }
377
+ function removeDirectoryRecursive(dir) {
378
+ if (!import_fs3.existsSync(dir)) {
379
+ return;
380
+ }
381
+ const entries = import_fs3.readdirSync(dir, { withFileTypes: true });
382
+ for (const entry of entries) {
383
+ const fullPath = import_path3.join(dir, entry.name);
384
+ if (entry.isDirectory()) {
385
+ removeDirectoryRecursive(fullPath);
386
+ } else {
387
+ import_fs3.unlinkSync(fullPath);
388
+ }
389
+ }
390
+ import_fs3.rmdirSync(dir);
391
+ }
392
+ // src/settings.ts
393
+ var import_fs5 = require("fs");
394
+ var path = __toESM(require("path"));
395
+
396
+ // src/utils.ts
397
+ var import_fs4 = require("fs");
398
+ function atomicWrite(filePath, content) {
399
+ const tmpPath = `${filePath}.tmp`;
400
+ try {
401
+ import_fs4.writeFileSync(tmpPath, content, "utf-8");
402
+ if (import_fs4.existsSync(filePath)) {
403
+ import_fs4.renameSync(filePath, `${filePath}.bak`);
404
+ }
405
+ import_fs4.renameSync(tmpPath, filePath);
406
+ try {
407
+ if (import_fs4.existsSync(`${filePath}.bak`)) {
408
+ import_fs4.unlinkSync(`${filePath}.bak`);
409
+ }
410
+ } catch {}
411
+ return {
412
+ success: true,
413
+ file_path: filePath,
414
+ bytes_written: Buffer.byteLength(content, "utf-8")
415
+ };
416
+ } catch (error) {
417
+ if (import_fs4.existsSync(`${filePath}.bak`)) {
418
+ try {
419
+ import_fs4.renameSync(`${filePath}.bak`, filePath);
420
+ } catch (restoreError) {
421
+ console.error("Failed to restore backup:", restoreError);
422
+ }
423
+ }
424
+ return {
425
+ success: false,
426
+ file_path: filePath,
427
+ error: error instanceof Error ? error.message : String(error)
428
+ };
429
+ }
430
+ }
431
+ function glob_match(pattern, text) {
432
+ if (!pattern.includes("*") && !pattern.includes("?")) {
433
+ return pattern.toLowerCase() === text.toLowerCase();
434
+ }
435
+ const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&");
436
+ const regex_str = escaped.replace(/\*/g, ".*").replace(/\?/g, ".");
437
+ return new RegExp(`^${regex_str}$`, "i").test(text);
438
+ }
439
+ function validate_name(name, label) {
440
+ if (name.includes("/")) {
441
+ return `${label} cannot contain forward slashes (/) \u2014 Unity uses them as hierarchy path separators`;
442
+ }
443
+ if (name.includes("\\")) {
444
+ return `${label} cannot contain backslashes (\\)`;
445
+ }
446
+ if (name.includes(`
447
+ `) || name.includes("\r")) {
448
+ return `${label} cannot contain newlines \u2014 they corrupt YAML structure`;
449
+ }
450
+ if (name.includes("\t")) {
451
+ return `${label} cannot contain tab characters \u2014 they break YAML indentation`;
452
+ }
453
+ if (name.includes("\x00")) {
454
+ return `${label} cannot contain null bytes`;
455
+ }
456
+ return null;
457
+ }
458
+ function generateGuid() {
459
+ const hex = "0123456789abcdef";
460
+ let guid = "";
461
+ for (let i = 0;i < 32; i++) {
462
+ guid += hex[Math.floor(Math.random() * 16)];
463
+ }
464
+ return guid;
465
+ }
466
+ function validate_file_path(file_path, operation) {
467
+ if (file_path.startsWith("file://")) {
468
+ return "file:// URIs are not supported. Use file paths directly.";
469
+ }
470
+ const normalized = file_path.replace(/\\/g, "/");
471
+ const isAbsolute = file_path.startsWith("/") || /^[A-Z]:[/\\]/i.test(file_path) || file_path.startsWith("\\\\") || file_path.startsWith("//");
472
+ if (!isAbsolute && (normalized.includes("/../") || normalized.startsWith("../"))) {
473
+ return "Path traversal (..) is not allowed in relative paths for security reasons.";
474
+ }
475
+ if (operation === "write" && !isAbsolute && normalized.startsWith("Packages/")) {
476
+ return "Cannot write to Packages/ directory (read-only in Unity).";
477
+ }
478
+ return null;
479
+ }
480
+
481
+ // src/settings.ts
482
+ function read_setting_file(file_path) {
483
+ return import_fs5.readFileSync(file_path, "utf-8").replace(/\r\n/g, `
484
+ `);
485
+ }
486
+ var SETTING_ALIASES = {
487
+ tags: "TagManager",
488
+ tagmanager: "TagManager",
489
+ physics: "DynamicsManager",
490
+ dynamics: "DynamicsManager",
491
+ dynamicsmanager: "DynamicsManager",
492
+ quality: "QualitySettings",
493
+ qualitysettings: "QualitySettings",
494
+ time: "TimeManager",
495
+ timemanager: "TimeManager",
496
+ input: "InputManager",
497
+ inputmanager: "InputManager",
498
+ audio: "AudioManager",
499
+ audiomanager: "AudioManager",
500
+ editor: "EditorSettings",
501
+ editorsettings: "EditorSettings",
502
+ graphics: "GraphicsSettings",
503
+ graphicssettings: "GraphicsSettings",
504
+ physics2d: "Physics2DSettings",
505
+ physics2dsettings: "Physics2DSettings",
506
+ player: "ProjectSettings",
507
+ project: "ProjectSettings",
508
+ projectsettings: "ProjectSettings",
509
+ navmesh: "NavMeshAreas",
510
+ navmeshareas: "NavMeshAreas"
511
+ };
512
+ function resolve_setting_name(setting) {
513
+ const lower = setting.toLowerCase();
514
+ const resolved = SETTING_ALIASES[lower];
515
+ if (resolved)
516
+ return resolved;
517
+ const canonical = Object.values(SETTING_ALIASES);
518
+ if (canonical.includes(setting))
519
+ return setting;
520
+ return setting;
521
+ }
522
+ function resolve_setting_path(project_path, setting) {
523
+ const canonical = resolve_setting_name(setting);
524
+ return path.join(project_path, "ProjectSettings", `${canonical}.asset`);
525
+ }
526
+ function parse_tag_manager(content) {
527
+ const tags = [];
528
+ const layers = [];
529
+ const sorting_layers = [];
530
+ const tagsMatch = content.match(/tags:\s*\n((?:\s*-\s*.+\n)*)/);
531
+ if (tagsMatch) {
532
+ const tagLines = tagsMatch[1].matchAll(/^\s*-\s*(.+)$/gm);
533
+ for (const m of tagLines) {
534
+ tags.push(m[1].trim());
535
+ }
536
+ }
537
+ const layersMatch = content.match(/layers:\s*\n([\s\S]*?)(?=\s*m_SortingLayers:)/);
538
+ if (layersMatch) {
539
+ const layerLines = layersMatch[1].split(`
540
+ `).filter((l) => l.match(/^\s*-/));
541
+ for (let i = 0;i < layerLines.length; i++) {
542
+ const nameMatch = layerLines[i].match(/^\s*-\s*(.*)$/);
543
+ const name = nameMatch ? nameMatch[1].trim() : "";
544
+ if (name) {
545
+ layers.push({ index: i, name });
546
+ }
547
+ }
548
+ }
549
+ const sortingMatch = content.match(/m_SortingLayers:\s*\n([\s\S]*?)(?=\n[^\s]|\n*$)/);
550
+ if (sortingMatch) {
551
+ const entryPattern = /- name:\s*(.+)\n\s*uniqueID:\s*(\d+)\n\s*locked:\s*(\d+)/g;
552
+ let m;
553
+ while ((m = entryPattern.exec(sortingMatch[1])) !== null) {
554
+ sorting_layers.push({
555
+ name: m[1].trim(),
556
+ unique_id: parseInt(m[2], 10),
557
+ locked: parseInt(m[3], 10)
558
+ });
559
+ }
560
+ }
561
+ return { tags, layers, sorting_layers };
562
+ }
563
+ function parse_dynamics_manager(content) {
564
+ const parse_vector = (str) => {
565
+ const m = str.match(/\{x:\s*([-\d.]+),\s*y:\s*([-\d.]+),\s*z:\s*([-\d.]+)\}/);
566
+ return m ? { x: parseFloat(m[1]), y: parseFloat(m[2]), z: parseFloat(m[3]) } : { x: 0, y: 0, z: 0 };
567
+ };
568
+ const get_float = (key) => {
569
+ const m = content.match(new RegExp(`${key}:\\s*([-\\d.]+)`));
570
+ return m ? parseFloat(m[1]) : 0;
571
+ };
572
+ const get_int = (key) => {
573
+ const m = content.match(new RegExp(`${key}:\\s*(\\d+)`));
574
+ return m ? parseInt(m[1], 10) : 0;
575
+ };
576
+ const gravity_match = content.match(/m_Gravity:\s*(\{[^}]+\})/);
577
+ const gravity = gravity_match ? parse_vector(gravity_match[1]) : { x: 0, y: -9.81, z: 0 };
578
+ return {
579
+ gravity,
580
+ default_contact_offset: get_float("m_DefaultContactOffset"),
581
+ default_solver_iterations: get_int("m_DefaultSolverIterations"),
582
+ default_solver_velocity_iterations: get_int("m_DefaultSolverVelocityIterations"),
583
+ bounce_threshold: get_float("m_BounceThreshold"),
584
+ sleep_threshold: get_float("m_SleepThreshold"),
585
+ queries_hit_triggers: get_int("m_QueriesHitTriggers") === 1,
586
+ auto_simulation: get_int("m_AutoSimulation") === 1
587
+ };
588
+ }
589
+ function parse_quality_settings(content) {
590
+ const current_match = content.match(/m_CurrentQuality:\s*(\d+)/);
591
+ const current_quality = current_match ? parseInt(current_match[1], 10) : 0;
592
+ const quality_levels = [];
593
+ const levels_section = content.match(/m_QualitySettings:\s*\n([\s\S]*?)(?=\n\s*m_PerPlatformDefaultQuality:|\n*$)/);
594
+ if (levels_section) {
595
+ const entries = levels_section[1].split(/\n\s*-\s*serializedVersion:\s*\d+\n/).filter((s) => s.trim());
596
+ for (const entry of entries) {
597
+ const get = (key) => {
598
+ const m = entry.match(new RegExp(`${key}:\\s*(.+)`));
599
+ return m ? m[1].trim() : "";
600
+ };
601
+ const name = get("name");
602
+ if (!name)
603
+ continue;
604
+ quality_levels.push({
605
+ name,
606
+ pixel_light_count: parseInt(get("pixelLightCount") || "0", 10),
607
+ shadows: parseInt(get("shadows") || "0", 10),
608
+ shadow_resolution: parseInt(get("shadowResolution") || "0", 10),
609
+ shadow_distance: parseFloat(get("shadowDistance") || "0"),
610
+ anti_aliasing: parseInt(get("antiAliasing") || "0", 10),
611
+ vsync_count: parseInt(get("vSyncCount") || "0", 10),
612
+ lod_bias: parseFloat(get("lodBias") || "0")
613
+ });
614
+ }
615
+ }
616
+ return { current_quality, quality_levels };
617
+ }
618
+ function parse_time_manager(content) {
619
+ const get_float = (key) => {
620
+ const m = content.match(new RegExp(`${key}:\\s*([-\\d.]+)`));
621
+ return m ? parseFloat(m[1]) : 0;
622
+ };
623
+ return {
624
+ fixed_timestep: get_float("Fixed Timestep"),
625
+ max_timestep: get_float("Maximum Allowed Timestep"),
626
+ time_scale: get_float("m_TimeScale"),
627
+ max_particle_timestep: get_float("Maximum Particle Timestep")
628
+ };
629
+ }
630
+ function parse_generic_asset(content) {
631
+ const result = {};
632
+ const lines = content.split(`
633
+ `);
634
+ for (const line of lines) {
635
+ const match = line.match(/^\s{2}(\w[\w\s]*\w|\w+):\s*(.+)$/);
636
+ if (match) {
637
+ const key = match[1];
638
+ let value = match[2].trim();
639
+ if (/^-?\d+(\.\d+)?$/.test(value)) {
640
+ value = parseFloat(value);
641
+ } else if (value === "0" || value === "1") {
642
+ value = parseInt(value, 10);
643
+ }
644
+ result[key] = value;
645
+ }
646
+ }
647
+ return result;
648
+ }
649
+ function read_settings(options) {
650
+ const { project_path, setting } = options;
651
+ const file_path = resolve_setting_path(project_path, setting);
652
+ if (!import_fs5.existsSync(file_path)) {
653
+ return {
654
+ success: false,
655
+ project_path,
656
+ setting,
657
+ error: `Settings file not found: ${file_path}`
658
+ };
659
+ }
660
+ let content;
661
+ try {
662
+ content = read_setting_file(file_path);
663
+ } catch (err) {
664
+ return {
665
+ success: false,
666
+ project_path,
667
+ setting,
668
+ error: `Failed to read settings file: ${err instanceof Error ? err.message : String(err)}`
669
+ };
670
+ }
671
+ const canonical = resolve_setting_name(setting);
672
+ let data;
673
+ switch (canonical) {
674
+ case "TagManager":
675
+ data = parse_tag_manager(content);
676
+ break;
677
+ case "DynamicsManager":
678
+ data = parse_dynamics_manager(content);
679
+ break;
680
+ case "QualitySettings":
681
+ data = parse_quality_settings(content);
682
+ break;
683
+ case "TimeManager":
684
+ data = parse_time_manager(content);
685
+ break;
686
+ default:
687
+ data = parse_generic_asset(content);
688
+ break;
689
+ }
690
+ return {
691
+ success: true,
692
+ project_path,
693
+ setting: canonical,
694
+ file_path,
695
+ data
696
+ };
697
+ }
698
+ function edit_settings(options) {
699
+ const { project_path, setting, property, value } = options;
700
+ const file_path = resolve_setting_path(project_path, setting);
701
+ if (!import_fs5.existsSync(file_path)) {
702
+ return {
703
+ success: false,
704
+ project_path,
705
+ setting,
706
+ error: `Settings file not found: ${file_path}`
707
+ };
708
+ }
709
+ let content;
710
+ try {
711
+ content = read_setting_file(file_path);
712
+ } catch (err) {
713
+ return {
714
+ success: false,
715
+ project_path,
716
+ setting,
717
+ error: `Failed to read settings file: ${err instanceof Error ? err.message : String(err)}`
718
+ };
719
+ }
720
+ const propPattern = new RegExp(`(^\\s*${property}:\\s*)(.*)$`, "m");
721
+ if (propPattern.test(content)) {
722
+ content = content.replace(propPattern, `$1${value}`);
723
+ } else {
724
+ const prefixedPattern = new RegExp(`(^\\s*m_${property}:\\s*)(.*)$`, "m");
725
+ if (prefixedPattern.test(content)) {
726
+ content = content.replace(prefixedPattern, `$1${value}`);
727
+ } else {
728
+ const pascal = property.replace(/(^|_)([a-z])/g, (_, __, c) => c.toUpperCase());
729
+ const pascalPattern = new RegExp(`(^\\s*m_${pascal}:\\s*)(.*)$`, "m");
730
+ if (pascalPattern.test(content)) {
731
+ content = content.replace(pascalPattern, `$1${value}`);
732
+ } else {
733
+ const spacedName = property.replace(/_/g, " ").replace(/(^| )([a-z])/g, (_, sp, c) => sp + c.toUpperCase());
734
+ const spacedPattern = new RegExp(`(^\\s*${spacedName}:\\s*)(.*)$`, "m");
735
+ if (spacedPattern.test(content)) {
736
+ content = content.replace(spacedPattern, `$1${value}`);
737
+ } else {
738
+ return {
739
+ success: false,
740
+ project_path,
741
+ setting,
742
+ error: `Property "${property}" not found in ${setting}`
743
+ };
744
+ }
745
+ }
746
+ }
747
+ }
748
+ const result = atomicWrite(file_path, content);
749
+ if (!result.success) {
750
+ return {
751
+ success: false,
752
+ project_path,
753
+ setting,
754
+ error: result.error
755
+ };
756
+ }
757
+ return {
758
+ success: true,
759
+ project_path,
760
+ setting: resolve_setting_name(setting),
761
+ file_path,
762
+ bytes_written: result.bytes_written
763
+ };
764
+ }
765
+ function edit_tag(options) {
766
+ const { project_path, action, tag } = options;
767
+ if (!tag || !tag.trim()) {
768
+ return {
769
+ success: false,
770
+ project_path,
771
+ setting: "TagManager",
772
+ error: "Tag name cannot be empty"
773
+ };
774
+ }
775
+ const nameError = validate_name(tag, "Tag name");
776
+ if (nameError) {
777
+ return {
778
+ success: false,
779
+ project_path,
780
+ setting: "TagManager",
781
+ error: nameError
782
+ };
783
+ }
784
+ const file_path = resolve_setting_path(project_path, "TagManager");
785
+ if (!import_fs5.existsSync(file_path)) {
786
+ return {
787
+ success: false,
788
+ project_path,
789
+ setting: "TagManager",
790
+ error: `TagManager not found: ${file_path}`
791
+ };
792
+ }
793
+ let content;
794
+ try {
795
+ content = read_setting_file(file_path);
796
+ } catch (err) {
797
+ return {
798
+ success: false,
799
+ project_path,
800
+ setting: "TagManager",
801
+ error: `Failed to read TagManager: ${err instanceof Error ? err.message : String(err)}`
802
+ };
803
+ }
804
+ if (action === "add") {
805
+ const existing = parse_tag_manager(content);
806
+ if (existing.tags.includes(tag)) {
807
+ return {
808
+ success: false,
809
+ project_path,
810
+ setting: "TagManager",
811
+ error: `Tag "${tag}" already exists`
812
+ };
813
+ }
814
+ content = content.replace(/(tags:\s*\n(?:\s*-\s*.+\n)*)/, `$1 - ${tag}
815
+ `);
816
+ } else {
817
+ const tagPattern = new RegExp(`^\\s*-\\s*${tag.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s*$\\n?`, "m");
818
+ if (!tagPattern.test(content)) {
819
+ return {
820
+ success: false,
821
+ project_path,
822
+ setting: "TagManager",
823
+ error: `Tag "${tag}" not found`
824
+ };
825
+ }
826
+ content = content.replace(tagPattern, "");
827
+ }
828
+ const result = atomicWrite(file_path, content);
829
+ if (!result.success) {
830
+ return {
831
+ success: false,
832
+ project_path,
833
+ setting: "TagManager",
834
+ error: result.error
835
+ };
836
+ }
837
+ return {
838
+ success: true,
839
+ project_path,
840
+ setting: "TagManager",
841
+ file_path,
842
+ bytes_written: result.bytes_written
843
+ };
844
+ }
845
+ function edit_layer(options) {
846
+ const { project_path, index, name } = options;
847
+ const file_path = resolve_setting_path(project_path, "TagManager");
848
+ if (!import_fs5.existsSync(file_path)) {
849
+ return {
850
+ success: false,
851
+ project_path,
852
+ setting: "TagManager",
853
+ error: `TagManager not found: ${file_path}`
854
+ };
855
+ }
856
+ const RESERVED_LAYERS = {
857
+ 0: "Default",
858
+ 1: "TransparentFX",
859
+ 2: "Ignore Raycast",
860
+ 4: "Water",
861
+ 5: "UI"
862
+ };
863
+ if (index < 0 || index > 31) {
864
+ return {
865
+ success: false,
866
+ project_path,
867
+ setting: "TagManager",
868
+ error: `Layer index must be between 0 and 31`
869
+ };
870
+ }
871
+ if (RESERVED_LAYERS[index]) {
872
+ return {
873
+ success: false,
874
+ project_path,
875
+ setting: "TagManager",
876
+ error: `Cannot modify reserved layer "${RESERVED_LAYERS[index]}" at index ${index}`
877
+ };
878
+ }
879
+ const nameError = validate_name(name, "Layer name");
880
+ if (nameError) {
881
+ return {
882
+ success: false,
883
+ project_path,
884
+ setting: "TagManager",
885
+ error: nameError
886
+ };
887
+ }
888
+ let content;
889
+ try {
890
+ content = read_setting_file(file_path);
891
+ } catch (err) {
892
+ return {
893
+ success: false,
894
+ project_path,
895
+ setting: "TagManager",
896
+ error: `Failed to read TagManager: ${err instanceof Error ? err.message : String(err)}`
897
+ };
898
+ }
899
+ const layersMatch = content.match(/(layers:\s*\n)([\s\S]*?)(?=\s*m_SortingLayers:)/);
900
+ if (!layersMatch) {
901
+ return {
902
+ success: false,
903
+ project_path,
904
+ setting: "TagManager",
905
+ error: "Could not find layers section in TagManager"
906
+ };
907
+ }
908
+ const layerLines = layersMatch[2].split(`
909
+ `).filter((l) => l.match(/^\s*-/));
910
+ if (index >= layerLines.length) {
911
+ return {
912
+ success: false,
913
+ project_path,
914
+ setting: "TagManager",
915
+ error: `Layer index ${index} is out of range (file has ${layerLines.length} layers)`
916
+ };
917
+ }
918
+ layerLines[index] = ` - ${name}`;
919
+ const newLayersSection = layerLines.join(`
920
+ `) + `
921
+ `;
922
+ content = content.replace(layersMatch[2], newLayersSection);
923
+ const result = atomicWrite(file_path, content);
924
+ if (!result.success) {
925
+ return {
926
+ success: false,
927
+ project_path,
928
+ setting: "TagManager",
929
+ error: result.error
930
+ };
931
+ }
932
+ return {
933
+ success: true,
934
+ project_path,
935
+ setting: "TagManager",
936
+ file_path,
937
+ bytes_written: result.bytes_written
938
+ };
939
+ }
940
+ function edit_sorting_layer(options) {
941
+ const { project_path, action, name } = options;
942
+ if (!name || !name.trim()) {
943
+ return {
944
+ success: false,
945
+ project_path,
946
+ setting: "TagManager",
947
+ error: "Sorting layer name cannot be empty"
948
+ };
949
+ }
950
+ const file_path = resolve_setting_path(project_path, "TagManager");
951
+ if (!import_fs5.existsSync(file_path)) {
952
+ return {
953
+ success: false,
954
+ project_path,
955
+ setting: "TagManager",
956
+ error: `TagManager not found: ${file_path}`
957
+ };
958
+ }
959
+ let content;
960
+ try {
961
+ content = read_setting_file(file_path);
962
+ } catch (err) {
963
+ return {
964
+ success: false,
965
+ project_path,
966
+ setting: "TagManager",
967
+ error: `Failed to read TagManager: ${err instanceof Error ? err.message : String(err)}`
968
+ };
969
+ }
970
+ if (action === "remove" && name === "Default") {
971
+ return {
972
+ success: false,
973
+ project_path,
974
+ setting: "TagManager",
975
+ error: "Cannot remove the Default sorting layer \u2014 it is required by Unity"
976
+ };
977
+ }
978
+ if (action === "add") {
979
+ const existing = parse_tag_manager(content);
980
+ if (existing.sorting_layers.some((sl) => sl.name === name)) {
981
+ return {
982
+ success: false,
983
+ project_path,
984
+ setting: "TagManager",
985
+ error: `Sorting layer "${name}" already exists`
986
+ };
987
+ }
988
+ const unique_id = Math.floor(Math.random() * 4294967295);
989
+ const newEntry = ` - name: ${name}
990
+ uniqueID: ${unique_id}
991
+ locked: 0
992
+ `;
993
+ const sortingEnd = content.match(/(m_SortingLayers:\s*\n(?:\s+-\s+name:[\s\S]*?(?=\n[^\s]|\n*$)))/);
994
+ if (sortingEnd) {
995
+ content = content.replace(sortingEnd[1], sortingEnd[1] + newEntry);
996
+ } else {
997
+ content = content.trimEnd() + `
998
+ ` + newEntry;
999
+ }
1000
+ } else {
1001
+ const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1002
+ const slPattern = new RegExp(`\\s*-\\s*name:\\s*${escapedName}\\n\\s*uniqueID:\\s*\\d+\\n\\s*locked:\\s*\\d+\\n?`, "m");
1003
+ if (!slPattern.test(content)) {
1004
+ return {
1005
+ success: false,
1006
+ project_path,
1007
+ setting: "TagManager",
1008
+ error: `Sorting layer "${name}" not found`
1009
+ };
1010
+ }
1011
+ content = content.replace(slPattern, `
1012
+ `);
1013
+ }
1014
+ const result = atomicWrite(file_path, content);
1015
+ if (!result.success) {
1016
+ return {
1017
+ success: false,
1018
+ project_path,
1019
+ setting: "TagManager",
1020
+ error: result.error
1021
+ };
1022
+ }
1023
+ return {
1024
+ success: true,
1025
+ project_path,
1026
+ setting: "TagManager",
1027
+ file_path,
1028
+ bytes_written: result.bytes_written
1029
+ };
1030
+ }
1031
+ // src/project-search.ts
1032
+ var import_fs6 = require("fs");
1033
+ var path2 = __toESM(require("path"));
1034
+ var BINARY_EXTENSIONS = new Set([
1035
+ ".png",
1036
+ ".jpg",
1037
+ ".jpeg",
1038
+ ".gif",
1039
+ ".bmp",
1040
+ ".tga",
1041
+ ".psd",
1042
+ ".tif",
1043
+ ".tiff",
1044
+ ".fbx",
1045
+ ".obj",
1046
+ ".dae",
1047
+ ".blend",
1048
+ ".3ds",
1049
+ ".max",
1050
+ ".dll",
1051
+ ".so",
1052
+ ".dylib",
1053
+ ".exe",
1054
+ ".a",
1055
+ ".lib",
1056
+ ".mp3",
1057
+ ".wav",
1058
+ ".ogg",
1059
+ ".aif",
1060
+ ".aiff",
1061
+ ".mp4",
1062
+ ".mov",
1063
+ ".avi",
1064
+ ".wmv",
1065
+ ".zip",
1066
+ ".gz",
1067
+ ".tar",
1068
+ ".rar",
1069
+ ".7z",
1070
+ ".ttf",
1071
+ ".otf",
1072
+ ".woff",
1073
+ ".woff2",
1074
+ ".bank",
1075
+ ".bytes",
1076
+ ".db"
1077
+ ]);
1078
+ var SKIP_DIRS = new Set(["Library", "Temp", "obj", "Logs", ".git", ".unity-agentic", "node_modules"]);
1079
+ function walk_project_files(project_path, extensions, exclude_dirs) {
1080
+ const nativeWalk = getNativeWalkProjectFiles();
1081
+ if (nativeWalk) {
1082
+ try {
1083
+ return nativeWalk(project_path, extensions, exclude_dirs ?? null);
1084
+ } catch {}
1085
+ }
1086
+ return walk_project_files_js(project_path, extensions, exclude_dirs);
1087
+ }
1088
+ function walk_project_files_js(project_path, extensions, exclude_dirs) {
1089
+ const result = [];
1090
+ const skipSet = new Set([...SKIP_DIRS, ...exclude_dirs || []]);
1091
+ const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
1092
+ function walk(dir) {
1093
+ let entries;
1094
+ try {
1095
+ entries = import_fs6.readdirSync(dir);
1096
+ } catch {
1097
+ return;
1098
+ }
1099
+ for (const entry of entries) {
1100
+ const full = path2.join(dir, entry);
1101
+ let stat;
1102
+ try {
1103
+ stat = import_fs6.statSync(full);
1104
+ } catch {
1105
+ continue;
1106
+ }
1107
+ if (stat.isDirectory()) {
1108
+ if (!skipSet.has(entry)) {
1109
+ walk(full);
1110
+ }
1111
+ } else if (stat.isFile()) {
1112
+ const ext = path2.extname(entry).toLowerCase();
1113
+ if (extSet.has(ext)) {
1114
+ result.push(full);
1115
+ }
1116
+ }
1117
+ }
1118
+ }
1119
+ const assetsDir = path2.join(project_path, "Assets");
1120
+ if (import_fs6.existsSync(assetsDir)) {
1121
+ walk(assetsDir);
1122
+ }
1123
+ if (extSet.has(".asset")) {
1124
+ const settingsDir = path2.join(project_path, "ProjectSettings");
1125
+ if (import_fs6.existsSync(settingsDir)) {
1126
+ walk(settingsDir);
1127
+ }
1128
+ }
1129
+ return result;
1130
+ }
1131
+ function search_project(options) {
1132
+ const {
1133
+ project_path,
1134
+ name,
1135
+ exact = false,
1136
+ component,
1137
+ tag,
1138
+ layer,
1139
+ file_type = "all",
1140
+ max_matches
1141
+ } = options;
1142
+ if (max_matches !== undefined && max_matches < 1) {
1143
+ return {
1144
+ success: false,
1145
+ project_path,
1146
+ total_files_scanned: 0,
1147
+ total_matches: 0,
1148
+ cursor: 0,
1149
+ truncated: false,
1150
+ matches: [],
1151
+ error: "--max-matches must be a positive integer (>= 1)"
1152
+ };
1153
+ }
1154
+ if (name !== undefined && name.trim() === "") {
1155
+ return {
1156
+ success: false,
1157
+ project_path,
1158
+ total_files_scanned: 0,
1159
+ total_matches: 0,
1160
+ cursor: 0,
1161
+ truncated: false,
1162
+ matches: [],
1163
+ error: "Name pattern must not be empty"
1164
+ };
1165
+ }
1166
+ if (!import_fs6.existsSync(project_path)) {
1167
+ return {
1168
+ success: false,
1169
+ project_path,
1170
+ total_files_scanned: 0,
1171
+ total_matches: 0,
1172
+ cursor: 0,
1173
+ truncated: false,
1174
+ matches: [],
1175
+ error: `Project path not found: ${project_path}`
1176
+ };
1177
+ }
1178
+ if (!isNativeModuleAvailable()) {
1179
+ return {
1180
+ success: false,
1181
+ project_path,
1182
+ total_files_scanned: 0,
1183
+ total_matches: 0,
1184
+ cursor: 0,
1185
+ truncated: false,
1186
+ matches: [],
1187
+ error: "Native scanner module not available. Run bun install in the project root."
1188
+ };
1189
+ }
1190
+ const extensions = [];
1191
+ if (file_type === "scene" || file_type === "all")
1192
+ extensions.push(".unity");
1193
+ if (file_type === "prefab" || file_type === "all")
1194
+ extensions.push(".prefab");
1195
+ const files = walk_project_files(project_path, extensions);
1196
+ const scanner = new UnityScanner;
1197
+ const matches = [];
1198
+ for (const file of files) {
1199
+ try {
1200
+ let gameObjects;
1201
+ const needFullData = !!(component || tag || layer !== undefined);
1202
+ if (name && !needFullData) {
1203
+ gameObjects = scanner.find_by_name(file, name, !exact);
1204
+ } else if (needFullData) {
1205
+ gameObjects = scanner.scan_scene_with_components(file);
1206
+ if (name) {
1207
+ const nameLower = name.toLowerCase();
1208
+ const hasWildcard = name.includes("*") || name.includes("?");
1209
+ gameObjects = gameObjects.filter((go) => {
1210
+ if (!go.name)
1211
+ return false;
1212
+ if (hasWildcard) {
1213
+ return glob_match(name, go.name);
1214
+ }
1215
+ if (exact) {
1216
+ return go.name === name;
1217
+ }
1218
+ return go.name.toLowerCase().includes(nameLower);
1219
+ });
1220
+ }
1221
+ } else {
1222
+ gameObjects = scanner.scan_scene_minimal(file);
1223
+ }
1224
+ for (const go of gameObjects) {
1225
+ const isFindResult = "resultType" in go;
1226
+ const isPrefab = isFindResult && go.resultType === "PrefabInstance";
1227
+ if (isPrefab && (component || tag || layer !== undefined)) {
1228
+ continue;
1229
+ }
1230
+ if (component) {
1231
+ if ("components" in go && go.components) {
1232
+ const hasComponent = go.components.some((c) => glob_match(component, c.type));
1233
+ if (!hasComponent)
1234
+ continue;
1235
+ } else {
1236
+ continue;
1237
+ }
1238
+ }
1239
+ if (tag) {
1240
+ if (!("tag" in go) || go.tag !== tag)
1241
+ continue;
1242
+ }
1243
+ if (layer !== undefined) {
1244
+ if (!("layer" in go) || go.layer !== layer)
1245
+ continue;
1246
+ }
1247
+ const relPath = path2.relative(project_path, file);
1248
+ const fileId = isFindResult ? go.fileId : go.file_id;
1249
+ const match = {
1250
+ file: relPath,
1251
+ game_object: go.name,
1252
+ file_id: fileId,
1253
+ tag: "tag" in go ? go.tag : undefined,
1254
+ layer: "layer" in go ? go.layer : undefined
1255
+ };
1256
+ if ("components" in go && go.components) {
1257
+ match.components = go.components.map((c) => c.type);
1258
+ }
1259
+ matches.push(match);
1260
+ if (max_matches !== undefined && matches.length >= max_matches)
1261
+ break;
1262
+ }
1263
+ if (max_matches !== undefined && matches.length >= max_matches)
1264
+ break;
1265
+ } catch {
1266
+ continue;
1267
+ }
1268
+ }
1269
+ return {
1270
+ success: true,
1271
+ project_path,
1272
+ total_files_scanned: files.length,
1273
+ total_matches: matches.length,
1274
+ cursor: 0,
1275
+ truncated: max_matches !== undefined && matches.length >= max_matches,
1276
+ matches
1277
+ };
1278
+ }
1279
+ function grep_project(options) {
1280
+ const nativeGrep = getNativeGrepProject();
1281
+ if (nativeGrep) {
1282
+ try {
1283
+ const nativeResult = nativeGrep({
1284
+ projectPath: options.project_path,
1285
+ pattern: options.pattern,
1286
+ fileType: options.file_type,
1287
+ maxResults: options.max_results,
1288
+ contextLines: options.context_lines
1289
+ });
1290
+ return {
1291
+ success: nativeResult.success,
1292
+ project_path: nativeResult.projectPath,
1293
+ pattern: nativeResult.pattern,
1294
+ total_files_scanned: nativeResult.totalFilesScanned,
1295
+ total_matches: nativeResult.totalMatches,
1296
+ truncated: nativeResult.truncated,
1297
+ error: nativeResult.error,
1298
+ matches: nativeResult.matches.map((m) => ({
1299
+ file: m.file,
1300
+ line_number: m.lineNumber,
1301
+ line: m.line,
1302
+ context_before: m.contextBefore,
1303
+ context_after: m.contextAfter
1304
+ }))
1305
+ };
1306
+ } catch {}
1307
+ }
1308
+ return grep_project_js(options);
1309
+ }
1310
+ function grep_project_js(options) {
1311
+ const {
1312
+ project_path,
1313
+ pattern,
1314
+ file_type = "all",
1315
+ max_results = 100,
1316
+ context_lines = 0
1317
+ } = options;
1318
+ if (!import_fs6.existsSync(project_path)) {
1319
+ return {
1320
+ success: false,
1321
+ project_path,
1322
+ pattern,
1323
+ total_files_scanned: 0,
1324
+ total_matches: 0,
1325
+ truncated: false,
1326
+ matches: [],
1327
+ error: `Project path not found: ${project_path}`
1328
+ };
1329
+ }
1330
+ let regex;
1331
+ try {
1332
+ regex = new RegExp(pattern, "i");
1333
+ } catch (err) {
1334
+ return {
1335
+ success: false,
1336
+ project_path,
1337
+ pattern,
1338
+ total_files_scanned: 0,
1339
+ total_matches: 0,
1340
+ truncated: false,
1341
+ matches: [],
1342
+ error: `Invalid regex pattern: ${err instanceof Error ? err.message : String(err)}`
1343
+ };
1344
+ }
1345
+ const EXTENSION_MAP = {
1346
+ cs: [".cs"],
1347
+ yaml: [".yaml", ".yml", ".unity", ".prefab", ".asset"],
1348
+ unity: [".unity"],
1349
+ prefab: [".prefab"],
1350
+ asset: [".asset"],
1351
+ all: [".cs", ".unity", ".prefab", ".asset", ".yaml", ".yml", ".txt", ".json", ".xml", ".shader", ".cginc", ".hlsl", ".compute", ".asmdef", ".asmref"]
1352
+ };
1353
+ const extensions = EXTENSION_MAP[file_type] || EXTENSION_MAP.all;
1354
+ const files = walk_project_files(project_path, extensions);
1355
+ const matches = [];
1356
+ let totalFilesScanned = 0;
1357
+ let truncated = false;
1358
+ for (const file of files) {
1359
+ const ext = path2.extname(file).toLowerCase();
1360
+ if (BINARY_EXTENSIONS.has(ext))
1361
+ continue;
1362
+ totalFilesScanned++;
1363
+ let content;
1364
+ try {
1365
+ content = import_fs6.readFileSync(file, "utf-8");
1366
+ } catch {
1367
+ continue;
1368
+ }
1369
+ const lines = content.split(`
1370
+ `);
1371
+ const relPath = path2.relative(project_path, file);
1372
+ for (let i = 0;i < lines.length; i++) {
1373
+ if (regex.test(lines[i])) {
1374
+ let line = lines[i];
1375
+ if (line.length > 200) {
1376
+ line = line.substring(0, 200) + "...";
1377
+ }
1378
+ const match = {
1379
+ file: relPath,
1380
+ line_number: i + 1,
1381
+ line
1382
+ };
1383
+ if (context_lines > 0) {
1384
+ match.context_before = [];
1385
+ match.context_after = [];
1386
+ for (let j = Math.max(0, i - context_lines);j < i; j++) {
1387
+ let ctxLine = lines[j];
1388
+ if (ctxLine.length > 200)
1389
+ ctxLine = ctxLine.substring(0, 200) + "...";
1390
+ match.context_before.push(ctxLine);
1391
+ }
1392
+ for (let j = i + 1;j <= Math.min(lines.length - 1, i + context_lines); j++) {
1393
+ let ctxLine = lines[j];
1394
+ if (ctxLine.length > 200)
1395
+ ctxLine = ctxLine.substring(0, 200) + "...";
1396
+ match.context_after.push(ctxLine);
1397
+ }
1398
+ }
1399
+ matches.push(match);
1400
+ if (matches.length >= max_results) {
1401
+ truncated = true;
1402
+ break;
1403
+ }
1404
+ }
1405
+ }
1406
+ if (truncated)
1407
+ break;
1408
+ }
1409
+ return {
1410
+ success: true,
1411
+ project_path,
1412
+ pattern,
1413
+ total_files_scanned: totalFilesScanned,
1414
+ total_matches: matches.length,
1415
+ truncated,
1416
+ matches
1417
+ };
1418
+ }
1419
+ // src/editor/create.ts
1420
+ var import_fs7 = require("fs");
1421
+
1422
+ // src/class-ids.ts
1423
+ var UNITY_CLASS_IDS = {
1424
+ 1: "GameObject",
1425
+ 2: "Component",
1426
+ 3: "LevelGameManager",
1427
+ 4: "Transform",
1428
+ 5: "TimeManager",
1429
+ 6: "GlobalGameManager",
1430
+ 8: "Behaviour",
1431
+ 9: "GameManager",
1432
+ 11: "AudioManager",
1433
+ 13: "InputManager",
1434
+ 18: "EditorExtension",
1435
+ 19: "Physics2DSettings",
1436
+ 20: "Camera",
1437
+ 21: "Material",
1438
+ 23: "MeshRenderer",
1439
+ 25: "Renderer",
1440
+ 27: "Texture",
1441
+ 28: "Texture2D",
1442
+ 29: "OcclusionCullingSettings",
1443
+ 30: "GraphicsSettings",
1444
+ 33: "MeshFilter",
1445
+ 41: "OcclusionPortal",
1446
+ 43: "Mesh",
1447
+ 45: "Skybox",
1448
+ 47: "QualitySettings",
1449
+ 48: "Shader",
1450
+ 49: "TextAsset",
1451
+ 50: "Rigidbody2D",
1452
+ 53: "Collider2D",
1453
+ 54: "Rigidbody",
1454
+ 55: "PhysicsManager",
1455
+ 56: "Collider",
1456
+ 57: "Joint",
1457
+ 58: "CircleCollider2D",
1458
+ 59: "HingeJoint",
1459
+ 60: "PolygonCollider2D",
1460
+ 61: "BoxCollider2D",
1461
+ 62: "PhysicsMaterial2D",
1462
+ 64: "MeshCollider",
1463
+ 65: "BoxCollider",
1464
+ 66: "CompositeCollider2D",
1465
+ 68: "EdgeCollider2D",
1466
+ 70: "CapsuleCollider2D",
1467
+ 72: "ComputeShader",
1468
+ 74: "AnimationClip",
1469
+ 75: "ConstantForce",
1470
+ 78: "TagManager",
1471
+ 81: "AudioListener",
1472
+ 82: "AudioSource",
1473
+ 83: "AudioClip",
1474
+ 84: "RenderTexture",
1475
+ 86: "CustomRenderTexture",
1476
+ 89: "Cubemap",
1477
+ 90: "Avatar",
1478
+ 91: "AnimatorController",
1479
+ 93: "RuntimeAnimatorController",
1480
+ 94: "ScriptMapper",
1481
+ 95: "Animator",
1482
+ 96: "TrailRenderer",
1483
+ 98: "DelayedCallManager",
1484
+ 102: "TextMesh",
1485
+ 104: "RenderSettings",
1486
+ 108: "Light",
1487
+ 109: "CGProgram",
1488
+ 110: "BaseAnimationTrack",
1489
+ 111: "Animation",
1490
+ 114: "MonoBehaviour",
1491
+ 115: "MonoScript",
1492
+ 117: "Texture3D",
1493
+ 119: "NewAnimationTrack",
1494
+ 120: "Projector",
1495
+ 121: "LineRenderer",
1496
+ 122: "Flare",
1497
+ 123: "Halo",
1498
+ 124: "LensFlare",
1499
+ 125: "FlareLayer",
1500
+ 126: "HaloLayer",
1501
+ 127: "NavMeshProjectSettings",
1502
+ 128: "Font",
1503
+ 129: "PlayerSettings",
1504
+ 130: "NamedObject",
1505
+ 134: "PhysicMaterial",
1506
+ 135: "SphereCollider",
1507
+ 136: "CapsuleCollider",
1508
+ 137: "SkinnedMeshRenderer",
1509
+ 138: "FixedJoint",
1510
+ 141: "BuildSettings",
1511
+ 142: "AssetBundle",
1512
+ 143: "CharacterController",
1513
+ 144: "CharacterJoint",
1514
+ 145: "SpringJoint",
1515
+ 146: "WheelCollider",
1516
+ 147: "ResourceManager",
1517
+ 150: "PreloadData",
1518
+ 153: "ConfigurableJoint",
1519
+ 154: "TerrainCollider",
1520
+ 156: "TerrainData",
1521
+ 157: "LightmapSettings",
1522
+ 158: "WebCamTexture",
1523
+ 159: "EditorSettings",
1524
+ 162: "EditorUserSettings",
1525
+ 164: "AudioReverbFilter",
1526
+ 165: "AudioHighPassFilter",
1527
+ 166: "AudioChorusFilter",
1528
+ 167: "AudioReverbZone",
1529
+ 168: "AudioEchoFilter",
1530
+ 169: "AudioLowPassFilter",
1531
+ 170: "AudioDistortionFilter",
1532
+ 171: "SparseTexture",
1533
+ 180: "AudioBehaviour",
1534
+ 181: "AudioFilter",
1535
+ 182: "WindZone",
1536
+ 183: "Cloth",
1537
+ 184: "SubstanceArchive",
1538
+ 185: "ProceduralMaterial",
1539
+ 186: "ProceduralTexture",
1540
+ 187: "Texture2DArray",
1541
+ 188: "CubemapArray",
1542
+ 191: "OffMeshLink",
1543
+ 192: "OcclusionArea",
1544
+ 193: "Tree",
1545
+ 195: "NavMeshAgent",
1546
+ 196: "NavMeshSettings",
1547
+ 198: "ParticleSystem",
1548
+ 199: "ParticleSystemRenderer",
1549
+ 200: "ShaderVariantCollection",
1550
+ 205: "LODGroup",
1551
+ 206: "BlendTree",
1552
+ 207: "Motion",
1553
+ 208: "NavMeshObstacle",
1554
+ 210: "SortingGroup",
1555
+ 212: "SpriteRenderer",
1556
+ 213: "Sprite",
1557
+ 214: "CachedSpriteAtlas",
1558
+ 215: "ReflectionProbe",
1559
+ 218: "Terrain",
1560
+ 220: "LightProbeGroup",
1561
+ 221: "AnimatorOverrideController",
1562
+ 222: "CanvasRenderer",
1563
+ 223: "Canvas",
1564
+ 224: "RectTransform",
1565
+ 225: "CanvasGroup",
1566
+ 226: "BillboardAsset",
1567
+ 227: "BillboardRenderer",
1568
+ 228: "SpeedTreeWindAsset",
1569
+ 229: "AnchoredJoint2D",
1570
+ 230: "Joint2D",
1571
+ 231: "SpringJoint2D",
1572
+ 232: "DistanceJoint2D",
1573
+ 233: "HingeJoint2D",
1574
+ 234: "SliderJoint2D",
1575
+ 235: "WheelJoint2D",
1576
+ 236: "ClusterInputManager",
1577
+ 237: "BaseVideoTexture",
1578
+ 238: "NavMeshData",
1579
+ 240: "AudioMixer",
1580
+ 241: "AudioMixerController",
1581
+ 243: "AudioMixerGroupController",
1582
+ 244: "AudioMixerEffectController",
1583
+ 245: "AudioMixerSnapshotController",
1584
+ 246: "PhysicsUpdateBehaviour2D",
1585
+ 247: "ConstantForce2D",
1586
+ 248: "Effector2D",
1587
+ 249: "AreaEffector2D",
1588
+ 250: "PointEffector2D",
1589
+ 251: "PlatformEffector2D",
1590
+ 252: "SurfaceEffector2D",
1591
+ 253: "BuoyancyEffector2D",
1592
+ 254: "RelativeJoint2D",
1593
+ 255: "FixedJoint2D",
1594
+ 256: "FrictionJoint2D",
1595
+ 257: "TargetJoint2D",
1596
+ 258: "LightProbes",
1597
+ 259: "LightProbeProxyVolume",
1598
+ 260: "SampleClip",
1599
+ 261: "AudioMixerSnapshot",
1600
+ 262: "AudioMixerGroup",
1601
+ 265: "NScreenBridge",
1602
+ 271: "AssetBundleManifest",
1603
+ 272: "UnityAdsManager",
1604
+ 273: "RuntimeInitializeOnLoadManager",
1605
+ 280: "UnityConnectSettings",
1606
+ 281: "AvatarMask",
1607
+ 290: "PlayableDirector",
1608
+ 292: "VideoPlayer",
1609
+ 293: "VideoClip",
1610
+ 294: "ParticleSystemForceField",
1611
+ 298: "SpriteMask",
1612
+ 300: "WorldAnchor",
1613
+ 301: "OcclusionCullingData",
1614
+ 310: "PrefabInstance",
1615
+ 319: "TextureImporter",
1616
+ 363: "Preset",
1617
+ 687078895: "SpriteAtlas",
1618
+ 1839735485: "Tilemap",
1619
+ 1839735486: "TilemapCollider2D",
1620
+ 1839735487: "TilemapRenderer"
1621
+ };
1622
+ var UNITY_CLASS_NAMES = Object.fromEntries(Object.entries(UNITY_CLASS_IDS).map(([id, name]) => [name, parseInt(id, 10)]));
1623
+ function get_class_id_name(class_id) {
1624
+ return UNITY_CLASS_IDS[class_id] || `Unknown_${class_id}`;
1625
+ }
1626
+
1627
+ // src/editor/unity-block.ts
1628
+ var HEADER_PATTERN = /^--- !u!(\d+) &(\d+)(\s+stripped)?/;
1629
+ function parse_header(raw) {
1630
+ const first_newline = raw.indexOf(`
1631
+ `);
1632
+ const first_line = first_newline === -1 ? raw : raw.slice(0, first_newline);
1633
+ const match = first_line.match(HEADER_PATTERN);
1634
+ if (!match)
1635
+ return null;
1636
+ return {
1637
+ class_id: parseInt(match[1], 10),
1638
+ file_id: match[2],
1639
+ is_stripped: match[3] !== undefined
1640
+ };
1641
+ }
1642
+ function escape_regex(str) {
1643
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1644
+ }
1645
+
1646
+ class UnityBlock {
1647
+ _raw;
1648
+ _header;
1649
+ _dirty = false;
1650
+ _format_cache = new Map;
1651
+ constructor(raw) {
1652
+ const normalized = raw.replace(/\r\n/g, `
1653
+ `);
1654
+ const header = parse_header(normalized);
1655
+ if (!header) {
1656
+ throw new Error(`Invalid Unity YAML block header: "${normalized.slice(0, 80)}"`);
1657
+ }
1658
+ this._raw = normalized;
1659
+ this._header = header;
1660
+ }
1661
+ get file_id() {
1662
+ return this._header.file_id;
1663
+ }
1664
+ get class_id() {
1665
+ return this._header.class_id;
1666
+ }
1667
+ get is_stripped() {
1668
+ return this._header.is_stripped;
1669
+ }
1670
+ get type_name() {
1671
+ return get_class_id_name(this._header.class_id);
1672
+ }
1673
+ get raw() {
1674
+ return this._raw;
1675
+ }
1676
+ get dirty() {
1677
+ return this._dirty;
1678
+ }
1679
+ get_property(path3) {
1680
+ if (path3.includes("Array.data[")) {
1681
+ return this._get_array_element(path3);
1682
+ }
1683
+ if (path3.includes(".")) {
1684
+ const parts = path3.split(".");
1685
+ const root_prop = parts[0];
1686
+ const root_pattern = new RegExp(`^\\s*${escape_regex(root_prop)}:\\s*(.*)$`, "m");
1687
+ const root_match = this._raw.match(root_pattern);
1688
+ if (root_match) {
1689
+ const obj_str = root_match[1].trim();
1690
+ const sub_field = parts.slice(1).join(".");
1691
+ const sub_pattern = new RegExp(`${escape_regex(sub_field)}:\\s*([^,}]+)`);
1692
+ const sub_match = obj_str.match(sub_pattern);
1693
+ if (sub_match)
1694
+ return sub_match[1].trim();
1695
+ }
1696
+ const block_value = this._extract_block_style_value(parts);
1697
+ if (block_value !== null)
1698
+ return block_value;
1699
+ return null;
1700
+ }
1701
+ const prop_pattern = new RegExp(`^\\s*${escape_regex(path3)}:\\s*(.*)$`, "m");
1702
+ const match = this._raw.match(prop_pattern);
1703
+ return match ? match[1].trim() : null;
1704
+ }
1705
+ set_property(path3, value, object_reference) {
1706
+ const old_raw = this._raw;
1707
+ const effective_ref = object_reference && object_reference !== "{fileID: 0}" ? object_reference : undefined;
1708
+ if (!path3.includes(".") && !path3.includes("Array")) {
1709
+ const prop_pattern = new RegExp(`(^\\s*${escape_regex(path3)}:\\s*)(.*)$`, "m");
1710
+ if (prop_pattern.test(this._raw)) {
1711
+ const replacement_value = effective_ref ?? value;
1712
+ this._raw = this._raw.replace(prop_pattern, `$1${replacement_value}`);
1713
+ }
1714
+ return this._check_dirty(old_raw);
1715
+ }
1716
+ if (path3.includes(".") && !path3.includes("Array")) {
1717
+ const parts = path3.split(".");
1718
+ const parent_prop = parts[0];
1719
+ const sub_field = parts[1];
1720
+ const inline_pattern = new RegExp(`(${escape_regex(parent_prop)}:\\s*\\{)([^}]*)(\\})`, "m");
1721
+ const inline_match = this._raw.match(inline_pattern);
1722
+ let inline_applied = false;
1723
+ if (inline_match) {
1724
+ const fields = inline_match[2];
1725
+ const field_pattern = new RegExp(`(${escape_regex(sub_field)}:\\s*)([^,}]+)`);
1726
+ if (field_pattern.test(fields)) {
1727
+ const updated_fields = fields.replace(field_pattern, `$1${value}`);
1728
+ this._raw = this._raw.replace(inline_pattern, `$1${updated_fields}$3`);
1729
+ inline_applied = true;
1730
+ }
1731
+ }
1732
+ if (!inline_applied) {
1733
+ const effective_value = effective_ref ?? value;
1734
+ const block_result = this._resolve_block_style_path(parts, effective_value);
1735
+ if (block_result !== null) {
1736
+ this._raw = block_result;
1737
+ }
1738
+ }
1739
+ return this._check_dirty(old_raw);
1740
+ }
1741
+ if (path3.includes("Array.data[")) {
1742
+ const array_match = path3.match(/^(.+)\.Array\.data\[(\d+)\]$/);
1743
+ if (array_match) {
1744
+ const array_prop = array_match[1];
1745
+ const index = parseInt(array_match[2], 10);
1746
+ const ref_value = effective_ref ?? value;
1747
+ const array_pattern = new RegExp(`${escape_regex(array_prop)}:\\s*\\n((?:\\s*-\\s*[^\\n]+\\n)*)`, "m");
1748
+ const array_block_match = this._raw.match(array_pattern);
1749
+ if (array_block_match) {
1750
+ const lines = array_block_match[1].split(`
1751
+ `).filter((l) => l.trim().startsWith("-"));
1752
+ if (index < lines.length) {
1753
+ const old_line = lines[index];
1754
+ const new_line = old_line.replace(/-\s*.*/, `- ${ref_value}`);
1755
+ this._raw = this._raw.replace(old_line, new_line);
1756
+ }
1757
+ }
1758
+ }
1759
+ return this._check_dirty(old_raw);
1760
+ }
1761
+ return false;
1762
+ }
1763
+ has_property(path3) {
1764
+ return this.get_property(path3) !== null;
1765
+ }
1766
+ detect_format(property_name) {
1767
+ const cached = this._format_cache.get(property_name);
1768
+ if (cached)
1769
+ return cached;
1770
+ const inline_pattern = new RegExp(`^\\s*${escape_regex(property_name)}:\\s*\\{[^}]+\\}\\s*$`, "m");
1771
+ const result = inline_pattern.test(this._raw) ? "inline" : "block";
1772
+ this._format_cache.set(property_name, result);
1773
+ return result;
1774
+ }
1775
+ get_array_length(array_property) {
1776
+ const empty_pattern = new RegExp(`^\\s*${escape_regex(array_property)}:\\s*\\[\\]\\s*$`, "m");
1777
+ if (empty_pattern.test(this._raw))
1778
+ return 0;
1779
+ const lines = this._raw.split(`
1780
+ `);
1781
+ let in_array = false;
1782
+ let array_indent = -1;
1783
+ let count = 0;
1784
+ for (const line of lines) {
1785
+ if (!in_array) {
1786
+ const header_match = line.match(new RegExp(`^(\\s*)${escape_regex(array_property)}:\\s*$`));
1787
+ if (header_match) {
1788
+ in_array = true;
1789
+ array_indent = header_match[1].length;
1790
+ continue;
1791
+ }
1792
+ } else {
1793
+ const trimmed = line.trim();
1794
+ if (trimmed === "")
1795
+ continue;
1796
+ const leading_match = line.match(/^(\s*)/);
1797
+ const indent = leading_match ? leading_match[1].length : 0;
1798
+ if (indent < array_indent)
1799
+ break;
1800
+ if (indent === array_indent && !trimmed.startsWith("-"))
1801
+ break;
1802
+ if (trimmed.startsWith("-")) {
1803
+ count++;
1804
+ }
1805
+ }
1806
+ }
1807
+ return count;
1808
+ }
1809
+ insert_array_element(array_property, index, value) {
1810
+ const old_raw = this._raw;
1811
+ const empty_pattern = new RegExp(`(^(\\s*)${escape_regex(array_property)}:\\s*)\\[\\]`, "m");
1812
+ const empty_match = this._raw.match(empty_pattern);
1813
+ if (empty_match) {
1814
+ const base_indent = empty_match[2];
1815
+ const element_indent2 = base_indent + " ";
1816
+ this._raw = this._raw.replace(empty_pattern, `$1
1817
+ ${element_indent2}- ${value}`);
1818
+ return this._check_dirty(old_raw);
1819
+ }
1820
+ const lines = this._raw.split(`
1821
+ `);
1822
+ let array_header_idx = -1;
1823
+ let array_indent = -1;
1824
+ const element_indices = [];
1825
+ for (let i = 0;i < lines.length; i++) {
1826
+ if (array_header_idx === -1) {
1827
+ const header_match = lines[i].match(new RegExp(`^(\\s*)${escape_regex(array_property)}:\\s*$`));
1828
+ if (header_match) {
1829
+ array_header_idx = i;
1830
+ array_indent = header_match[1].length;
1831
+ continue;
1832
+ }
1833
+ } else {
1834
+ const trimmed = lines[i].trim();
1835
+ if (trimmed === "")
1836
+ continue;
1837
+ const leading_match = lines[i].match(/^(\s*)/);
1838
+ const indent = leading_match ? leading_match[1].length : 0;
1839
+ if (indent < array_indent)
1840
+ break;
1841
+ if (indent === array_indent && !trimmed.startsWith("-"))
1842
+ break;
1843
+ if (trimmed.startsWith("-")) {
1844
+ element_indices.push(i);
1845
+ }
1846
+ }
1847
+ }
1848
+ if (array_header_idx === -1)
1849
+ return false;
1850
+ let element_indent;
1851
+ if (element_indices.length > 0) {
1852
+ const first_elem = lines[element_indices[0]];
1853
+ const indent_match = first_elem.match(/^(\s*)-/);
1854
+ element_indent = indent_match ? indent_match[1] : " ";
1855
+ } else {
1856
+ element_indent = " ".repeat(array_indent + 2);
1857
+ }
1858
+ const new_line = `${element_indent}- ${value}`;
1859
+ let insert_at;
1860
+ if (index === -1 || index >= element_indices.length) {
1861
+ insert_at = element_indices.length > 0 ? element_indices[element_indices.length - 1] + 1 : array_header_idx + 1;
1862
+ } else {
1863
+ insert_at = element_indices[index];
1864
+ }
1865
+ lines.splice(insert_at, 0, new_line);
1866
+ this._raw = lines.join(`
1867
+ `);
1868
+ return this._check_dirty(old_raw);
1869
+ }
1870
+ remove_array_element(array_property, index) {
1871
+ const old_raw = this._raw;
1872
+ const lines = this._raw.split(`
1873
+ `);
1874
+ let array_header_idx = -1;
1875
+ let array_indent = -1;
1876
+ const element_indices = [];
1877
+ for (let i = 0;i < lines.length; i++) {
1878
+ if (array_header_idx === -1) {
1879
+ const header_match = lines[i].match(new RegExp(`^(\\s*)${escape_regex(array_property)}:\\s*$`));
1880
+ if (header_match) {
1881
+ array_header_idx = i;
1882
+ array_indent = header_match[1].length;
1883
+ continue;
1884
+ }
1885
+ } else {
1886
+ const trimmed = lines[i].trim();
1887
+ if (trimmed === "")
1888
+ continue;
1889
+ const leading_match = lines[i].match(/^(\s*)/);
1890
+ const indent = leading_match ? leading_match[1].length : 0;
1891
+ if (indent < array_indent)
1892
+ break;
1893
+ if (indent === array_indent && !trimmed.startsWith("-"))
1894
+ break;
1895
+ if (trimmed.startsWith("-")) {
1896
+ element_indices.push(i);
1897
+ }
1898
+ }
1899
+ }
1900
+ if (array_header_idx === -1 || index < 0 || index >= element_indices.length) {
1901
+ return false;
1902
+ }
1903
+ lines.splice(element_indices[index], 1);
1904
+ if (element_indices.length === 1) {
1905
+ const header_indent_match = lines[array_header_idx].match(/^(\s*)/);
1906
+ const header_indent = header_indent_match ? header_indent_match[1] : "";
1907
+ lines[array_header_idx] = `${header_indent}${array_property}: []`;
1908
+ }
1909
+ this._raw = lines.join(`
1910
+ `);
1911
+ return this._check_dirty(old_raw);
1912
+ }
1913
+ extract_file_id_refs() {
1914
+ const refs = [];
1915
+ const pattern = /\{fileID:\s*(\d+)/g;
1916
+ const first_newline = this._raw.indexOf(`
1917
+ `);
1918
+ const body = first_newline === -1 ? "" : this._raw.slice(first_newline);
1919
+ let match;
1920
+ while ((match = pattern.exec(body)) !== null) {
1921
+ if (match[1] !== "0") {
1922
+ refs.push(match[1]);
1923
+ }
1924
+ }
1925
+ return refs;
1926
+ }
1927
+ remap_file_id(old_id, new_id) {
1928
+ if (old_id === "0")
1929
+ return;
1930
+ const old_raw = this._raw;
1931
+ const escaped_old = escape_regex(old_id);
1932
+ this._raw = this._raw.replace(new RegExp(`^(--- !u!\\d+ &)${escaped_old}(\\s|$)`), `$1${new_id}$2`);
1933
+ this._raw = this._raw.replace(new RegExp(`(\\{fileID:\\s*)${escaped_old}(\\})`, "g"), `$1${new_id}$2`);
1934
+ if (this._raw !== old_raw) {
1935
+ this._dirty = true;
1936
+ if (this._header.file_id === old_id) {
1937
+ this._header = { ...this._header, file_id: new_id };
1938
+ }
1939
+ }
1940
+ }
1941
+ replace_raw(new_text) {
1942
+ const header = parse_header(new_text);
1943
+ if (!header) {
1944
+ throw new Error(`Invalid Unity YAML block header in replacement text: "${new_text.slice(0, 80)}"`);
1945
+ }
1946
+ this._raw = new_text;
1947
+ this._header = header;
1948
+ this._dirty = true;
1949
+ this._format_cache.clear();
1950
+ }
1951
+ clone() {
1952
+ return new UnityBlock(this._raw);
1953
+ }
1954
+ _check_dirty(old_raw) {
1955
+ if (this._raw !== old_raw) {
1956
+ this._dirty = true;
1957
+ return true;
1958
+ }
1959
+ return false;
1960
+ }
1961
+ _get_array_element(path3) {
1962
+ const array_match = path3.match(/^(.+)\.Array\.data\[(\d+)\]$/);
1963
+ if (!array_match)
1964
+ return null;
1965
+ const array_prop = array_match[1];
1966
+ const index = parseInt(array_match[2], 10);
1967
+ const array_pattern = new RegExp(`${escape_regex(array_prop)}:\\s*\\n((?:\\s*-\\s*[^\\n]+\\n?)*)`, "m");
1968
+ const array_block_match = this._raw.match(array_pattern);
1969
+ if (!array_block_match)
1970
+ return null;
1971
+ const lines = array_block_match[1].split(`
1972
+ `).filter((l) => l.trim().startsWith("-"));
1973
+ if (index >= lines.length)
1974
+ return null;
1975
+ const element_match = lines[index].match(/^\s*-\s*(.+)$/);
1976
+ return element_match ? element_match[1].trim() : null;
1977
+ }
1978
+ _extract_block_style_value(parts) {
1979
+ const lines = this._raw.split(`
1980
+ `);
1981
+ let search_start = 0;
1982
+ let search_end = lines.length;
1983
+ for (let seg = 0;seg < parts.length - 1; seg++) {
1984
+ const segment = parts[seg];
1985
+ let parent_idx = -1;
1986
+ let parent_indent = -1;
1987
+ for (let i = search_start;i < search_end; i++) {
1988
+ const match = lines[i].match(new RegExp(`^(\\s*)${escape_regex(segment)}:\\s*(.*)$`));
1989
+ if (match) {
1990
+ const trailing = match[2].trim();
1991
+ if (trailing === "") {
1992
+ parent_idx = i;
1993
+ parent_indent = match[1].length;
1994
+ break;
1995
+ }
1996
+ for (let j = i + 1;j < search_end; j++) {
1997
+ if (lines[j].trim() === "")
1998
+ continue;
1999
+ const nextLeading = lines[j].match(/^(\s*)/);
2000
+ if (nextLeading && nextLeading[1].length > match[1].length) {
2001
+ parent_idx = i;
2002
+ parent_indent = match[1].length;
2003
+ }
2004
+ break;
2005
+ }
2006
+ if (parent_idx !== -1)
2007
+ break;
2008
+ }
2009
+ }
2010
+ if (parent_idx === -1)
2011
+ return null;
2012
+ let child_indent = -1;
2013
+ for (let i = parent_idx + 1;i < search_end; i++) {
2014
+ if (lines[i].trim() === "")
2015
+ continue;
2016
+ const leading_spaces = lines[i].match(/^(\s*)/);
2017
+ if (leading_spaces) {
2018
+ const indent = leading_spaces[1].length;
2019
+ if (indent > parent_indent) {
2020
+ child_indent = indent;
2021
+ break;
2022
+ }
2023
+ }
2024
+ break;
2025
+ }
2026
+ if (child_indent === -1)
2027
+ return null;
2028
+ search_start = parent_idx + 1;
2029
+ for (let i = parent_idx + 1;i < search_end; i++) {
2030
+ if (lines[i].trim() === "")
2031
+ continue;
2032
+ const leading_spaces = lines[i].match(/^(\s*)/);
2033
+ if (leading_spaces && leading_spaces[1].length < child_indent) {
2034
+ search_end = i;
2035
+ break;
2036
+ }
2037
+ }
2038
+ }
2039
+ const final_prop = parts[parts.length - 1];
2040
+ for (let i = search_start;i < search_end; i++) {
2041
+ const match = lines[i].match(new RegExp(`^\\s*${escape_regex(final_prop)}:\\s*(.+)$`));
2042
+ if (match) {
2043
+ return match[1].trim();
2044
+ }
2045
+ }
2046
+ return null;
2047
+ }
2048
+ _resolve_block_style_path(segments, value) {
2049
+ const lines = this._raw.split(`
2050
+ `);
2051
+ let search_start = 0;
2052
+ let search_end = lines.length;
2053
+ for (let seg = 0;seg < segments.length - 1; seg++) {
2054
+ const segment = segments[seg];
2055
+ let parent_idx = -1;
2056
+ let parent_indent = -1;
2057
+ for (let i = search_start;i < search_end; i++) {
2058
+ const match = lines[i].match(new RegExp(`^(\\s*)${escape_regex(segment)}:\\s*(.*)$`));
2059
+ if (match) {
2060
+ const trailing = match[2].trim();
2061
+ if (trailing === "") {
2062
+ parent_idx = i;
2063
+ parent_indent = match[1].length;
2064
+ break;
2065
+ }
2066
+ for (let j = i + 1;j < search_end; j++) {
2067
+ if (lines[j].trim() === "")
2068
+ continue;
2069
+ const nextLeading = lines[j].match(/^(\s*)/);
2070
+ if (nextLeading && nextLeading[1].length > match[1].length) {
2071
+ parent_idx = i;
2072
+ parent_indent = match[1].length;
2073
+ }
2074
+ break;
2075
+ }
2076
+ if (parent_idx !== -1)
2077
+ break;
2078
+ }
2079
+ }
2080
+ if (parent_idx === -1)
2081
+ return null;
2082
+ let child_indent = -1;
2083
+ for (let i = parent_idx + 1;i < search_end; i++) {
2084
+ if (lines[i].trim() === "")
2085
+ continue;
2086
+ const leading_spaces = lines[i].match(/^(\s*)/);
2087
+ if (leading_spaces) {
2088
+ const indent = leading_spaces[1].length;
2089
+ if (indent > parent_indent) {
2090
+ child_indent = indent;
2091
+ break;
2092
+ }
2093
+ }
2094
+ break;
2095
+ }
2096
+ if (child_indent === -1)
2097
+ return null;
2098
+ search_start = parent_idx + 1;
2099
+ for (let i = parent_idx + 1;i < search_end; i++) {
2100
+ if (lines[i].trim() === "")
2101
+ continue;
2102
+ const leading_spaces = lines[i].match(/^(\s*)/);
2103
+ if (leading_spaces && leading_spaces[1].length < child_indent) {
2104
+ search_end = i;
2105
+ break;
2106
+ }
2107
+ }
2108
+ }
2109
+ const final_prop = segments[segments.length - 1];
2110
+ for (let i = search_start;i < search_end; i++) {
2111
+ const match = lines[i].match(new RegExp(`^(\\s*${escape_regex(final_prop)}:\\s*).+$`));
2112
+ if (match) {
2113
+ lines[i] = match[1] + value;
2114
+ return lines.join(`
2115
+ `);
2116
+ }
2117
+ }
2118
+ return null;
2119
+ }
2120
+ }
2121
+
2122
+ // src/editor/create.ts
2123
+ function createScene(options) {
2124
+ const { output_path, include_defaults, scene_guid } = options;
2125
+ const pathError = validate_file_path(output_path, "write");
2126
+ if (pathError) {
2127
+ return { success: false, output_path, error: pathError };
2128
+ }
2129
+ if (!output_path.endsWith(".unity")) {
2130
+ return {
2131
+ success: false,
2132
+ output_path,
2133
+ error: "Output path must have .unity extension"
2134
+ };
2135
+ }
2136
+ if (import_fs7.existsSync(output_path)) {
2137
+ return {
2138
+ success: false,
2139
+ output_path,
2140
+ error: `File already exists: ${output_path}. Delete it first or choose a different path.`
2141
+ };
2142
+ }
2143
+ const guid = scene_guid || generateGuid();
2144
+ let yaml = `%YAML 1.1
2145
+ %TAG !u! tag:unity3d.com,2011:
2146
+ --- !u!29 &1
2147
+ OcclusionCullingSettings:
2148
+ m_ObjectHideFlags: 0
2149
+ serializedVersion: 2
2150
+ m_OcclusionBakeSettings:
2151
+ smallestOccluder: 5
2152
+ smallestHole: 0.25
2153
+ backfaceThreshold: 100
2154
+ m_SceneGUID: 00000000000000000000000000000000
2155
+ m_OcclusionCullingData: {fileID: 0}
2156
+ --- !u!104 &2
2157
+ RenderSettings:
2158
+ m_ObjectHideFlags: 0
2159
+ serializedVersion: 9
2160
+ m_Fog: 0
2161
+ m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
2162
+ m_FogMode: 3
2163
+ m_FogDensity: 0.01
2164
+ m_LinearFogStart: 0
2165
+ m_LinearFogEnd: 300
2166
+ m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
2167
+ m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
2168
+ m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
2169
+ m_AmbientIntensity: 1
2170
+ m_AmbientMode: 0
2171
+ m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
2172
+ m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
2173
+ m_HaloStrength: 0.5
2174
+ m_FlareStrength: 1
2175
+ m_FlareFadeSpeed: 3
2176
+ m_HaloTexture: {fileID: 0}
2177
+ m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
2178
+ m_DefaultReflectionMode: 0
2179
+ m_DefaultReflectionResolution: 128
2180
+ m_ReflectionBounces: 1
2181
+ m_ReflectionIntensity: 1
2182
+ m_CustomReflection: {fileID: 0}
2183
+ m_Sun: {fileID: 0}
2184
+ m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1}
2185
+ m_UseRadianceAmbientProbe: 0
2186
+ --- !u!157 &3
2187
+ LightmapSettings:
2188
+ m_ObjectHideFlags: 0
2189
+ serializedVersion: 12
2190
+ m_GIWorkflowMode: 1
2191
+ m_GISettings:
2192
+ serializedVersion: 2
2193
+ m_BounceScale: 1
2194
+ m_IndirectOutputScale: 1
2195
+ m_AlbedoBoost: 1
2196
+ m_EnvironmentLightingMode: 0
2197
+ m_EnableBakedLightmaps: 1
2198
+ m_EnableRealtimeLightmaps: 0
2199
+ m_LightmapEditorSettings:
2200
+ serializedVersion: 12
2201
+ m_Resolution: 2
2202
+ m_BakeResolution: 40
2203
+ m_AtlasSize: 1024
2204
+ m_AO: 0
2205
+ m_AOMaxDistance: 1
2206
+ m_CompAOExponent: 1
2207
+ m_CompAOExponentDirect: 0
2208
+ m_ExtractAmbientOcclusion: 0
2209
+ m_Padding: 2
2210
+ m_LightmapParameters: {fileID: 0}
2211
+ m_LightmapsBakeMode: 1
2212
+ m_TextureCompression: 1
2213
+ m_FinalGather: 0
2214
+ m_FinalGatherFiltering: 1
2215
+ m_FinalGatherRayCount: 256
2216
+ m_ReflectionCompression: 2
2217
+ m_MixedBakeMode: 2
2218
+ m_BakeBackend: 1
2219
+ m_PVRSampling: 1
2220
+ m_PVRDirectSampleCount: 32
2221
+ m_PVRSampleCount: 512
2222
+ m_PVRBounces: 2
2223
+ m_PVREnvironmentSampleCount: 256
2224
+ m_PVREnvironmentReferencePointCount: 2048
2225
+ m_PVRFilteringMode: 1
2226
+ m_PVRDenoiserTypeDirect: 1
2227
+ m_PVRDenoiserTypeIndirect: 1
2228
+ m_PVRDenoiserTypeAO: 1
2229
+ m_PVRFilterTypeDirect: 0
2230
+ m_PVRFilterTypeIndirect: 0
2231
+ m_PVRFilterTypeAO: 0
2232
+ m_PVREnvironmentMIS: 1
2233
+ m_PVRCulling: 1
2234
+ m_PVRFilteringGaussRadiusDirect: 1
2235
+ m_PVRFilteringGaussRadiusIndirect: 5
2236
+ m_PVRFilteringGaussRadiusAO: 2
2237
+ m_PVRFilteringAtrousPositionSigmaDirect: 0.5
2238
+ m_PVRFilteringAtrousPositionSigmaIndirect: 2
2239
+ m_PVRFilteringAtrousPositionSigmaAO: 1
2240
+ m_ExportTrainingData: 0
2241
+ m_TrainingDataDestination: TrainingData
2242
+ m_LightProbeSampleCountMultiplier: 4
2243
+ m_LightingDataAsset: {fileID: 0}
2244
+ m_LightingSettings: {fileID: 0}
2245
+ --- !u!196 &4
2246
+ NavMeshSettings:
2247
+ serializedVersion: 2
2248
+ m_ObjectHideFlags: 0
2249
+ m_BuildSettings:
2250
+ serializedVersion: 3
2251
+ agentTypeID: 0
2252
+ agentRadius: 0.5
2253
+ agentHeight: 2
2254
+ agentSlope: 45
2255
+ agentClimb: 0.4
2256
+ ledgeDropHeight: 0
2257
+ maxJumpAcrossDistance: 0
2258
+ minRegionArea: 2
2259
+ manualCellSize: 0
2260
+ cellSize: 0.16666667
2261
+ manualTileSize: 0
2262
+ tileSize: 256
2263
+ buildHeightMesh: 0
2264
+ maxJobWorkers: 0
2265
+ preserveTilesOutsideBounds: 0
2266
+ debug:
2267
+ m_Flags: 0
2268
+ m_NavMeshData: {fileID: 0}
2269
+ `;
2270
+ if (include_defaults) {
2271
+ yaml += `--- !u!1 &519420028
2272
+ GameObject:
2273
+ m_ObjectHideFlags: 0
2274
+ m_CorrespondingSourceObject: {fileID: 0}
2275
+ m_PrefabInstance: {fileID: 0}
2276
+ m_PrefabAsset: {fileID: 0}
2277
+ serializedVersion: 6
2278
+ m_Component:
2279
+ - component: {fileID: 519420032}
2280
+ - component: {fileID: 519420031}
2281
+ - component: {fileID: 519420029}
2282
+ m_Layer: 0
2283
+ m_Name: Main Camera
2284
+ m_TagString: MainCamera
2285
+ m_Icon: {fileID: 0}
2286
+ m_NavMeshLayer: 0
2287
+ m_StaticEditorFlags: 0
2288
+ m_IsActive: 1
2289
+ --- !u!4 &519420032
2290
+ Transform:
2291
+ m_ObjectHideFlags: 0
2292
+ m_CorrespondingSourceObject: {fileID: 0}
2293
+ m_PrefabInstance: {fileID: 0}
2294
+ m_PrefabAsset: {fileID: 0}
2295
+ m_GameObject: {fileID: 519420028}
2296
+ serializedVersion: 2
2297
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
2298
+ m_LocalPosition: {x: 0, y: 1, z: -10}
2299
+ m_LocalScale: {x: 1, y: 1, z: 1}
2300
+ m_ConstrainProportionsScale: 0
2301
+ m_Children: []
2302
+ m_Father: {fileID: 0}
2303
+ m_RootOrder: 0
2304
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
2305
+ --- !u!20 &519420031
2306
+ Camera:
2307
+ m_ObjectHideFlags: 0
2308
+ m_CorrespondingSourceObject: {fileID: 0}
2309
+ m_PrefabInstance: {fileID: 0}
2310
+ m_PrefabAsset: {fileID: 0}
2311
+ m_GameObject: {fileID: 519420028}
2312
+ m_Enabled: 1
2313
+ serializedVersion: 2
2314
+ m_ClearFlags: 1
2315
+ m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
2316
+ m_projectionMatrixMode: 1
2317
+ m_GateFitMode: 2
2318
+ m_FOVAxisMode: 0
2319
+ m_Iso: 200
2320
+ m_ShutterSpeed: 0.005
2321
+ m_Aperture: 16
2322
+ m_FocusDistance: 10
2323
+ m_FocalLength: 50
2324
+ m_BladeCount: 5
2325
+ m_Curvature: {x: 2, y: 11}
2326
+ m_BarrelClipping: 0.25
2327
+ m_Anamorphism: 0
2328
+ m_SensorSize: {x: 36, y: 24}
2329
+ m_LensShift: {x: 0, y: 0}
2330
+ m_NormalizedViewPortRect:
2331
+ serializedVersion: 2
2332
+ x: 0
2333
+ y: 0
2334
+ width: 1
2335
+ height: 1
2336
+ near clip plane: 0.3
2337
+ far clip plane: 1000
2338
+ field of view: 60
2339
+ orthographic: 0
2340
+ orthographic size: 5
2341
+ m_Depth: -1
2342
+ m_CullingMask:
2343
+ serializedVersion: 2
2344
+ m_Bits: 4294967295
2345
+ m_RenderingPath: -1
2346
+ m_TargetTexture: {fileID: 0}
2347
+ m_TargetDisplay: 0
2348
+ m_TargetEye: 3
2349
+ m_HDR: 1
2350
+ m_AllowMSAA: 1
2351
+ m_AllowDynamicResolution: 0
2352
+ m_ForceIntoRT: 0
2353
+ m_OcclusionCulling: 1
2354
+ m_StereoConvergence: 10
2355
+ m_StereoSeparation: 0.022
2356
+ --- !u!81 &519420029
2357
+ AudioListener:
2358
+ m_ObjectHideFlags: 0
2359
+ m_CorrespondingSourceObject: {fileID: 0}
2360
+ m_PrefabInstance: {fileID: 0}
2361
+ m_PrefabAsset: {fileID: 0}
2362
+ m_GameObject: {fileID: 519420028}
2363
+ m_Enabled: 1
2364
+ --- !u!1 &705507993
2365
+ GameObject:
2366
+ m_ObjectHideFlags: 0
2367
+ m_CorrespondingSourceObject: {fileID: 0}
2368
+ m_PrefabInstance: {fileID: 0}
2369
+ m_PrefabAsset: {fileID: 0}
2370
+ serializedVersion: 6
2371
+ m_Component:
2372
+ - component: {fileID: 705507995}
2373
+ - component: {fileID: 705507994}
2374
+ m_Layer: 0
2375
+ m_Name: Directional Light
2376
+ m_TagString: Untagged
2377
+ m_Icon: {fileID: 0}
2378
+ m_NavMeshLayer: 0
2379
+ m_StaticEditorFlags: 0
2380
+ m_IsActive: 1
2381
+ --- !u!4 &705507995
2382
+ Transform:
2383
+ m_ObjectHideFlags: 0
2384
+ m_CorrespondingSourceObject: {fileID: 0}
2385
+ m_PrefabInstance: {fileID: 0}
2386
+ m_PrefabAsset: {fileID: 0}
2387
+ m_GameObject: {fileID: 705507993}
2388
+ serializedVersion: 2
2389
+ m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
2390
+ m_LocalPosition: {x: 0, y: 3, z: 0}
2391
+ m_LocalScale: {x: 1, y: 1, z: 1}
2392
+ m_ConstrainProportionsScale: 0
2393
+ m_Children: []
2394
+ m_Father: {fileID: 0}
2395
+ m_RootOrder: 1
2396
+ m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
2397
+ --- !u!108 &705507994
2398
+ Light:
2399
+ m_ObjectHideFlags: 0
2400
+ m_CorrespondingSourceObject: {fileID: 0}
2401
+ m_PrefabInstance: {fileID: 0}
2402
+ m_PrefabAsset: {fileID: 0}
2403
+ m_GameObject: {fileID: 705507993}
2404
+ m_Enabled: 1
2405
+ serializedVersion: 10
2406
+ m_Type: 1
2407
+ m_Shape: 0
2408
+ m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1}
2409
+ m_Intensity: 1
2410
+ m_Range: 10
2411
+ m_SpotAngle: 30
2412
+ m_InnerSpotAngle: 21.80208
2413
+ m_CookieSize: 10
2414
+ m_Shadows:
2415
+ m_Type: 2
2416
+ m_Resolution: -1
2417
+ m_CustomResolution: -1
2418
+ m_Strength: 1
2419
+ m_Bias: 0.05
2420
+ m_NormalBias: 0.4
2421
+ m_NearPlane: 0.2
2422
+ m_CullingMatrixOverride:
2423
+ e00: 1
2424
+ e01: 0
2425
+ e02: 0
2426
+ e03: 0
2427
+ e10: 0
2428
+ e11: 1
2429
+ e12: 0
2430
+ e13: 0
2431
+ e20: 0
2432
+ e21: 0
2433
+ e22: 1
2434
+ e23: 0
2435
+ e30: 0
2436
+ e31: 0
2437
+ e32: 0
2438
+ e33: 1
2439
+ m_UseCullingMatrixOverride: 0
2440
+ m_Cookie: {fileID: 0}
2441
+ m_DrawHalo: 0
2442
+ m_Flare: {fileID: 0}
2443
+ m_RenderMode: 0
2444
+ m_CullingMask:
2445
+ serializedVersion: 2
2446
+ m_Bits: 4294967295
2447
+ m_RenderingLayerMask: 1
2448
+ m_Lightmapping: 4
2449
+ m_LightShadowCasterMode: 0
2450
+ m_AreaSize: {x: 1, y: 1}
2451
+ m_BounceIntensity: 1
2452
+ m_ColorTemperature: 6570
2453
+ m_UseColorTemperature: 0
2454
+ m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
2455
+ m_UseBoundingSphereOverride: 0
2456
+ m_UseViewFrustumForShadowCasterCull: 1
2457
+ m_ShadowRadius: 0
2458
+ m_ShadowAngle: 0
2459
+ `;
2460
+ }
2461
+ try {
2462
+ import_fs7.writeFileSync(output_path, yaml, "utf-8");
2463
+ } catch (err) {
2464
+ return {
2465
+ success: false,
2466
+ output_path,
2467
+ error: `Failed to write scene file: ${err instanceof Error ? err.message : String(err)}`
2468
+ };
2469
+ }
2470
+ const metaContent = `fileFormatVersion: 2
2471
+ guid: ${guid}
2472
+ DefaultImporter:
2473
+ externalObjects: {}
2474
+ userData:
2475
+ assetBundleName:
2476
+ assetBundleVariant:
2477
+ `;
2478
+ const metaPath = output_path + ".meta";
2479
+ try {
2480
+ import_fs7.writeFileSync(metaPath, metaContent, "utf-8");
2481
+ } catch (err) {
2482
+ try {
2483
+ const fs = require("fs");
2484
+ fs.unlinkSync(output_path);
2485
+ } catch {}
2486
+ return {
2487
+ success: false,
2488
+ output_path,
2489
+ error: `Failed to write .meta file: ${err instanceof Error ? err.message : String(err)}`
2490
+ };
2491
+ }
2492
+ return {
2493
+ success: true,
2494
+ output_path,
2495
+ scene_guid: guid,
2496
+ meta_path: metaPath
2497
+ };
2498
+ }
2499
+ })