@akiojin/unity-mcp-server 2.40.2 → 2.40.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 +21 -0
- package/bin/unity-mcp-server +1 -1
- package/package.json +1 -1
- package/src/core/codeIndex.js +64 -15
- package/src/core/server.js +3 -34
- package/src/handlers/analysis/AnalyzeSceneContentsToolHandler.js +27 -24
- package/src/handlers/analysis/FindByComponentToolHandler.js +4 -1
- package/src/handlers/analysis/GetAnimatorStateToolHandler.js +5 -5
- package/src/handlers/analysis/GetComponentValuesToolHandler.js +4 -1
- package/src/handlers/analysis/GetGameObjectDetailsToolHandler.js +27 -24
- package/src/handlers/analysis/GetInputActionsStateToolHandler.js +5 -5
- package/src/handlers/analysis/GetObjectReferencesToolHandler.js +4 -1
- package/src/handlers/asset/AssetDatabaseManageToolHandler.js +24 -6
- package/src/handlers/asset/AssetDependencyAnalyzeToolHandler.js +21 -11
- package/src/handlers/asset/AssetImportSettingsManageToolHandler.js +7 -7
- package/src/handlers/asset/AssetMaterialCreateToolHandler.js +78 -81
- package/src/handlers/asset/AssetMaterialModifyToolHandler.js +57 -61
- package/src/handlers/asset/AssetPrefabCreateToolHandler.js +61 -64
- package/src/handlers/asset/AssetPrefabExitModeToolHandler.js +9 -13
- package/src/handlers/asset/AssetPrefabInstantiateToolHandler.js +110 -116
- package/src/handlers/asset/AssetPrefabModifyToolHandler.js +58 -58
- package/src/handlers/asset/AssetPrefabOpenToolHandler.js +7 -5
- package/src/handlers/asset/AssetPrefabSaveToolHandler.js +13 -6
- package/src/handlers/compilation/CompilationGetStateToolHandler.js +4 -3
- package/src/handlers/component/ComponentAddToolHandler.js +2 -2
- package/src/handlers/component/ComponentGetTypesToolHandler.js +17 -21
- package/src/handlers/component/ComponentListToolHandler.js +5 -3
- package/src/handlers/component/ComponentModifyToolHandler.js +3 -3
- package/src/handlers/component/ComponentRemoveToolHandler.js +2 -2
- package/src/handlers/console/ConsoleClearToolHandler.js +36 -46
- package/src/handlers/editor/EditorLayersManageToolHandler.js +7 -6
- package/src/handlers/editor/EditorTagsManageToolHandler.js +20 -11
- package/src/handlers/editor/EditorToolsManageToolHandler.js +2 -2
- package/src/handlers/editor/EditorWindowsManageToolHandler.js +6 -5
- package/src/handlers/gameobject/GameObjectCreateToolHandler.js +62 -66
- package/src/handlers/gameobject/GameObjectDeleteToolHandler.js +9 -9
- package/src/handlers/gameobject/GameObjectFindToolHandler.js +13 -11
- package/src/handlers/gameobject/GameObjectGetHierarchyToolHandler.js +22 -16
- package/src/handlers/input/InputActionAddToolHandler.js +2 -2
- package/src/handlers/input/InputActionMapCreateToolHandler.js +2 -2
- package/src/handlers/input/InputActionMapRemoveToolHandler.js +2 -2
- package/src/handlers/input/InputActionRemoveToolHandler.js +2 -2
- package/src/handlers/input/InputBindingAddToolHandler.js +2 -2
- package/src/handlers/input/InputBindingCompositeCreateToolHandler.js +2 -2
- package/src/handlers/input/InputBindingRemoveAllToolHandler.js +2 -2
- package/src/handlers/input/InputBindingRemoveToolHandler.js +2 -2
- package/src/handlers/input/InputControlSchemesManageToolHandler.js +2 -2
- package/src/handlers/package/PackageManagerToolHandler.js +41 -44
- package/src/handlers/package/RegistryConfigToolHandler.js +28 -7
- package/src/handlers/playmode/PlaymodeGetStateToolHandler.js +12 -16
- package/src/handlers/playmode/PlaymodePauseToolHandler.js +8 -12
- package/src/handlers/playmode/PlaymodeWaitForStateToolHandler.js +6 -3
- package/src/handlers/scene/GetSceneInfoToolHandler.js +11 -11
- package/src/handlers/scene/SceneCreateToolHandler.js +28 -31
- package/src/handlers/scene/SceneListToolHandler.js +21 -24
- package/src/handlers/scene/SceneLoadToolHandler.js +27 -29
- package/src/handlers/scene/SceneSaveToolHandler.js +19 -22
- package/src/handlers/screenshot/ScreenshotCaptureToolHandler.js +88 -66
- package/src/handlers/script/CodeIndexStatusToolHandler.js +4 -3
- package/src/handlers/script/CodeIndexUpdateToolHandler.js +24 -14
- package/src/handlers/script/ScriptCreateClassToolHandler.js +44 -9
- package/src/handlers/script/ScriptPackagesListToolHandler.js +91 -91
- package/src/handlers/script/ScriptRefactorRenameToolHandler.js +80 -71
- package/src/handlers/script/ScriptRemoveSymbolToolHandler.js +21 -7
- package/src/handlers/script/ScriptSearchToolHandler.js +299 -266
- package/src/handlers/script/ScriptSymbolsGetToolHandler.js +88 -79
- package/src/handlers/settings/SettingsGetToolHandler.js +28 -13
- package/src/handlers/settings/SettingsUpdateToolHandler.js +20 -6
- package/src/handlers/ui/UIClickElementToolHandler.js +87 -96
- package/src/handlers/ui/UIFindElementsToolHandler.js +45 -55
- package/src/handlers/ui/UIGetElementStateToolHandler.js +35 -43
- package/src/handlers/ui/UISetElementValueToolHandler.js +42 -49
- package/src/handlers/ui/UISimulateInputToolHandler.js +134 -136
- package/src/handlers/video/VideoCaptureForToolHandler.js +24 -7
- package/src/lsp/LspRpcClient.js +24 -12
- package/src/tools/analysis/analyzeSceneContents.js +85 -85
- package/src/tools/analysis/findByComponent.js +73 -73
- package/src/tools/analysis/getAnimatorState.js +287 -287
- package/src/tools/analysis/getComponentValues.js +161 -161
- package/src/tools/analysis/getGameObjectDetails.js +138 -138
- package/src/tools/analysis/getInputActionsState.js +291 -291
- package/src/tools/analysis/getObjectReferences.js +72 -72
- package/src/tools/input/inputActionsEditor.js +522 -474
- package/src/tools/scene/createScene.js +98 -97
- package/src/tools/scene/getSceneInfo.js +82 -81
- package/src/tools/scene/listScenes.js +70 -69
- package/src/tools/scene/loadScene.js +108 -106
- package/src/tools/scene/saveScene.js +78 -77
- package/src/tools/system/ping.js +9 -12
- package/src/utils/validators.js +2 -2
|
@@ -4,93 +4,102 @@ import { BaseToolHandler } from '../base/BaseToolHandler.js';
|
|
|
4
4
|
import { ProjectInfoProvider } from '../../core/projectInfo.js';
|
|
5
5
|
|
|
6
6
|
export class ScriptSymbolsGetToolHandler extends BaseToolHandler {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
7
|
+
constructor(unityConnection) {
|
|
8
|
+
super(
|
|
9
|
+
'script_symbols_get',
|
|
10
|
+
'FIRST STEP: Identify symbols (classes, methods, fields, properties) with spans before any edit. Path must start with Assets/ or Packages/. Use this to scope changes to a single symbol and avoid line-based edits. Returns line/column positions and container names (helpful to build container namePath like Outer/Nested/Member).',
|
|
11
|
+
{
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
path: {
|
|
15
|
+
type: 'string',
|
|
16
|
+
description:
|
|
17
|
+
'Project-relative .cs path under Assets/ or Packages/ (e.g., Packages/unity-mcp-server/Editor/Foo.cs). Do NOT prefix repository folders (e.g., UnityMCPServer/…).'
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
required: ['path']
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
this.unityConnection = unityConnection;
|
|
24
|
+
this.projectInfo = new ProjectInfoProvider(unityConnection);
|
|
25
|
+
}
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
validate(params) {
|
|
28
|
+
super.validate(params);
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
const { path } = params;
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
if (!path || path.trim() === '') {
|
|
33
|
+
throw new Error('path cannot be empty');
|
|
34
|
+
}
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
36
|
+
// Check for .cs extension
|
|
37
|
+
if (!path.endsWith('.cs')) {
|
|
38
|
+
throw new Error('Only .cs files are supported');
|
|
39
39
|
}
|
|
40
|
+
}
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
async execute(params) {
|
|
43
|
+
// Normalize to project-relative path (strip repo-root prefixes if provided)
|
|
44
|
+
const rawPath = String(params.path || '').replace(/\\/g, '/');
|
|
45
|
+
const ai = rawPath.indexOf('Assets/');
|
|
46
|
+
const pi = rawPath.indexOf('Packages/');
|
|
47
|
+
const cut = ai >= 0 && pi >= 0 ? Math.min(ai, pi) : ai >= 0 ? ai : pi;
|
|
48
|
+
const relPath = cut >= 0 ? rawPath.substring(cut) : rawPath;
|
|
48
49
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
50
|
+
try {
|
|
51
|
+
const info = await this.projectInfo.get();
|
|
52
|
+
if (!relPath.startsWith('Assets/') && !relPath.startsWith('Packages/')) {
|
|
53
|
+
return { error: 'Path must be under Assets/ or Packages/' };
|
|
54
|
+
}
|
|
55
|
+
const abs = path.join(info.projectRoot, relPath);
|
|
56
|
+
const st = await fs.stat(abs).catch(() => null);
|
|
57
|
+
if (!st || !st.isFile()) return { error: 'File not found', path: relPath };
|
|
58
|
+
const { LspRpcClient } = await import('../../lsp/LspRpcClient.js');
|
|
59
|
+
const lsp = new LspRpcClient(info.projectRoot);
|
|
60
|
+
const uri = 'file://' + abs.replace(/\\\\/g, '/');
|
|
61
|
+
const res = await lsp.request('textDocument/documentSymbol', { textDocument: { uri } });
|
|
62
|
+
const docSymbols = res?.result ?? res ?? [];
|
|
63
|
+
const list = [];
|
|
64
|
+
const visit = (s, container) => {
|
|
65
|
+
const start = s.range?.start || s.selectionRange?.start || {};
|
|
66
|
+
list.push({
|
|
67
|
+
name: s.name || '',
|
|
68
|
+
kind: this.mapKind(s.kind),
|
|
69
|
+
container: container || null,
|
|
70
|
+
namespace: null,
|
|
71
|
+
startLine: (start.line ?? 0) + 1,
|
|
72
|
+
startColumn: (start.character ?? 0) + 1,
|
|
73
|
+
endLine: (start.line ?? 0) + 1,
|
|
74
|
+
endColumn: (start.character ?? 0) + 1
|
|
75
|
+
});
|
|
76
|
+
if (Array.isArray(s.children)) for (const c of s.children) visit(c, s.name || container);
|
|
77
|
+
};
|
|
78
|
+
if (Array.isArray(docSymbols)) for (const s of docSymbols) visit(s, null);
|
|
79
|
+
return { success: true, path: relPath, symbols: list };
|
|
80
|
+
} catch (e) {
|
|
81
|
+
return { error: e.message || 'Failed to get symbols' };
|
|
82
82
|
}
|
|
83
|
+
}
|
|
83
84
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
85
|
+
mapKind(k) {
|
|
86
|
+
switch (k) {
|
|
87
|
+
case 5:
|
|
88
|
+
return 'class';
|
|
89
|
+
case 23:
|
|
90
|
+
return 'struct';
|
|
91
|
+
case 11:
|
|
92
|
+
return 'interface';
|
|
93
|
+
case 10:
|
|
94
|
+
return 'enum';
|
|
95
|
+
case 6:
|
|
96
|
+
return 'method';
|
|
97
|
+
case 7:
|
|
98
|
+
return 'property';
|
|
99
|
+
case 8:
|
|
100
|
+
return 'field';
|
|
101
|
+
default:
|
|
102
|
+
return undefined;
|
|
95
103
|
}
|
|
104
|
+
}
|
|
96
105
|
}
|
|
@@ -13,19 +13,23 @@ export class SettingsGetToolHandler extends BaseToolHandler {
|
|
|
13
13
|
properties: {
|
|
14
14
|
includePlayer: {
|
|
15
15
|
type: 'boolean',
|
|
16
|
-
description:
|
|
16
|
+
description:
|
|
17
|
+
'Include player settings (company/product name, version, etc.) (default: true).'
|
|
17
18
|
},
|
|
18
19
|
includeGraphics: {
|
|
19
20
|
type: 'boolean',
|
|
20
|
-
description:
|
|
21
|
+
description:
|
|
22
|
+
'Include graphics settings (color space, render pipeline, etc.) (default: false).'
|
|
21
23
|
},
|
|
22
24
|
includeQuality: {
|
|
23
25
|
type: 'boolean',
|
|
24
|
-
description:
|
|
26
|
+
description:
|
|
27
|
+
'Include quality settings (levels, anti-aliasing, shadows, etc.) (default: false).'
|
|
25
28
|
},
|
|
26
29
|
includePhysics: {
|
|
27
30
|
type: 'boolean',
|
|
28
|
-
description:
|
|
31
|
+
description:
|
|
32
|
+
'Include 3D physics settings (gravity, solver iterations, etc.) (default: false).'
|
|
29
33
|
},
|
|
30
34
|
includePhysics2D: {
|
|
31
35
|
type: 'boolean',
|
|
@@ -33,11 +37,13 @@ export class SettingsGetToolHandler extends BaseToolHandler {
|
|
|
33
37
|
},
|
|
34
38
|
includeAudio: {
|
|
35
39
|
type: 'boolean',
|
|
36
|
-
description:
|
|
40
|
+
description:
|
|
41
|
+
'Include audio settings (speaker mode, DSP buffer, volume, etc.) (default: false).'
|
|
37
42
|
},
|
|
38
43
|
includeTime: {
|
|
39
44
|
type: 'boolean',
|
|
40
|
-
description:
|
|
45
|
+
description:
|
|
46
|
+
'Include time settings (fixed timestep, time scale, etc.) (default: false).'
|
|
41
47
|
},
|
|
42
48
|
includeInputManager: {
|
|
43
49
|
type: 'boolean',
|
|
@@ -45,11 +51,13 @@ export class SettingsGetToolHandler extends BaseToolHandler {
|
|
|
45
51
|
},
|
|
46
52
|
includeEditor: {
|
|
47
53
|
type: 'boolean',
|
|
48
|
-
description:
|
|
54
|
+
description:
|
|
55
|
+
'Include editor settings (Unity Remote, serialization mode, etc.) (default: false).'
|
|
49
56
|
},
|
|
50
57
|
includeBuild: {
|
|
51
58
|
type: 'boolean',
|
|
52
|
-
description:
|
|
59
|
+
description:
|
|
60
|
+
'Include build settings (scenes in build, build target, etc.) (default: false).'
|
|
53
61
|
},
|
|
54
62
|
includeTags: {
|
|
55
63
|
type: 'boolean',
|
|
@@ -59,7 +67,7 @@ export class SettingsGetToolHandler extends BaseToolHandler {
|
|
|
59
67
|
required: []
|
|
60
68
|
}
|
|
61
69
|
);
|
|
62
|
-
|
|
70
|
+
|
|
63
71
|
this.unityConnection = unityConnection;
|
|
64
72
|
}
|
|
65
73
|
|
|
@@ -71,10 +79,17 @@ export class SettingsGetToolHandler extends BaseToolHandler {
|
|
|
71
79
|
validate(params) {
|
|
72
80
|
// All parameters are optional booleans with defaults, no special validation needed
|
|
73
81
|
const booleanParams = [
|
|
74
|
-
'includePlayer',
|
|
75
|
-
'
|
|
76
|
-
'
|
|
77
|
-
'
|
|
82
|
+
'includePlayer',
|
|
83
|
+
'includeGraphics',
|
|
84
|
+
'includeQuality',
|
|
85
|
+
'includePhysics',
|
|
86
|
+
'includePhysics2D',
|
|
87
|
+
'includeAudio',
|
|
88
|
+
'includeTime',
|
|
89
|
+
'includeInputManager',
|
|
90
|
+
'includeEditor',
|
|
91
|
+
'includeBuild',
|
|
92
|
+
'includeTags'
|
|
78
93
|
];
|
|
79
94
|
|
|
80
95
|
for (const param of booleanParams) {
|
|
@@ -110,14 +110,18 @@ export class SettingsUpdateToolHandler extends BaseToolHandler {
|
|
|
110
110
|
enum: [0, 2, 4, 8],
|
|
111
111
|
description: 'Anti-aliasing samples'
|
|
112
112
|
},
|
|
113
|
-
shadowDistance: {
|
|
113
|
+
shadowDistance: {
|
|
114
|
+
type: 'number',
|
|
115
|
+
minimum: 0,
|
|
116
|
+
description: 'Shadow rendering distance'
|
|
117
|
+
}
|
|
114
118
|
}
|
|
115
119
|
}
|
|
116
120
|
},
|
|
117
121
|
required: ['confirmChanges']
|
|
118
122
|
}
|
|
119
123
|
);
|
|
120
|
-
|
|
124
|
+
|
|
121
125
|
this.unityConnection = unityConnection;
|
|
122
126
|
}
|
|
123
127
|
|
|
@@ -129,13 +133,23 @@ export class SettingsUpdateToolHandler extends BaseToolHandler {
|
|
|
129
133
|
validate(params) {
|
|
130
134
|
// Require explicit confirmation
|
|
131
135
|
if (!params.confirmChanges) {
|
|
132
|
-
throw new Error(
|
|
136
|
+
throw new Error(
|
|
137
|
+
'confirmChanges must be set to true to update settings. This is a safety measure to prevent accidental changes.'
|
|
138
|
+
);
|
|
133
139
|
}
|
|
134
140
|
|
|
135
141
|
// Check that at least one settings category is provided
|
|
136
|
-
const settingsCategories = [
|
|
142
|
+
const settingsCategories = [
|
|
143
|
+
'player',
|
|
144
|
+
'graphics',
|
|
145
|
+
'physics',
|
|
146
|
+
'physics2D',
|
|
147
|
+
'audio',
|
|
148
|
+
'time',
|
|
149
|
+
'quality'
|
|
150
|
+
];
|
|
137
151
|
const hasSettings = settingsCategories.some(cat => params[cat] !== undefined);
|
|
138
|
-
|
|
152
|
+
|
|
139
153
|
if (!hasSettings) {
|
|
140
154
|
throw new Error('At least one settings category must be provided to update');
|
|
141
155
|
}
|
|
@@ -261,7 +275,7 @@ export class SettingsUpdateToolHandler extends BaseToolHandler {
|
|
|
261
275
|
safetyCheckExample: {
|
|
262
276
|
description: 'Example showing safety check (will fail)',
|
|
263
277
|
params: {
|
|
264
|
-
confirmChanges: false,
|
|
278
|
+
confirmChanges: false, // This will trigger safety check
|
|
265
279
|
player: {
|
|
266
280
|
productName: 'Accidental Change'
|
|
267
281
|
}
|
|
@@ -1,110 +1,101 @@
|
|
|
1
1
|
import { BaseToolHandler } from '../base/BaseToolHandler.js';
|
|
2
2
|
|
|
3
3
|
export class UIClickElementToolHandler extends BaseToolHandler {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
clickType: {
|
|
16
|
-
type: 'string',
|
|
17
|
-
enum: ['left', 'right', 'middle'],
|
|
18
|
-
|
|
19
|
-
description: 'Type of click (left, right, middle)'
|
|
20
|
-
},
|
|
21
|
-
holdDuration: {
|
|
22
|
-
type: 'number',
|
|
23
|
-
|
|
24
|
-
minimum: 0,
|
|
25
|
-
maximum: 10000,
|
|
26
|
-
description: 'Duration to hold click in milliseconds'
|
|
27
|
-
},
|
|
28
|
-
position: {
|
|
29
|
-
type: 'object',
|
|
30
|
-
properties: {
|
|
31
|
-
x: {
|
|
32
|
-
type: 'number',
|
|
33
|
-
minimum: 0,
|
|
34
|
-
maximum: 1,
|
|
35
|
-
description: 'X position within element (0-1)'
|
|
36
|
-
},
|
|
37
|
-
y: {
|
|
38
|
-
type: 'number',
|
|
39
|
-
minimum: 0,
|
|
40
|
-
maximum: 1,
|
|
41
|
-
description: 'Y position within element (0-1)'
|
|
42
|
-
}
|
|
43
|
-
},
|
|
44
|
-
description: 'Specific position within element to click'
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
required: ['elementPath']
|
|
48
|
-
}
|
|
49
|
-
);
|
|
50
|
-
this.unityConnection = unityConnection;
|
|
51
|
-
}
|
|
4
|
+
constructor(unityConnection) {
|
|
5
|
+
super('ui_click_element', 'Simulate clicking on UI elements', {
|
|
6
|
+
type: 'object',
|
|
7
|
+
properties: {
|
|
8
|
+
elementPath: {
|
|
9
|
+
type: 'string',
|
|
10
|
+
description: 'Full hierarchy path to the UI element'
|
|
11
|
+
},
|
|
12
|
+
clickType: {
|
|
13
|
+
type: 'string',
|
|
14
|
+
enum: ['left', 'right', 'middle'],
|
|
52
15
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
// Validate clickType enum
|
|
58
|
-
if (params.clickType && !['left', 'right', 'middle'].includes(params.clickType)) {
|
|
59
|
-
throw new Error('clickType must be one of: left, right, middle');
|
|
60
|
-
}
|
|
16
|
+
description: 'Type of click (left, right, middle)'
|
|
17
|
+
},
|
|
18
|
+
holdDuration: {
|
|
19
|
+
type: 'number',
|
|
61
20
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
21
|
+
minimum: 0,
|
|
22
|
+
maximum: 10000,
|
|
23
|
+
description: 'Duration to hold click in milliseconds'
|
|
24
|
+
},
|
|
25
|
+
position: {
|
|
26
|
+
type: 'object',
|
|
27
|
+
properties: {
|
|
28
|
+
x: {
|
|
29
|
+
type: 'number',
|
|
30
|
+
minimum: 0,
|
|
31
|
+
maximum: 1,
|
|
32
|
+
description: 'X position within element (0-1)'
|
|
33
|
+
},
|
|
34
|
+
y: {
|
|
35
|
+
type: 'number',
|
|
36
|
+
minimum: 0,
|
|
37
|
+
maximum: 1,
|
|
38
|
+
description: 'Y position within element (0-1)'
|
|
67
39
|
}
|
|
40
|
+
},
|
|
41
|
+
description: 'Specific position within element to click'
|
|
68
42
|
}
|
|
43
|
+
},
|
|
44
|
+
required: ['elementPath']
|
|
45
|
+
});
|
|
46
|
+
this.unityConnection = unityConnection;
|
|
47
|
+
}
|
|
69
48
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
throw new Error('position.y must be a number');
|
|
78
|
-
}
|
|
79
|
-
if (pos.x !== undefined && (pos.x < 0 || pos.x > 1)) {
|
|
80
|
-
throw new Error('position.x must be between 0 and 1');
|
|
81
|
-
}
|
|
82
|
-
if (pos.y !== undefined && (pos.y < 0 || pos.y > 1)) {
|
|
83
|
-
throw new Error('position.y must be between 0 and 1');
|
|
84
|
-
}
|
|
85
|
-
}
|
|
49
|
+
validate(params) {
|
|
50
|
+
// Call parent validation for required fields
|
|
51
|
+
super.validate(params);
|
|
52
|
+
|
|
53
|
+
// Validate clickType enum
|
|
54
|
+
if (params.clickType && !['left', 'right', 'middle'].includes(params.clickType)) {
|
|
55
|
+
throw new Error('clickType must be one of: left, right, middle');
|
|
86
56
|
}
|
|
87
57
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
58
|
+
// Validate holdDuration range
|
|
59
|
+
if (params.holdDuration !== undefined) {
|
|
60
|
+
const duration = params.holdDuration;
|
|
61
|
+
if (typeof duration !== 'number' || duration < 0 || duration > 10000) {
|
|
62
|
+
throw new Error('holdDuration must be between 0 and 10000 milliseconds');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
95
65
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
66
|
+
// Validate position object
|
|
67
|
+
if (params.position) {
|
|
68
|
+
const pos = params.position;
|
|
69
|
+
if (pos.x !== undefined && typeof pos.x !== 'number') {
|
|
70
|
+
throw new Error('position.x must be a number');
|
|
71
|
+
}
|
|
72
|
+
if (pos.y !== undefined && typeof pos.y !== 'number') {
|
|
73
|
+
throw new Error('position.y must be a number');
|
|
74
|
+
}
|
|
75
|
+
if (pos.x !== undefined && (pos.x < 0 || pos.x > 1)) {
|
|
76
|
+
throw new Error('position.x must be between 0 and 1');
|
|
77
|
+
}
|
|
78
|
+
if (pos.y !== undefined && (pos.y < 0 || pos.y > 1)) {
|
|
79
|
+
throw new Error('position.y must be between 0 and 1');
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
100
83
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
clickType,
|
|
104
|
-
holdDuration,
|
|
105
|
-
position
|
|
106
|
-
});
|
|
84
|
+
async execute(params) {
|
|
85
|
+
const { elementPath, clickType = 'left', holdDuration = 0, position } = params;
|
|
107
86
|
|
|
108
|
-
|
|
87
|
+
// Ensure connected
|
|
88
|
+
if (!this.unityConnection.isConnected()) {
|
|
89
|
+
await this.unityConnection.connect();
|
|
109
90
|
}
|
|
110
|
-
|
|
91
|
+
|
|
92
|
+
const result = await this.unityConnection.sendCommand('click_ui_element', {
|
|
93
|
+
elementPath,
|
|
94
|
+
clickType,
|
|
95
|
+
holdDuration,
|
|
96
|
+
position
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -1,63 +1,53 @@
|
|
|
1
1
|
import { BaseToolHandler } from '../base/BaseToolHandler.js';
|
|
2
2
|
|
|
3
3
|
export class UIFindElementsToolHandler extends BaseToolHandler {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
canvasFilter: {
|
|
28
|
-
type: 'string',
|
|
29
|
-
description: 'Filter by parent Canvas name.'
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
required: []
|
|
33
|
-
}
|
|
34
|
-
);
|
|
35
|
-
this.unityConnection = unityConnection;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async execute(params = {}) {
|
|
39
|
-
const {
|
|
40
|
-
elementType,
|
|
41
|
-
tagFilter,
|
|
42
|
-
namePattern,
|
|
43
|
-
includeInactive = false,
|
|
44
|
-
canvasFilter
|
|
45
|
-
} = params;
|
|
46
|
-
|
|
47
|
-
// Ensure connected
|
|
48
|
-
if (!this.unityConnection.isConnected()) {
|
|
49
|
-
await this.unityConnection.connect();
|
|
4
|
+
constructor(unityConnection) {
|
|
5
|
+
super('ui_find_elements', 'Find UI elements by component type, tag, or name pattern.', {
|
|
6
|
+
type: 'object',
|
|
7
|
+
properties: {
|
|
8
|
+
elementType: {
|
|
9
|
+
type: 'string',
|
|
10
|
+
description: 'UI component type (e.g., Button, Toggle, Slider).'
|
|
11
|
+
},
|
|
12
|
+
tagFilter: {
|
|
13
|
+
type: 'string',
|
|
14
|
+
description: 'Filter by GameObject tag.'
|
|
15
|
+
},
|
|
16
|
+
namePattern: {
|
|
17
|
+
type: 'string',
|
|
18
|
+
description: 'Search by name substring or regex.'
|
|
19
|
+
},
|
|
20
|
+
includeInactive: {
|
|
21
|
+
type: 'boolean',
|
|
22
|
+
description: 'If true, include inactive UI elements.'
|
|
23
|
+
},
|
|
24
|
+
canvasFilter: {
|
|
25
|
+
type: 'string',
|
|
26
|
+
description: 'Filter by parent Canvas name.'
|
|
50
27
|
}
|
|
28
|
+
},
|
|
29
|
+
required: []
|
|
30
|
+
});
|
|
31
|
+
this.unityConnection = unityConnection;
|
|
32
|
+
}
|
|
51
33
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
tagFilter,
|
|
55
|
-
namePattern,
|
|
56
|
-
includeInactive,
|
|
57
|
-
canvasFilter
|
|
58
|
-
});
|
|
34
|
+
async execute(params = {}) {
|
|
35
|
+
const { elementType, tagFilter, namePattern, includeInactive = false, canvasFilter } = params;
|
|
59
36
|
|
|
60
|
-
|
|
61
|
-
|
|
37
|
+
// Ensure connected
|
|
38
|
+
if (!this.unityConnection.isConnected()) {
|
|
39
|
+
await this.unityConnection.connect();
|
|
62
40
|
}
|
|
41
|
+
|
|
42
|
+
const result = await this.unityConnection.sendCommand('find_ui_elements', {
|
|
43
|
+
elementType,
|
|
44
|
+
tagFilter,
|
|
45
|
+
namePattern,
|
|
46
|
+
includeInactive,
|
|
47
|
+
canvasFilter
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Return the result for the BaseToolHandler to format
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
63
53
|
}
|