mcpforunityserver 9.3.0b20260128055651__py3-none-any.whl → 9.3.0b20260129121506__py3-none-any.whl
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.
- cli/commands/animation.py +6 -9
- cli/commands/asset.py +50 -80
- cli/commands/audio.py +14 -22
- cli/commands/batch.py +20 -33
- cli/commands/code.py +63 -70
- cli/commands/component.py +33 -55
- cli/commands/editor.py +122 -188
- cli/commands/gameobject.py +60 -83
- cli/commands/instance.py +28 -36
- cli/commands/lighting.py +54 -59
- cli/commands/material.py +39 -68
- cli/commands/prefab.py +63 -81
- cli/commands/scene.py +30 -54
- cli/commands/script.py +32 -50
- cli/commands/shader.py +43 -55
- cli/commands/texture.py +53 -51
- cli/commands/tool.py +24 -27
- cli/commands/ui.py +125 -130
- cli/commands/vfx.py +84 -138
- cli/utils/confirmation.py +37 -0
- cli/utils/connection.py +32 -2
- cli/utils/constants.py +23 -0
- cli/utils/parsers.py +112 -0
- core/config.py +0 -4
- core/telemetry.py +20 -2
- {mcpforunityserver-9.3.0b20260128055651.dist-info → mcpforunityserver-9.3.0b20260129121506.dist-info}/METADATA +21 -1
- mcpforunityserver-9.3.0b20260129121506.dist-info/RECORD +103 -0
- services/resources/active_tool.py +1 -1
- services/resources/custom_tools.py +1 -1
- services/resources/editor_state.py +1 -1
- services/resources/gameobject.py +4 -4
- services/resources/layers.py +1 -1
- services/resources/menu_items.py +1 -1
- services/resources/prefab.py +3 -3
- services/resources/prefab_stage.py +1 -1
- services/resources/project_info.py +1 -1
- services/resources/selection.py +1 -1
- services/resources/tags.py +1 -1
- services/resources/tests.py +40 -8
- services/resources/unity_instances.py +1 -1
- services/resources/windows.py +1 -1
- services/tools/__init__.py +3 -1
- services/tools/find_gameobjects.py +32 -11
- services/tools/manage_gameobject.py +11 -66
- services/tools/manage_material.py +4 -37
- services/tools/manage_prefabs.py +51 -7
- services/tools/manage_script.py +1 -1
- services/tools/manage_texture.py +10 -96
- services/tools/run_tests.py +67 -4
- services/tools/utils.py +217 -0
- transport/models.py +1 -0
- transport/plugin_hub.py +2 -1
- transport/plugin_registry.py +3 -0
- transport/unity_transport.py +0 -51
- utils/focus_nudge.py +291 -23
- mcpforunityserver-9.3.0b20260128055651.dist-info/RECORD +0 -101
- utils/reload_sentinel.py +0 -9
- {mcpforunityserver-9.3.0b20260128055651.dist-info → mcpforunityserver-9.3.0b20260129121506.dist-info}/WHEEL +0 -0
- {mcpforunityserver-9.3.0b20260128055651.dist-info → mcpforunityserver-9.3.0b20260129121506.dist-info}/entry_points.txt +0 -0
- {mcpforunityserver-9.3.0b20260128055651.dist-info → mcpforunityserver-9.3.0b20260129121506.dist-info}/licenses/LICENSE +0 -0
- {mcpforunityserver-9.3.0b20260128055651.dist-info → mcpforunityserver-9.3.0b20260129121506.dist-info}/top_level.txt +0 -0
cli/commands/script.py
CHANGED
|
@@ -7,7 +7,9 @@ from typing import Optional, Any
|
|
|
7
7
|
|
|
8
8
|
from cli.utils.config import get_config
|
|
9
9
|
from cli.utils.output import format_output, print_error, print_success
|
|
10
|
-
from cli.utils.connection import run_command,
|
|
10
|
+
from cli.utils.connection import run_command, handle_unity_errors
|
|
11
|
+
from cli.utils.parsers import parse_json_list_or_exit
|
|
12
|
+
from cli.utils.confirmation import confirm_destructive_action
|
|
11
13
|
|
|
12
14
|
|
|
13
15
|
@click.group()
|
|
@@ -41,6 +43,7 @@ def script():
|
|
|
41
43
|
default=None,
|
|
42
44
|
help="Full script contents (overrides template)."
|
|
43
45
|
)
|
|
46
|
+
@handle_unity_errors
|
|
44
47
|
def create(name: str, path: str, script_type: str, namespace: Optional[str], contents: Optional[str]):
|
|
45
48
|
"""Create a new C# script.
|
|
46
49
|
|
|
@@ -65,14 +68,10 @@ def create(name: str, path: str, script_type: str, namespace: Optional[str], con
|
|
|
65
68
|
if contents:
|
|
66
69
|
params["contents"] = contents
|
|
67
70
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
print_success(f"Created script: {name}.cs")
|
|
73
|
-
except UnityConnectionError as e:
|
|
74
|
-
print_error(str(e))
|
|
75
|
-
sys.exit(1)
|
|
71
|
+
result = run_command("manage_script", params, config)
|
|
72
|
+
click.echo(format_output(result, config.format))
|
|
73
|
+
if result.get("success"):
|
|
74
|
+
print_success(f"Created script: {name}.cs")
|
|
76
75
|
|
|
77
76
|
|
|
78
77
|
@script.command("read")
|
|
@@ -89,6 +88,7 @@ def create(name: str, path: str, script_type: str, namespace: Optional[str], con
|
|
|
89
88
|
type=int,
|
|
90
89
|
help="Number of lines to read."
|
|
91
90
|
)
|
|
91
|
+
@handle_unity_errors
|
|
92
92
|
def read(path: str, start_line: Optional[int], line_count: Optional[int]):
|
|
93
93
|
"""Read a C# script file.
|
|
94
94
|
|
|
@@ -115,20 +115,16 @@ def read(path: str, start_line: Optional[int], line_count: Optional[int]):
|
|
|
115
115
|
if line_count:
|
|
116
116
|
params["lineCount"] = line_count
|
|
117
117
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
click.echo(data["contents"])
|
|
125
|
-
else:
|
|
126
|
-
click.echo(format_output(result, config.format))
|
|
118
|
+
result = run_command("manage_script", params, config)
|
|
119
|
+
# For read, just output the content directly
|
|
120
|
+
if result.get("success") and result.get("data"):
|
|
121
|
+
data = result.get("data", {})
|
|
122
|
+
if isinstance(data, dict) and "contents" in data:
|
|
123
|
+
click.echo(data["contents"])
|
|
127
124
|
else:
|
|
128
125
|
click.echo(format_output(result, config.format))
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
sys.exit(1)
|
|
126
|
+
else:
|
|
127
|
+
click.echo(format_output(result, config.format))
|
|
132
128
|
|
|
133
129
|
|
|
134
130
|
@script.command("delete")
|
|
@@ -138,6 +134,7 @@ def read(path: str, start_line: Optional[int], line_count: Optional[int]):
|
|
|
138
134
|
is_flag=True,
|
|
139
135
|
help="Skip confirmation prompt."
|
|
140
136
|
)
|
|
137
|
+
@handle_unity_errors
|
|
141
138
|
def delete(path: str, force: bool):
|
|
142
139
|
"""Delete a C# script.
|
|
143
140
|
|
|
@@ -147,8 +144,7 @@ def delete(path: str, force: bool):
|
|
|
147
144
|
"""
|
|
148
145
|
config = get_config()
|
|
149
146
|
|
|
150
|
-
|
|
151
|
-
click.confirm(f"Delete script '{path}'?", abort=True)
|
|
147
|
+
confirm_destructive_action("Delete", "script", path, force)
|
|
152
148
|
|
|
153
149
|
parts = path.rsplit("/", 1)
|
|
154
150
|
filename = parts[-1]
|
|
@@ -161,14 +157,10 @@ def delete(path: str, force: bool):
|
|
|
161
157
|
"path": directory,
|
|
162
158
|
}
|
|
163
159
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
print_success(f"Deleted: {path}")
|
|
169
|
-
except UnityConnectionError as e:
|
|
170
|
-
print_error(str(e))
|
|
171
|
-
sys.exit(1)
|
|
160
|
+
result = run_command("manage_script", params, config)
|
|
161
|
+
click.echo(format_output(result, config.format))
|
|
162
|
+
if result.get("success"):
|
|
163
|
+
print_success(f"Deleted: {path}")
|
|
172
164
|
|
|
173
165
|
|
|
174
166
|
@script.command("edit")
|
|
@@ -178,6 +170,7 @@ def delete(path: str, force: bool):
|
|
|
178
170
|
required=True,
|
|
179
171
|
help='Edits as JSON array of {startLine, startCol, endLine, endCol, newText}.'
|
|
180
172
|
)
|
|
173
|
+
@handle_unity_errors
|
|
181
174
|
def edit(path: str, edits: str):
|
|
182
175
|
"""Apply text edits to a script.
|
|
183
176
|
|
|
@@ -187,25 +180,17 @@ def edit(path: str, edits: str):
|
|
|
187
180
|
"""
|
|
188
181
|
config = get_config()
|
|
189
182
|
|
|
190
|
-
|
|
191
|
-
edits_list = json.loads(edits)
|
|
192
|
-
except json.JSONDecodeError as e:
|
|
193
|
-
print_error(f"Invalid JSON for edits: {e}")
|
|
194
|
-
sys.exit(1)
|
|
183
|
+
edits_list = parse_json_list_or_exit(edits, "edits")
|
|
195
184
|
|
|
196
185
|
params: dict[str, Any] = {
|
|
197
186
|
"uri": path,
|
|
198
187
|
"edits": edits_list,
|
|
199
188
|
}
|
|
200
189
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
print_success(f"Applied edits to: {path}")
|
|
206
|
-
except UnityConnectionError as e:
|
|
207
|
-
print_error(str(e))
|
|
208
|
-
sys.exit(1)
|
|
190
|
+
result = run_command("apply_text_edits", params, config)
|
|
191
|
+
click.echo(format_output(result, config.format))
|
|
192
|
+
if result.get("success"):
|
|
193
|
+
print_success(f"Applied edits to: {path}")
|
|
209
194
|
|
|
210
195
|
|
|
211
196
|
@script.command("validate")
|
|
@@ -216,6 +201,7 @@ def edit(path: str, edits: str):
|
|
|
216
201
|
default="basic",
|
|
217
202
|
help="Validation level."
|
|
218
203
|
)
|
|
204
|
+
@handle_unity_errors
|
|
219
205
|
def validate(path: str, level: str):
|
|
220
206
|
"""Validate a C# script for errors.
|
|
221
207
|
|
|
@@ -232,9 +218,5 @@ def validate(path: str, level: str):
|
|
|
232
218
|
"include_diagnostics": True,
|
|
233
219
|
}
|
|
234
220
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
click.echo(format_output(result, config.format))
|
|
238
|
-
except UnityConnectionError as e:
|
|
239
|
-
print_error(str(e))
|
|
240
|
-
sys.exit(1)
|
|
221
|
+
result = run_command("validate_script", params, config)
|
|
222
|
+
click.echo(format_output(result, config.format))
|
cli/commands/shader.py
CHANGED
|
@@ -6,7 +6,8 @@ from typing import Optional
|
|
|
6
6
|
|
|
7
7
|
from cli.utils.config import get_config
|
|
8
8
|
from cli.utils.output import format_output, print_error, print_success
|
|
9
|
-
from cli.utils.connection import run_command,
|
|
9
|
+
from cli.utils.connection import run_command, handle_unity_errors
|
|
10
|
+
from cli.utils.confirmation import confirm_destructive_action
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
@click.group()
|
|
@@ -17,6 +18,7 @@ def shader():
|
|
|
17
18
|
|
|
18
19
|
@shader.command("read")
|
|
19
20
|
@click.argument("path")
|
|
21
|
+
@handle_unity_errors
|
|
20
22
|
def read_shader(path: str):
|
|
21
23
|
"""Read a shader file.
|
|
22
24
|
|
|
@@ -31,21 +33,17 @@ def read_shader(path: str):
|
|
|
31
33
|
name = os.path.splitext(os.path.basename(path))[0]
|
|
32
34
|
directory = os.path.dirname(path)
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}, config)
|
|
36
|
+
result = run_command("manage_shader", {
|
|
37
|
+
"action": "read",
|
|
38
|
+
"name": name,
|
|
39
|
+
"path": directory or "Assets/",
|
|
40
|
+
}, config)
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
except UnityConnectionError as e:
|
|
47
|
-
print_error(str(e))
|
|
48
|
-
sys.exit(1)
|
|
42
|
+
# If successful, display the contents nicely
|
|
43
|
+
if result.get("success") and result.get("data", {}).get("contents"):
|
|
44
|
+
click.echo(result["data"]["contents"])
|
|
45
|
+
else:
|
|
46
|
+
click.echo(format_output(result, config.format))
|
|
49
47
|
|
|
50
48
|
|
|
51
49
|
@shader.command("create")
|
|
@@ -67,6 +65,7 @@ def read_shader(path: str):
|
|
|
67
65
|
type=click.Path(exists=True),
|
|
68
66
|
help="Read shader code from file."
|
|
69
67
|
)
|
|
68
|
+
@handle_unity_errors
|
|
70
69
|
def create_shader(name: str, path: str, contents: Optional[str], file_path: Optional[str]):
|
|
71
70
|
"""Create a new shader.
|
|
72
71
|
|
|
@@ -127,19 +126,15 @@ def create_shader(name: str, path: str, contents: Optional[str], file_path: Opti
|
|
|
127
126
|
}}
|
|
128
127
|
'''
|
|
129
128
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
print_success(f"Created shader: {path}/{name}.shader")
|
|
140
|
-
except UnityConnectionError as e:
|
|
141
|
-
print_error(str(e))
|
|
142
|
-
sys.exit(1)
|
|
129
|
+
result = run_command("manage_shader", {
|
|
130
|
+
"action": "create",
|
|
131
|
+
"name": name,
|
|
132
|
+
"path": path,
|
|
133
|
+
"contents": shader_contents,
|
|
134
|
+
}, config)
|
|
135
|
+
click.echo(format_output(result, config.format))
|
|
136
|
+
if result.get("success"):
|
|
137
|
+
print_success(f"Created shader: {path}/{name}.shader")
|
|
143
138
|
|
|
144
139
|
|
|
145
140
|
@shader.command("update")
|
|
@@ -156,6 +151,7 @@ def create_shader(name: str, path: str, contents: Optional[str], file_path: Opti
|
|
|
156
151
|
type=click.Path(exists=True),
|
|
157
152
|
help="Read shader code from file."
|
|
158
153
|
)
|
|
154
|
+
@handle_unity_errors
|
|
159
155
|
def update_shader(path: str, contents: Optional[str], file_path: Optional[str]):
|
|
160
156
|
"""Update an existing shader.
|
|
161
157
|
|
|
@@ -185,19 +181,15 @@ def update_shader(path: str, contents: Optional[str], file_path: Optional[str]):
|
|
|
185
181
|
"No shader contents provided. Use --contents, --file, or pipe via stdin.")
|
|
186
182
|
sys.exit(1)
|
|
187
183
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
print_success(f"Updated shader: {path}")
|
|
198
|
-
except UnityConnectionError as e:
|
|
199
|
-
print_error(str(e))
|
|
200
|
-
sys.exit(1)
|
|
184
|
+
result = run_command("manage_shader", {
|
|
185
|
+
"action": "update",
|
|
186
|
+
"name": name,
|
|
187
|
+
"path": directory or "Assets/",
|
|
188
|
+
"contents": shader_contents,
|
|
189
|
+
}, config)
|
|
190
|
+
click.echo(format_output(result, config.format))
|
|
191
|
+
if result.get("success"):
|
|
192
|
+
print_success(f"Updated shader: {path}")
|
|
201
193
|
|
|
202
194
|
|
|
203
195
|
@shader.command("delete")
|
|
@@ -207,6 +199,7 @@ def update_shader(path: str, contents: Optional[str], file_path: Optional[str]):
|
|
|
207
199
|
is_flag=True,
|
|
208
200
|
help="Skip confirmation prompt."
|
|
209
201
|
)
|
|
202
|
+
@handle_unity_errors
|
|
210
203
|
def delete_shader(path: str, force: bool):
|
|
211
204
|
"""Delete a shader.
|
|
212
205
|
|
|
@@ -217,22 +210,17 @@ def delete_shader(path: str, force: bool):
|
|
|
217
210
|
"""
|
|
218
211
|
config = get_config()
|
|
219
212
|
|
|
220
|
-
|
|
221
|
-
click.confirm(f"Delete shader '{path}'?", abort=True)
|
|
213
|
+
confirm_destructive_action("Delete", "shader", path, force)
|
|
222
214
|
|
|
223
215
|
import os
|
|
224
216
|
name = os.path.splitext(os.path.basename(path))[0]
|
|
225
217
|
directory = os.path.dirname(path)
|
|
226
218
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
print_success(f"Deleted shader: {path}")
|
|
236
|
-
except UnityConnectionError as e:
|
|
237
|
-
print_error(str(e))
|
|
238
|
-
sys.exit(1)
|
|
219
|
+
result = run_command("manage_shader", {
|
|
220
|
+
"action": "delete",
|
|
221
|
+
"name": name,
|
|
222
|
+
"path": directory or "Assets/",
|
|
223
|
+
}, config)
|
|
224
|
+
click.echo(format_output(result, config.format))
|
|
225
|
+
if result.get("success"):
|
|
226
|
+
print_success(f"Deleted shader: {path}")
|
cli/commands/texture.py
CHANGED
|
@@ -1,28 +1,13 @@
|
|
|
1
1
|
"""Texture CLI commands."""
|
|
2
2
|
|
|
3
3
|
import sys
|
|
4
|
-
import json
|
|
5
4
|
import click
|
|
6
5
|
from typing import Optional, Any
|
|
7
6
|
|
|
8
7
|
from cli.utils.config import get_config
|
|
9
8
|
from cli.utils.output import format_output, print_error, print_success
|
|
10
|
-
from cli.utils.connection import run_command,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def try_parse_json(value: str, context: str) -> Any:
|
|
14
|
-
"""Try to parse JSON, with fallback for single quotes and Python bools."""
|
|
15
|
-
try:
|
|
16
|
-
return json.loads(value)
|
|
17
|
-
except json.JSONDecodeError:
|
|
18
|
-
# Try to fix common shell quoting issues (single quotes, Python bools)
|
|
19
|
-
try:
|
|
20
|
-
fixed = value.replace("'", '"').replace(
|
|
21
|
-
"True", "true").replace("False", "false")
|
|
22
|
-
return json.loads(fixed)
|
|
23
|
-
except json.JSONDecodeError as e:
|
|
24
|
-
print_error(f"Invalid JSON for {context}: {e}")
|
|
25
|
-
sys.exit(1)
|
|
9
|
+
from cli.utils.connection import run_command, handle_unity_errors
|
|
10
|
+
from cli.utils.parsers import parse_json_or_exit as try_parse_json
|
|
26
11
|
|
|
27
12
|
|
|
28
13
|
_TEXTURE_TYPES = {
|
|
@@ -125,6 +110,22 @@ def _normalize_color(value: Any, context: str) -> list[int]:
|
|
|
125
110
|
return _parse_hex_color(value)
|
|
126
111
|
value = try_parse_json(value, context)
|
|
127
112
|
|
|
113
|
+
# Handle dict with r/g/b keys (e.g., {"r": 1, "g": 0, "b": 0} or {"r": 1, "g": 0, "b": 0, "a": 1})
|
|
114
|
+
if isinstance(value, dict):
|
|
115
|
+
if all(k in value for k in ("r", "g", "b")):
|
|
116
|
+
try:
|
|
117
|
+
color = [value["r"], value["g"], value["b"]]
|
|
118
|
+
if "a" in value:
|
|
119
|
+
color.append(value["a"])
|
|
120
|
+
else:
|
|
121
|
+
color.append(1.0 if _is_normalized_color(color) else 255)
|
|
122
|
+
if _is_normalized_color(color):
|
|
123
|
+
return [int(round(float(c) * 255)) for c in color]
|
|
124
|
+
return [int(c) for c in color]
|
|
125
|
+
except (TypeError, ValueError):
|
|
126
|
+
raise ValueError(f"{context} dict values must be numeric, got {value}")
|
|
127
|
+
raise ValueError(f"{context} dict must have 'r', 'g', 'b' keys, got {list(value.keys())}")
|
|
128
|
+
|
|
128
129
|
if isinstance(value, (list, tuple)):
|
|
129
130
|
if len(value) == 3:
|
|
130
131
|
value = list(value) + [1.0 if _is_normalized_color(value) else 255]
|
|
@@ -339,6 +340,7 @@ def texture():
|
|
|
339
340
|
]), help="Pattern type")
|
|
340
341
|
@click.option("--palette", help="Color palette for pattern (JSON array of colors)")
|
|
341
342
|
@click.option("--import-settings", help="TextureImporter settings (JSON)")
|
|
343
|
+
@handle_unity_errors
|
|
342
344
|
def create(path: str, width: int, height: int, image_path: Optional[str], color: Optional[str],
|
|
343
345
|
pattern: Optional[str], palette: Optional[str], import_settings: Optional[str]):
|
|
344
346
|
"""Create a new procedural texture.
|
|
@@ -402,14 +404,10 @@ def create(path: str, width: int, height: int, image_path: Optional[str], color:
|
|
|
402
404
|
if image_path:
|
|
403
405
|
params["imagePath"] = image_path
|
|
404
406
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
print_success(f"Created texture: {path}")
|
|
410
|
-
except UnityConnectionError as e:
|
|
411
|
-
print_error(str(e))
|
|
412
|
-
sys.exit(1)
|
|
407
|
+
result = run_command("manage_texture", params, config)
|
|
408
|
+
click.echo(format_output(result, config.format))
|
|
409
|
+
if result.get("success"):
|
|
410
|
+
print_success(f"Created texture: {path}")
|
|
413
411
|
|
|
414
412
|
|
|
415
413
|
@texture.command("sprite")
|
|
@@ -423,6 +421,7 @@ def create(path: str, width: int, height: int, image_path: Optional[str], color:
|
|
|
423
421
|
]), help="Pattern type (defaults to checkerboard if no color specified)")
|
|
424
422
|
@click.option("--ppu", default=100.0, help="Pixels Per Unit")
|
|
425
423
|
@click.option("--pivot", help="Pivot as [x,y] (default: [0.5, 0.5])")
|
|
424
|
+
@handle_unity_errors
|
|
426
425
|
def sprite(path: str, width: int, height: int, image_path: Optional[str], color: Optional[str], pattern: Optional[str], ppu: float, pivot: Optional[str]):
|
|
427
426
|
"""Quickly create a sprite texture.
|
|
428
427
|
|
|
@@ -476,19 +475,16 @@ def sprite(path: str, width: int, height: int, image_path: Optional[str], color:
|
|
|
476
475
|
if image_path:
|
|
477
476
|
params["imagePath"] = image_path
|
|
478
477
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
print_success(f"Created sprite: {path}")
|
|
484
|
-
except UnityConnectionError as e:
|
|
485
|
-
print_error(str(e))
|
|
486
|
-
sys.exit(1)
|
|
478
|
+
result = run_command("manage_texture", params, config)
|
|
479
|
+
click.echo(format_output(result, config.format))
|
|
480
|
+
if result.get("success"):
|
|
481
|
+
print_success(f"Created sprite: {path}")
|
|
487
482
|
|
|
488
483
|
|
|
489
484
|
@texture.command("modify")
|
|
490
485
|
@click.argument("path")
|
|
491
486
|
@click.option("--set-pixels", required=True, help="Modification args as JSON")
|
|
487
|
+
@handle_unity_errors
|
|
492
488
|
def modify(path: str, set_pixels: str):
|
|
493
489
|
"""Modify an existing texture.
|
|
494
490
|
|
|
@@ -510,29 +506,35 @@ def modify(path: str, set_pixels: str):
|
|
|
510
506
|
print_error(str(e))
|
|
511
507
|
sys.exit(1)
|
|
512
508
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
print_success(f"Modified texture: {path}")
|
|
518
|
-
except UnityConnectionError as e:
|
|
519
|
-
print_error(str(e))
|
|
520
|
-
sys.exit(1)
|
|
509
|
+
result = run_command("manage_texture", params, config)
|
|
510
|
+
click.echo(format_output(result, config.format))
|
|
511
|
+
if result.get("success"):
|
|
512
|
+
print_success(f"Modified texture: {path}")
|
|
521
513
|
|
|
522
514
|
|
|
523
515
|
@texture.command("delete")
|
|
524
516
|
@click.argument("path")
|
|
525
|
-
|
|
517
|
+
@click.option(
|
|
518
|
+
"--force", "-f",
|
|
519
|
+
is_flag=True,
|
|
520
|
+
help="Skip confirmation prompt."
|
|
521
|
+
)
|
|
522
|
+
@handle_unity_errors
|
|
523
|
+
def delete(path: str, force: bool):
|
|
526
524
|
"""Delete a texture.
|
|
525
|
+
|
|
526
|
+
\\b
|
|
527
|
+
Examples:
|
|
528
|
+
unity-mcp texture delete "Assets/Textures/Old.png"
|
|
529
|
+
unity-mcp texture delete "Assets/Textures/Old.png" --force
|
|
527
530
|
"""
|
|
531
|
+
from cli.utils.confirmation import confirm_destructive_action
|
|
528
532
|
config = get_config()
|
|
529
533
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
print_error(str(e))
|
|
538
|
-
sys.exit(1)
|
|
534
|
+
confirm_destructive_action("Delete", "texture", path, force)
|
|
535
|
+
|
|
536
|
+
result = run_command("manage_texture", {
|
|
537
|
+
"action": "delete", "path": path}, config)
|
|
538
|
+
click.echo(format_output(result, config.format))
|
|
539
|
+
if result.get("success"):
|
|
540
|
+
print_success(f"Deleted texture: {path}")
|
cli/commands/tool.py
CHANGED
|
@@ -1,40 +1,35 @@
|
|
|
1
1
|
"""Tool CLI commands for listing custom tools."""
|
|
2
2
|
|
|
3
|
-
import sys
|
|
4
3
|
import click
|
|
5
4
|
|
|
6
5
|
from cli.utils.config import get_config
|
|
7
6
|
from cli.utils.output import format_output, print_error
|
|
8
|
-
from cli.utils.connection import run_list_custom_tools,
|
|
7
|
+
from cli.utils.connection import run_list_custom_tools, handle_unity_errors
|
|
9
8
|
|
|
10
9
|
|
|
11
10
|
def _list_custom_tools() -> None:
|
|
12
11
|
config = get_config()
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
click.echo(f" [{i}] {name}")
|
|
35
|
-
except UnityConnectionError as e:
|
|
36
|
-
print_error(str(e))
|
|
37
|
-
sys.exit(1)
|
|
12
|
+
result = run_list_custom_tools(config)
|
|
13
|
+
if config.format != "text":
|
|
14
|
+
click.echo(format_output(result, config.format))
|
|
15
|
+
return
|
|
16
|
+
|
|
17
|
+
if not isinstance(result, dict) or not result.get("success", True):
|
|
18
|
+
click.echo(format_output(result, config.format))
|
|
19
|
+
return
|
|
20
|
+
|
|
21
|
+
tools = result.get("tools")
|
|
22
|
+
if tools is None:
|
|
23
|
+
data = result.get("data", {})
|
|
24
|
+
tools = data.get("tools") if isinstance(data, dict) else None
|
|
25
|
+
if not isinstance(tools, list):
|
|
26
|
+
click.echo(format_output(result, config.format))
|
|
27
|
+
return
|
|
28
|
+
|
|
29
|
+
click.echo(f"Custom tools ({len(tools)}):")
|
|
30
|
+
for i, t in enumerate(tools):
|
|
31
|
+
name = t.get("name") if isinstance(t, dict) else str(t)
|
|
32
|
+
click.echo(f" [{i}] {name}")
|
|
38
33
|
|
|
39
34
|
|
|
40
35
|
@click.group("tool")
|
|
@@ -44,6 +39,7 @@ def tool():
|
|
|
44
39
|
|
|
45
40
|
|
|
46
41
|
@tool.command("list")
|
|
42
|
+
@handle_unity_errors
|
|
47
43
|
def list_tools():
|
|
48
44
|
"""List custom tools registered for the active Unity project."""
|
|
49
45
|
_list_custom_tools()
|
|
@@ -56,6 +52,7 @@ def custom_tool():
|
|
|
56
52
|
|
|
57
53
|
|
|
58
54
|
@custom_tool.command("list")
|
|
55
|
+
@handle_unity_errors
|
|
59
56
|
def list_custom_tools():
|
|
60
57
|
"""List custom tools registered for the active Unity project."""
|
|
61
58
|
_list_custom_tools()
|