@akiojin/unity-mcp-server 2.14.14
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/LICENSE +21 -0
- package/README.md +206 -0
- package/bin/unity-mcp-server +2 -0
- package/package.json +73 -0
- package/src/core/codeIndex.js +163 -0
- package/src/core/codeIndexDb.js +96 -0
- package/src/core/config.js +165 -0
- package/src/core/indexWatcher.js +52 -0
- package/src/core/projectInfo.js +111 -0
- package/src/core/server.js +294 -0
- package/src/core/unityConnection.js +426 -0
- package/src/handlers/analysis/AnalyzeSceneContentsToolHandler.js +35 -0
- package/src/handlers/analysis/FindByComponentToolHandler.js +20 -0
- package/src/handlers/analysis/GetAnimatorStateToolHandler.js +37 -0
- package/src/handlers/analysis/GetComponentValuesToolHandler.js +20 -0
- package/src/handlers/analysis/GetGameObjectDetailsToolHandler.js +35 -0
- package/src/handlers/analysis/GetInputActionsStateToolHandler.js +37 -0
- package/src/handlers/analysis/GetObjectReferencesToolHandler.js +20 -0
- package/src/handlers/asset/AssetDatabaseToolHandler.js +221 -0
- package/src/handlers/asset/AssetDependencyToolHandler.js +201 -0
- package/src/handlers/asset/AssetImportSettingsToolHandler.js +170 -0
- package/src/handlers/asset/CreateMaterialToolHandler.js +96 -0
- package/src/handlers/asset/CreatePrefabToolHandler.js +78 -0
- package/src/handlers/asset/ExitPrefabModeToolHandler.js +83 -0
- package/src/handlers/asset/InstantiatePrefabToolHandler.js +133 -0
- package/src/handlers/asset/ModifyMaterialToolHandler.js +76 -0
- package/src/handlers/asset/ModifyPrefabToolHandler.js +72 -0
- package/src/handlers/asset/OpenPrefabToolHandler.js +121 -0
- package/src/handlers/asset/SavePrefabToolHandler.js +106 -0
- package/src/handlers/base/BaseToolHandler.js +133 -0
- package/src/handlers/compilation/GetCompilationStateToolHandler.js +90 -0
- package/src/handlers/component/AddComponentToolHandler.js +126 -0
- package/src/handlers/component/GetComponentTypesToolHandler.js +100 -0
- package/src/handlers/component/ListComponentsToolHandler.js +85 -0
- package/src/handlers/component/ModifyComponentToolHandler.js +143 -0
- package/src/handlers/component/RemoveComponentToolHandler.js +108 -0
- package/src/handlers/console/ClearConsoleToolHandler.js +160 -0
- package/src/handlers/console/ReadConsoleToolHandler.js +276 -0
- package/src/handlers/editor/LayerManagementToolHandler.js +160 -0
- package/src/handlers/editor/SelectionToolHandler.js +141 -0
- package/src/handlers/editor/TagManagementToolHandler.js +129 -0
- package/src/handlers/editor/ToolManagementToolHandler.js +135 -0
- package/src/handlers/editor/WindowManagementToolHandler.js +125 -0
- package/src/handlers/gameobject/CreateGameObjectToolHandler.js +131 -0
- package/src/handlers/gameobject/DeleteGameObjectToolHandler.js +101 -0
- package/src/handlers/gameobject/FindGameObjectToolHandler.js +119 -0
- package/src/handlers/gameobject/GetHierarchyToolHandler.js +132 -0
- package/src/handlers/gameobject/ModifyGameObjectToolHandler.js +128 -0
- package/src/handlers/index.js +389 -0
- package/src/handlers/input/AddInputActionToolHandler.js +20 -0
- package/src/handlers/input/AddInputBindingToolHandler.js +20 -0
- package/src/handlers/input/CreateActionMapToolHandler.js +20 -0
- package/src/handlers/input/CreateCompositeBindingToolHandler.js +20 -0
- package/src/handlers/input/GamepadSimulationHandler.js +116 -0
- package/src/handlers/input/InputSystemHandler.js +80 -0
- package/src/handlers/input/KeyboardSimulationHandler.js +79 -0
- package/src/handlers/input/ManageControlSchemesToolHandler.js +20 -0
- package/src/handlers/input/MouseSimulationHandler.js +107 -0
- package/src/handlers/input/RemoveActionMapToolHandler.js +20 -0
- package/src/handlers/input/RemoveAllBindingsToolHandler.js +20 -0
- package/src/handlers/input/RemoveInputActionToolHandler.js +20 -0
- package/src/handlers/input/RemoveInputBindingToolHandler.js +20 -0
- package/src/handlers/input/TouchSimulationHandler.js +142 -0
- package/src/handlers/menu/ExecuteMenuItemToolHandler.js +304 -0
- package/src/handlers/package/PackageManagerToolHandler.js +248 -0
- package/src/handlers/package/RegistryConfigToolHandler.js +198 -0
- package/src/handlers/playmode/GetEditorStateToolHandler.js +81 -0
- package/src/handlers/playmode/PauseToolHandler.js +44 -0
- package/src/handlers/playmode/PlayToolHandler.js +91 -0
- package/src/handlers/playmode/StopToolHandler.js +77 -0
- package/src/handlers/playmode/WaitForEditorStateToolHandler.js +45 -0
- package/src/handlers/scene/CreateSceneToolHandler.js +91 -0
- package/src/handlers/scene/GetSceneInfoToolHandler.js +20 -0
- package/src/handlers/scene/ListScenesToolHandler.js +58 -0
- package/src/handlers/scene/LoadSceneToolHandler.js +92 -0
- package/src/handlers/scene/SaveSceneToolHandler.js +76 -0
- package/src/handlers/screenshot/AnalyzeScreenshotToolHandler.js +238 -0
- package/src/handlers/screenshot/CaptureScreenshotToolHandler.js +692 -0
- package/src/handlers/script/BuildCodeIndexToolHandler.js +163 -0
- package/src/handlers/script/ScriptCreateClassFileToolHandler.js +60 -0
- package/src/handlers/script/ScriptEditStructuredToolHandler.js +173 -0
- package/src/handlers/script/ScriptIndexStatusToolHandler.js +61 -0
- package/src/handlers/script/ScriptPackagesListToolHandler.js +103 -0
- package/src/handlers/script/ScriptReadToolHandler.js +106 -0
- package/src/handlers/script/ScriptRefactorRenameToolHandler.js +83 -0
- package/src/handlers/script/ScriptRefsFindToolHandler.js +144 -0
- package/src/handlers/script/ScriptRemoveSymbolToolHandler.js +79 -0
- package/src/handlers/script/ScriptSearchToolHandler.js +320 -0
- package/src/handlers/script/ScriptSymbolFindToolHandler.js +117 -0
- package/src/handlers/script/ScriptSymbolsGetToolHandler.js +96 -0
- package/src/handlers/settings/GetProjectSettingsToolHandler.js +161 -0
- package/src/handlers/settings/UpdateProjectSettingsToolHandler.js +272 -0
- package/src/handlers/system/GetCommandStatsToolHandler.js +25 -0
- package/src/handlers/system/PingToolHandler.js +53 -0
- package/src/handlers/system/RefreshAssetsToolHandler.js +45 -0
- package/src/handlers/ui/ClickUIElementToolHandler.js +110 -0
- package/src/handlers/ui/FindUIElementsToolHandler.js +63 -0
- package/src/handlers/ui/GetUIElementStateToolHandler.js +50 -0
- package/src/handlers/ui/SetUIElementValueToolHandler.js +49 -0
- package/src/handlers/ui/SimulateUIInputToolHandler.js +156 -0
- package/src/handlers/video/CaptureVideoForToolHandler.js +96 -0
- package/src/handlers/video/CaptureVideoStartToolHandler.js +38 -0
- package/src/handlers/video/CaptureVideoStatusToolHandler.js +30 -0
- package/src/handlers/video/CaptureVideoStopToolHandler.js +32 -0
- package/src/lsp/CSharpLspUtils.js +134 -0
- package/src/lsp/LspProcessManager.js +60 -0
- package/src/lsp/LspRpcClient.js +133 -0
- package/src/tools/analysis/analyzeSceneContents.js +100 -0
- package/src/tools/analysis/findByComponent.js +87 -0
- package/src/tools/analysis/getAnimatorState.js +326 -0
- package/src/tools/analysis/getComponentValues.js +182 -0
- package/src/tools/analysis/getGameObjectDetails.js +159 -0
- package/src/tools/analysis/getInputActionsState.js +329 -0
- package/src/tools/analysis/getObjectReferences.js +86 -0
- package/src/tools/input/inputActionsEditor.js +556 -0
- package/src/tools/scene/createScene.js +112 -0
- package/src/tools/scene/getSceneInfo.js +95 -0
- package/src/tools/scene/listScenes.js +82 -0
- package/src/tools/scene/loadScene.js +122 -0
- package/src/tools/scene/saveScene.js +91 -0
- package/src/tools/system/ping.js +72 -0
- package/src/tools/video/recordFor.js +31 -0
- package/src/tools/video/recordPlayMode.js +61 -0
- package/src/utils/csharpParse.js +88 -0
- package/src/utils/validators.js +90 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { BaseToolHandler } from '../base/BaseToolHandler.js';
|
|
2
|
+
|
|
3
|
+
export class CreatePrefabToolHandler extends BaseToolHandler {
|
|
4
|
+
constructor(unityConnection) {
|
|
5
|
+
super(
|
|
6
|
+
'create_prefab',
|
|
7
|
+
'Create a prefab from a GameObject path or create an empty prefab at a target asset path.',
|
|
8
|
+
{
|
|
9
|
+
type: 'object',
|
|
10
|
+
properties: {
|
|
11
|
+
gameObjectPath: {
|
|
12
|
+
type: 'string',
|
|
13
|
+
description: 'Scene path to convert (e.g., "/Root/Player"). Mutually exclusive with createFromTemplate.'
|
|
14
|
+
},
|
|
15
|
+
prefabPath: {
|
|
16
|
+
type: 'string',
|
|
17
|
+
description: 'Asset path for the prefab. Must start with Assets/ and end with .prefab.'
|
|
18
|
+
},
|
|
19
|
+
createFromTemplate: {
|
|
20
|
+
type: 'boolean',
|
|
21
|
+
description: 'If true, create an empty prefab (no source GameObject) (default: false).'
|
|
22
|
+
},
|
|
23
|
+
overwrite: {
|
|
24
|
+
type: 'boolean',
|
|
25
|
+
description: 'If true, overwrite existing prefab at the destination path (default: false).'
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
required: ['prefabPath']
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
this.unityConnection = unityConnection;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
validate(params) {
|
|
35
|
+
// Call parent validation for required fields
|
|
36
|
+
super.validate(params);
|
|
37
|
+
|
|
38
|
+
const { prefabPath, gameObjectPath, createFromTemplate } = params;
|
|
39
|
+
|
|
40
|
+
// Validate prefabPath format
|
|
41
|
+
if (!prefabPath.startsWith('Assets/') || !prefabPath.endsWith('.prefab')) {
|
|
42
|
+
throw new Error('prefabPath must start with Assets/ and end with .prefab');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Validate gameObjectPath when provided
|
|
46
|
+
if (gameObjectPath !== undefined && gameObjectPath === '') {
|
|
47
|
+
throw new Error('gameObjectPath cannot be empty when provided');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Validate mutually exclusive options
|
|
51
|
+
if (gameObjectPath && createFromTemplate) {
|
|
52
|
+
throw new Error('Cannot specify both gameObjectPath and createFromTemplate');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async execute(params) {
|
|
57
|
+
const {
|
|
58
|
+
gameObjectPath,
|
|
59
|
+
prefabPath,
|
|
60
|
+
createFromTemplate = false,
|
|
61
|
+
overwrite = false
|
|
62
|
+
} = params;
|
|
63
|
+
|
|
64
|
+
// Ensure connected
|
|
65
|
+
if (!this.unityConnection.isConnected()) {
|
|
66
|
+
await this.unityConnection.connect();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const result = await this.unityConnection.sendCommand('create_prefab', {
|
|
70
|
+
gameObjectPath,
|
|
71
|
+
prefabPath,
|
|
72
|
+
createFromTemplate,
|
|
73
|
+
overwrite
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { BaseToolHandler } from '../base/BaseToolHandler.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Handler for exiting Unity's prefab mode
|
|
5
|
+
*/
|
|
6
|
+
export class ExitPrefabModeToolHandler extends BaseToolHandler {
|
|
7
|
+
constructor(unityConnection) {
|
|
8
|
+
super(
|
|
9
|
+
'exit_prefab_mode',
|
|
10
|
+
'Exit prefab mode and return to the main scene',
|
|
11
|
+
{
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
saveChanges: {
|
|
15
|
+
type: 'boolean',
|
|
16
|
+
description: 'Save changes before exiting (default: true)'
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
this.unityConnection = unityConnection;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Executes the exit prefab mode operation
|
|
27
|
+
* @param {Object} params - The validated input parameters
|
|
28
|
+
* @returns {Promise<Object>} The result of exiting prefab mode
|
|
29
|
+
*/
|
|
30
|
+
async execute(params) {
|
|
31
|
+
// Ensure connection to Unity
|
|
32
|
+
if (!this.unityConnection.isConnected()) {
|
|
33
|
+
await this.unityConnection.connect();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Default saveChanges to true
|
|
37
|
+
const executeParams = {
|
|
38
|
+
saveChanges: params.saveChanges !== undefined ? params.saveChanges : true
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// Send command to Unity
|
|
42
|
+
const response = await this.unityConnection.sendCommand('exit_prefab_mode', executeParams);
|
|
43
|
+
|
|
44
|
+
// Handle Unity response
|
|
45
|
+
if (response.error) {
|
|
46
|
+
throw new Error(response.error);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Return result
|
|
50
|
+
return {
|
|
51
|
+
success: response.success,
|
|
52
|
+
wasInPrefabMode: response.wasInPrefabMode,
|
|
53
|
+
message: response.message || 'Exited prefab mode',
|
|
54
|
+
...(response.changesSaved !== undefined && { changesSaved: response.changesSaved }),
|
|
55
|
+
...(response.prefabPath !== undefined && { prefabPath: response.prefabPath })
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Gets example usage for this tool
|
|
61
|
+
* @returns {Object} Example usage scenarios
|
|
62
|
+
*/
|
|
63
|
+
getExamples() {
|
|
64
|
+
return {
|
|
65
|
+
exitAndSave: {
|
|
66
|
+
description: 'Exit prefab mode and save changes',
|
|
67
|
+
params: {
|
|
68
|
+
saveChanges: true
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
exitWithoutSave: {
|
|
72
|
+
description: 'Exit prefab mode without saving changes',
|
|
73
|
+
params: {
|
|
74
|
+
saveChanges: false
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
exitDefault: {
|
|
78
|
+
description: 'Exit prefab mode (saves by default)',
|
|
79
|
+
params: {}
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { BaseToolHandler } from '../base/BaseToolHandler.js';
|
|
2
|
+
|
|
3
|
+
export class InstantiatePrefabToolHandler extends BaseToolHandler {
|
|
4
|
+
constructor(unityConnection) {
|
|
5
|
+
super(
|
|
6
|
+
'instantiate_prefab',
|
|
7
|
+
'Instantiate a prefab in the scene with optional transform, parent, and name override.',
|
|
8
|
+
{
|
|
9
|
+
type: 'object',
|
|
10
|
+
properties: {
|
|
11
|
+
prefabPath: {
|
|
12
|
+
type: 'string',
|
|
13
|
+
description: 'Asset path to the prefab. Must start with Assets/ and end with .prefab.'
|
|
14
|
+
},
|
|
15
|
+
position: {
|
|
16
|
+
type: 'object',
|
|
17
|
+
properties: {
|
|
18
|
+
x: { type: 'number' },
|
|
19
|
+
y: { type: 'number' },
|
|
20
|
+
z: { type: 'number' }
|
|
21
|
+
},
|
|
22
|
+
description: 'World position for the instance (requires x,y,z).'
|
|
23
|
+
},
|
|
24
|
+
rotation: {
|
|
25
|
+
type: 'object',
|
|
26
|
+
properties: {
|
|
27
|
+
x: { type: 'number' },
|
|
28
|
+
y: { type: 'number' },
|
|
29
|
+
z: { type: 'number' }
|
|
30
|
+
},
|
|
31
|
+
description: 'Euler rotation for the instance (x,y,z).'
|
|
32
|
+
},
|
|
33
|
+
parent: {
|
|
34
|
+
type: 'string',
|
|
35
|
+
description: 'Parent GameObject scene path (optional).'
|
|
36
|
+
},
|
|
37
|
+
name: {
|
|
38
|
+
type: 'string',
|
|
39
|
+
description: 'Override name for the instantiated object.'
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
required: ['prefabPath']
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
this.unityConnection = unityConnection;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
validate(params) {
|
|
49
|
+
// Call parent validation for required fields
|
|
50
|
+
super.validate(params);
|
|
51
|
+
|
|
52
|
+
const { prefabPath, parent, position, rotation } = params;
|
|
53
|
+
|
|
54
|
+
// Validate prefabPath format
|
|
55
|
+
if (!prefabPath.startsWith('Assets/') || !prefabPath.endsWith('.prefab')) {
|
|
56
|
+
throw new Error('prefabPath must start with Assets/ and end with .prefab');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Validate parent when provided
|
|
60
|
+
if (parent !== undefined && parent === '') {
|
|
61
|
+
throw new Error('parent cannot be empty when provided');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Validate position object when provided
|
|
65
|
+
if (position !== undefined) {
|
|
66
|
+
if (typeof position !== 'object' || position === null) {
|
|
67
|
+
throw new Error('position must be an object');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Check individual properties first for better error messages
|
|
71
|
+
if ('x' in position && typeof position.x !== 'number') {
|
|
72
|
+
throw new Error('position.x must be a number');
|
|
73
|
+
}
|
|
74
|
+
if ('y' in position && typeof position.y !== 'number') {
|
|
75
|
+
throw new Error('position.y must be a number');
|
|
76
|
+
}
|
|
77
|
+
if ('z' in position && typeof position.z !== 'number') {
|
|
78
|
+
throw new Error('position.z must be a number');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Then check for missing properties
|
|
82
|
+
if (!('x' in position) || !('y' in position) || !('z' in position)) {
|
|
83
|
+
throw new Error('position must have x, y, and z properties');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Validate rotation object when provided
|
|
88
|
+
if (rotation !== undefined) {
|
|
89
|
+
if (typeof rotation !== 'object' || rotation === null) {
|
|
90
|
+
throw new Error('rotation must be an object');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (!('x' in rotation) || !('y' in rotation) || !('z' in rotation)) {
|
|
94
|
+
throw new Error('rotation must have x, y, and z properties');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (typeof rotation.x !== 'number') {
|
|
98
|
+
throw new Error('rotation.x must be a number');
|
|
99
|
+
}
|
|
100
|
+
if (typeof rotation.y !== 'number') {
|
|
101
|
+
throw new Error('rotation.y must be a number');
|
|
102
|
+
}
|
|
103
|
+
if (typeof rotation.z !== 'number') {
|
|
104
|
+
throw new Error('rotation.z must be a number');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async execute(params) {
|
|
110
|
+
const {
|
|
111
|
+
prefabPath,
|
|
112
|
+
position,
|
|
113
|
+
rotation,
|
|
114
|
+
parent,
|
|
115
|
+
name
|
|
116
|
+
} = params;
|
|
117
|
+
|
|
118
|
+
// Ensure connected
|
|
119
|
+
if (!this.unityConnection.isConnected()) {
|
|
120
|
+
await this.unityConnection.connect();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const result = await this.unityConnection.sendCommand('instantiate_prefab', {
|
|
124
|
+
prefabPath,
|
|
125
|
+
position,
|
|
126
|
+
rotation,
|
|
127
|
+
parent,
|
|
128
|
+
name
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { BaseToolHandler } from '../base/BaseToolHandler.js';
|
|
2
|
+
|
|
3
|
+
export class ModifyMaterialToolHandler extends BaseToolHandler {
|
|
4
|
+
constructor(unityConnection) {
|
|
5
|
+
super(
|
|
6
|
+
'modify_material',
|
|
7
|
+
'Modify a material by updating property values and/or changing the shader.',
|
|
8
|
+
{
|
|
9
|
+
type: 'object',
|
|
10
|
+
properties: {
|
|
11
|
+
materialPath: {
|
|
12
|
+
type: 'string',
|
|
13
|
+
description: 'Asset path to the material. Must start with Assets/ and end with .mat.'
|
|
14
|
+
},
|
|
15
|
+
properties: {
|
|
16
|
+
type: 'object',
|
|
17
|
+
description: 'Property updates (e.g., {"_Color":[1,0,0,1], "_Metallic":0.5}).'
|
|
18
|
+
},
|
|
19
|
+
shader: {
|
|
20
|
+
type: 'string',
|
|
21
|
+
description: 'Optional: change the shader (e.g., Standard, Unlit/Color).'
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
required: ['materialPath', 'properties']
|
|
25
|
+
}
|
|
26
|
+
);
|
|
27
|
+
this.unityConnection = unityConnection;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
validate(params) {
|
|
31
|
+
// Call parent validation for required fields
|
|
32
|
+
super.validate(params);
|
|
33
|
+
|
|
34
|
+
const { materialPath, properties, shader } = params;
|
|
35
|
+
|
|
36
|
+
// Validate materialPath format
|
|
37
|
+
if (!materialPath.startsWith('Assets/') || !materialPath.endsWith('.mat')) {
|
|
38
|
+
throw new Error('materialPath must start with Assets/ and end with .mat');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Validate properties
|
|
42
|
+
if (typeof properties !== 'object' || properties === null || Array.isArray(properties)) {
|
|
43
|
+
throw new Error('properties must be an object');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (Object.keys(properties).length === 0) {
|
|
47
|
+
throw new Error('properties cannot be empty');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Validate shader when provided
|
|
51
|
+
if (shader !== undefined && shader === '') {
|
|
52
|
+
throw new Error('shader cannot be empty when provided');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async execute(params) {
|
|
57
|
+
const {
|
|
58
|
+
materialPath,
|
|
59
|
+
properties,
|
|
60
|
+
shader
|
|
61
|
+
} = params;
|
|
62
|
+
|
|
63
|
+
// Ensure connected
|
|
64
|
+
if (!this.unityConnection.isConnected()) {
|
|
65
|
+
await this.unityConnection.connect();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const result = await this.unityConnection.sendCommand('modify_material', {
|
|
69
|
+
materialPath,
|
|
70
|
+
properties,
|
|
71
|
+
shader
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { BaseToolHandler } from '../base/BaseToolHandler.js';
|
|
2
|
+
|
|
3
|
+
export class ModifyPrefabToolHandler extends BaseToolHandler {
|
|
4
|
+
constructor(unityConnection) {
|
|
5
|
+
super(
|
|
6
|
+
'modify_prefab',
|
|
7
|
+
'Modify an existing prefab by applying property changes (optionally to instances).',
|
|
8
|
+
{
|
|
9
|
+
type: 'object',
|
|
10
|
+
properties: {
|
|
11
|
+
prefabPath: {
|
|
12
|
+
type: 'string',
|
|
13
|
+
description: 'Asset path to the prefab. Must start with Assets/ and end with .prefab.'
|
|
14
|
+
},
|
|
15
|
+
modifications: {
|
|
16
|
+
type: 'object',
|
|
17
|
+
description: 'Key/value object of properties to modify on the prefab.'
|
|
18
|
+
},
|
|
19
|
+
applyToInstances: {
|
|
20
|
+
type: 'boolean',
|
|
21
|
+
description: 'If true, also apply to existing scene instances (default: true).'
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
required: ['prefabPath', 'modifications']
|
|
25
|
+
}
|
|
26
|
+
);
|
|
27
|
+
this.unityConnection = unityConnection;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
validate(params) {
|
|
31
|
+
// Call parent validation for required fields
|
|
32
|
+
super.validate(params);
|
|
33
|
+
|
|
34
|
+
const { prefabPath, modifications } = params;
|
|
35
|
+
|
|
36
|
+
// Validate prefabPath format
|
|
37
|
+
if (!prefabPath.startsWith('Assets/') || !prefabPath.endsWith('.prefab')) {
|
|
38
|
+
throw new Error('prefabPath must start with Assets/ and end with .prefab');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Validate modifications is object
|
|
42
|
+
if (typeof modifications !== 'object' || modifications === null || Array.isArray(modifications)) {
|
|
43
|
+
throw new Error('modifications must be an object');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Validate modifications is not empty
|
|
47
|
+
if (Object.keys(modifications).length === 0) {
|
|
48
|
+
throw new Error('modifications cannot be empty');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async execute(params) {
|
|
53
|
+
const {
|
|
54
|
+
prefabPath,
|
|
55
|
+
modifications,
|
|
56
|
+
applyToInstances = true
|
|
57
|
+
} = params;
|
|
58
|
+
|
|
59
|
+
// Ensure connected
|
|
60
|
+
if (!this.unityConnection.isConnected()) {
|
|
61
|
+
await this.unityConnection.connect();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const result = await this.unityConnection.sendCommand('modify_prefab', {
|
|
65
|
+
prefabPath,
|
|
66
|
+
modifications,
|
|
67
|
+
applyToInstances
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { BaseToolHandler } from '../base/BaseToolHandler.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Handler for opening prefabs in Unity's prefab mode
|
|
5
|
+
*/
|
|
6
|
+
export class OpenPrefabToolHandler extends BaseToolHandler {
|
|
7
|
+
constructor(unityConnection) {
|
|
8
|
+
super(
|
|
9
|
+
'open_prefab',
|
|
10
|
+
'Open a prefab asset in prefab mode for editing. Once in prefab mode, use component tools (list_components, add_component, etc.) to inspect and modify components.',
|
|
11
|
+
{
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
prefabPath: {
|
|
15
|
+
type: 'string',
|
|
16
|
+
description: 'Asset path to the prefab (must start with Assets/ and end with .prefab)'
|
|
17
|
+
},
|
|
18
|
+
focusObject: {
|
|
19
|
+
type: 'string',
|
|
20
|
+
description: 'Optional path to object within prefab to focus on (relative to prefab root)'
|
|
21
|
+
},
|
|
22
|
+
isolateObject: {
|
|
23
|
+
type: 'boolean',
|
|
24
|
+
description: 'Isolate the focused object in the hierarchy (default: false)'
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
required: ['prefabPath']
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
this.unityConnection = unityConnection;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Validates the input parameters
|
|
36
|
+
* @param {Object} params - The input parameters
|
|
37
|
+
* @throws {Error} If validation fails
|
|
38
|
+
*/
|
|
39
|
+
validate(params) {
|
|
40
|
+
super.validate(params); // Check required fields
|
|
41
|
+
|
|
42
|
+
const { prefabPath } = params;
|
|
43
|
+
|
|
44
|
+
// Validate prefabPath is not empty
|
|
45
|
+
if (!prefabPath || prefabPath.trim() === '') {
|
|
46
|
+
throw new Error('prefabPath cannot be empty');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Validate prefabPath format
|
|
50
|
+
if (!prefabPath.startsWith('Assets/') || !prefabPath.endsWith('.prefab')) {
|
|
51
|
+
throw new Error('prefabPath must start with Assets/ and end with .prefab');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Executes the open prefab operation
|
|
57
|
+
* @param {Object} params - The validated input parameters
|
|
58
|
+
* @returns {Promise<Object>} The result of opening the prefab
|
|
59
|
+
*/
|
|
60
|
+
async execute(params) {
|
|
61
|
+
// Ensure connection to Unity
|
|
62
|
+
if (!this.unityConnection.isConnected()) {
|
|
63
|
+
await this.unityConnection.connect();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Send command to Unity
|
|
67
|
+
const response = await this.unityConnection.sendCommand('open_prefab', params);
|
|
68
|
+
|
|
69
|
+
// Handle Unity response
|
|
70
|
+
if (response.error) {
|
|
71
|
+
throw new Error(response.error);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Return result
|
|
75
|
+
return {
|
|
76
|
+
success: response.success,
|
|
77
|
+
prefabPath: response.prefabPath,
|
|
78
|
+
isInPrefabMode: response.isInPrefabMode,
|
|
79
|
+
prefabContentsRoot: response.prefabContentsRoot,
|
|
80
|
+
message: response.message || 'Prefab opened',
|
|
81
|
+
...(response.focusedObject !== undefined && { focusedObject: response.focusedObject }),
|
|
82
|
+
...(response.wasAlreadyOpen !== undefined && { wasAlreadyOpen: response.wasAlreadyOpen })
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Gets example usage for this tool
|
|
88
|
+
* @returns {Object} Example usage scenarios
|
|
89
|
+
*/
|
|
90
|
+
getExamples() {
|
|
91
|
+
return {
|
|
92
|
+
openSimple: {
|
|
93
|
+
description: 'Open a prefab for editing',
|
|
94
|
+
params: {
|
|
95
|
+
prefabPath: 'Assets/Prefabs/PlayerCharacter.prefab'
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
openWithFocus: {
|
|
99
|
+
description: 'Open prefab and focus on specific object',
|
|
100
|
+
params: {
|
|
101
|
+
prefabPath: 'Assets/Prefabs/UI/MainMenu.prefab',
|
|
102
|
+
focusObject: '/Canvas/Buttons/StartButton'
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
openWithIsolation: {
|
|
106
|
+
description: 'Open prefab and isolate specific object',
|
|
107
|
+
params: {
|
|
108
|
+
prefabPath: 'Assets/Prefabs/Enemies/Boss.prefab',
|
|
109
|
+
focusObject: '/Armature/Hips/Spine',
|
|
110
|
+
isolateObject: true
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
openForComponentWork: {
|
|
114
|
+
description: 'Open prefab for component inspection and modification (use with component tools like list_components, add_component, etc.)',
|
|
115
|
+
params: {
|
|
116
|
+
prefabPath: 'Assets/Prefabs/Weapons/Sword.prefab'
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { BaseToolHandler } from '../base/BaseToolHandler.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Handler for saving prefab changes in Unity
|
|
5
|
+
*/
|
|
6
|
+
export class SavePrefabToolHandler extends BaseToolHandler {
|
|
7
|
+
constructor(unityConnection) {
|
|
8
|
+
super(
|
|
9
|
+
'save_prefab',
|
|
10
|
+
'Save current prefab changes in prefab mode or save a GameObject as prefab override',
|
|
11
|
+
{
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
gameObjectPath: {
|
|
15
|
+
type: 'string',
|
|
16
|
+
description: 'Path to GameObject to save as prefab override (optional - if not provided, saves current prefab in prefab mode)'
|
|
17
|
+
},
|
|
18
|
+
includeChildren: {
|
|
19
|
+
type: 'boolean',
|
|
20
|
+
description: 'Include child object overrides when saving (default: true)'
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
this.unityConnection = unityConnection;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Validates the input parameters
|
|
31
|
+
* @param {Object} params - The input parameters
|
|
32
|
+
* @throws {Error} If validation fails
|
|
33
|
+
*/
|
|
34
|
+
validate(params) {
|
|
35
|
+
const { gameObjectPath } = params;
|
|
36
|
+
|
|
37
|
+
// If gameObjectPath is provided, ensure it's not empty
|
|
38
|
+
if (gameObjectPath !== undefined && gameObjectPath.trim() === '') {
|
|
39
|
+
throw new Error('gameObjectPath cannot be empty when provided');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Executes the save prefab operation
|
|
45
|
+
* @param {Object} params - The validated input parameters
|
|
46
|
+
* @returns {Promise<Object>} The result of saving the prefab
|
|
47
|
+
*/
|
|
48
|
+
async execute(params) {
|
|
49
|
+
// Ensure connection to Unity
|
|
50
|
+
if (!this.unityConnection.isConnected()) {
|
|
51
|
+
await this.unityConnection.connect();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Send command to Unity
|
|
55
|
+
const response = await this.unityConnection.sendCommand('save_prefab', params);
|
|
56
|
+
|
|
57
|
+
// Handle Unity response
|
|
58
|
+
if (response.error) {
|
|
59
|
+
throw new Error(response.error);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Return result
|
|
63
|
+
return {
|
|
64
|
+
success: response.success,
|
|
65
|
+
message: response.message || 'Prefab saved',
|
|
66
|
+
...(response.savedInPrefabMode !== undefined && { savedInPrefabMode: response.savedInPrefabMode }),
|
|
67
|
+
...(response.prefabPath !== undefined && { prefabPath: response.prefabPath }),
|
|
68
|
+
...(response.gameObjectPath !== undefined && { gameObjectPath: response.gameObjectPath }),
|
|
69
|
+
...(response.overridesApplied !== undefined && { overridesApplied: response.overridesApplied }),
|
|
70
|
+
...(response.includedChildren !== undefined && { includedChildren: response.includedChildren })
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Gets example usage for this tool
|
|
76
|
+
* @returns {Object} Example usage scenarios
|
|
77
|
+
*/
|
|
78
|
+
getExamples() {
|
|
79
|
+
return {
|
|
80
|
+
saveInPrefabMode: {
|
|
81
|
+
description: 'Save changes while in prefab mode',
|
|
82
|
+
params: {}
|
|
83
|
+
},
|
|
84
|
+
savePrefabInstance: {
|
|
85
|
+
description: 'Save GameObject prefab instance overrides',
|
|
86
|
+
params: {
|
|
87
|
+
gameObjectPath: '/Player'
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
saveWithChildren: {
|
|
91
|
+
description: 'Save prefab instance including all child overrides',
|
|
92
|
+
params: {
|
|
93
|
+
gameObjectPath: '/UI/MainMenu',
|
|
94
|
+
includeChildren: true
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
saveWithoutChildren: {
|
|
98
|
+
description: 'Save only the root GameObject overrides',
|
|
99
|
+
params: {
|
|
100
|
+
gameObjectPath: '/Enemies/Boss',
|
|
101
|
+
includeChildren: false
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|