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.
Files changed (61) hide show
  1. cli/commands/animation.py +6 -9
  2. cli/commands/asset.py +50 -80
  3. cli/commands/audio.py +14 -22
  4. cli/commands/batch.py +20 -33
  5. cli/commands/code.py +63 -70
  6. cli/commands/component.py +33 -55
  7. cli/commands/editor.py +122 -188
  8. cli/commands/gameobject.py +60 -83
  9. cli/commands/instance.py +28 -36
  10. cli/commands/lighting.py +54 -59
  11. cli/commands/material.py +39 -68
  12. cli/commands/prefab.py +63 -81
  13. cli/commands/scene.py +30 -54
  14. cli/commands/script.py +32 -50
  15. cli/commands/shader.py +43 -55
  16. cli/commands/texture.py +53 -51
  17. cli/commands/tool.py +24 -27
  18. cli/commands/ui.py +125 -130
  19. cli/commands/vfx.py +84 -138
  20. cli/utils/confirmation.py +37 -0
  21. cli/utils/connection.py +32 -2
  22. cli/utils/constants.py +23 -0
  23. cli/utils/parsers.py +112 -0
  24. core/config.py +0 -4
  25. core/telemetry.py +20 -2
  26. {mcpforunityserver-9.3.0b20260128055651.dist-info → mcpforunityserver-9.3.0b20260129121506.dist-info}/METADATA +21 -1
  27. mcpforunityserver-9.3.0b20260129121506.dist-info/RECORD +103 -0
  28. services/resources/active_tool.py +1 -1
  29. services/resources/custom_tools.py +1 -1
  30. services/resources/editor_state.py +1 -1
  31. services/resources/gameobject.py +4 -4
  32. services/resources/layers.py +1 -1
  33. services/resources/menu_items.py +1 -1
  34. services/resources/prefab.py +3 -3
  35. services/resources/prefab_stage.py +1 -1
  36. services/resources/project_info.py +1 -1
  37. services/resources/selection.py +1 -1
  38. services/resources/tags.py +1 -1
  39. services/resources/tests.py +40 -8
  40. services/resources/unity_instances.py +1 -1
  41. services/resources/windows.py +1 -1
  42. services/tools/__init__.py +3 -1
  43. services/tools/find_gameobjects.py +32 -11
  44. services/tools/manage_gameobject.py +11 -66
  45. services/tools/manage_material.py +4 -37
  46. services/tools/manage_prefabs.py +51 -7
  47. services/tools/manage_script.py +1 -1
  48. services/tools/manage_texture.py +10 -96
  49. services/tools/run_tests.py +67 -4
  50. services/tools/utils.py +217 -0
  51. transport/models.py +1 -0
  52. transport/plugin_hub.py +2 -1
  53. transport/plugin_registry.py +3 -0
  54. transport/unity_transport.py +0 -51
  55. utils/focus_nudge.py +291 -23
  56. mcpforunityserver-9.3.0b20260128055651.dist-info/RECORD +0 -101
  57. utils/reload_sentinel.py +0 -9
  58. {mcpforunityserver-9.3.0b20260128055651.dist-info → mcpforunityserver-9.3.0b20260129121506.dist-info}/WHEEL +0 -0
  59. {mcpforunityserver-9.3.0b20260128055651.dist-info → mcpforunityserver-9.3.0b20260129121506.dist-info}/entry_points.txt +0 -0
  60. {mcpforunityserver-9.3.0b20260128055651.dist-info → mcpforunityserver-9.3.0b20260129121506.dist-info}/licenses/LICENSE +0 -0
  61. {mcpforunityserver-9.3.0b20260128055651.dist-info → mcpforunityserver-9.3.0b20260129121506.dist-info}/top_level.txt +0 -0
cli/commands/material.py CHANGED
@@ -7,7 +7,9 @@ from typing import Optional, Any, Tuple
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, UnityConnectionError
10
+ from cli.utils.connection import run_command, handle_unity_errors
11
+ from cli.utils.parsers import parse_value_safe, parse_json_dict_or_exit
12
+ from cli.utils.constants import SEARCH_METHOD_CHOICE_RENDERER
11
13
 
12
14
 
13
15
  @click.group()
@@ -18,6 +20,7 @@ def material():
18
20
 
19
21
  @material.command("info")
20
22
  @click.argument("path")
23
+ @handle_unity_errors
21
24
  def info(path: str):
22
25
  """Get information about a material.
23
26
 
@@ -27,15 +30,11 @@ def info(path: str):
27
30
  """
28
31
  config = get_config()
29
32
 
30
- try:
31
- result = run_command("manage_material", {
32
- "action": "get_material_info",
33
- "materialPath": path,
34
- }, config)
35
- click.echo(format_output(result, config.format))
36
- except UnityConnectionError as e:
37
- print_error(str(e))
38
- sys.exit(1)
33
+ result = run_command("manage_material", {
34
+ "action": "get_material_info",
35
+ "materialPath": path,
36
+ }, config)
37
+ click.echo(format_output(result, config.format))
39
38
 
40
39
 
41
40
  @material.command("create")
@@ -50,6 +49,7 @@ def info(path: str):
50
49
  default=None,
51
50
  help='Initial properties as JSON.'
52
51
  )
52
+ @handle_unity_errors
53
53
  def create(path: str, shader: str, properties: Optional[str]):
54
54
  """Create a new material.
55
55
 
@@ -68,20 +68,12 @@ def create(path: str, shader: str, properties: Optional[str]):
68
68
  }
69
69
 
70
70
  if properties:
71
- try:
72
- params["properties"] = json.loads(properties)
73
- except json.JSONDecodeError as e:
74
- print_error(f"Invalid JSON for properties: {e}")
75
- sys.exit(1)
76
-
77
- try:
78
- result = run_command("manage_material", params, config)
79
- click.echo(format_output(result, config.format))
80
- if result.get("success"):
81
- print_success(f"Created material: {path}")
82
- except UnityConnectionError as e:
83
- print_error(str(e))
84
- sys.exit(1)
71
+ params["properties"] = parse_json_dict_or_exit(properties, "properties")
72
+
73
+ result = run_command("manage_material", params, config)
74
+ click.echo(format_output(result, config.format))
75
+ if result.get("success"):
76
+ print_success(f"Created material: {path}")
85
77
 
86
78
 
87
79
  @material.command("set-color")
@@ -95,6 +87,7 @@ def create(path: str, shader: str, properties: Optional[str]):
95
87
  default="_Color",
96
88
  help="Color property name (default: _Color)."
97
89
  )
90
+ @handle_unity_errors
98
91
  def set_color(path: str, r: float, g: float, b: float, a: float, property: str):
99
92
  """Set a material's color.
100
93
 
@@ -113,20 +106,17 @@ def set_color(path: str, r: float, g: float, b: float, a: float, property: str):
113
106
  "color": [r, g, b, a],
114
107
  }
115
108
 
116
- try:
117
- result = run_command("manage_material", params, config)
118
- click.echo(format_output(result, config.format))
119
- if result.get("success"):
120
- print_success(f"Set color on: {path}")
121
- except UnityConnectionError as e:
122
- print_error(str(e))
123
- sys.exit(1)
109
+ result = run_command("manage_material", params, config)
110
+ click.echo(format_output(result, config.format))
111
+ if result.get("success"):
112
+ print_success(f"Set color on: {path}")
124
113
 
125
114
 
126
115
  @material.command("set-property")
127
116
  @click.argument("path")
128
117
  @click.argument("property_name")
129
118
  @click.argument("value")
119
+ @handle_unity_errors
130
120
  def set_property(path: str, property_name: str, value: str):
131
121
  """Set a shader property on a material.
132
122
 
@@ -139,14 +129,7 @@ def set_property(path: str, property_name: str, value: str):
139
129
  config = get_config()
140
130
 
141
131
  # Try to parse value as JSON for complex types
142
- try:
143
- parsed_value = json.loads(value)
144
- except json.JSONDecodeError:
145
- # Try to parse as number
146
- try:
147
- parsed_value = float(value)
148
- except ValueError:
149
- parsed_value = value
132
+ parsed_value = parse_value_safe(value)
150
133
 
151
134
  params: dict[str, Any] = {
152
135
  "action": "set_material_shader_property",
@@ -155,14 +138,10 @@ def set_property(path: str, property_name: str, value: str):
155
138
  "value": parsed_value,
156
139
  }
157
140
 
158
- try:
159
- result = run_command("manage_material", params, config)
160
- click.echo(format_output(result, config.format))
161
- if result.get("success"):
162
- print_success(f"Set {property_name} on: {path}")
163
- except UnityConnectionError as e:
164
- print_error(str(e))
165
- sys.exit(1)
141
+ result = run_command("manage_material", params, config)
142
+ click.echo(format_output(result, config.format))
143
+ if result.get("success"):
144
+ print_success(f"Set {property_name} on: {path}")
166
145
 
167
146
 
168
147
  @material.command("assign")
@@ -170,8 +149,7 @@ def set_property(path: str, property_name: str, value: str):
170
149
  @click.argument("target")
171
150
  @click.option(
172
151
  "--search-method",
173
- type=click.Choice(["by_name", "by_path", "by_tag",
174
- "by_layer", "by_component"]),
152
+ type=SEARCH_METHOD_CHOICE_RENDERER,
175
153
  default=None,
176
154
  help="How to find the target GameObject."
177
155
  )
@@ -187,6 +165,7 @@ def set_property(path: str, property_name: str, value: str):
187
165
  default="shared",
188
166
  help="Assignment mode."
189
167
  )
168
+ @handle_unity_errors
190
169
  def assign(material_path: str, target: str, search_method: Optional[str], slot: int, mode: str):
191
170
  """Assign a material to a GameObject's renderer.
192
171
 
@@ -209,14 +188,10 @@ def assign(material_path: str, target: str, search_method: Optional[str], slot:
209
188
  if search_method:
210
189
  params["searchMethod"] = search_method
211
190
 
212
- try:
213
- result = run_command("manage_material", params, config)
214
- click.echo(format_output(result, config.format))
215
- if result.get("success"):
216
- print_success(f"Assigned material to: {target}")
217
- except UnityConnectionError as e:
218
- print_error(str(e))
219
- sys.exit(1)
191
+ result = run_command("manage_material", params, config)
192
+ click.echo(format_output(result, config.format))
193
+ if result.get("success"):
194
+ print_success(f"Assigned material to: {target}")
220
195
 
221
196
 
222
197
  @material.command("set-renderer-color")
@@ -227,8 +202,7 @@ def assign(material_path: str, target: str, search_method: Optional[str], slot:
227
202
  @click.argument("a", type=float, default=1.0)
228
203
  @click.option(
229
204
  "--search-method",
230
- type=click.Choice(["by_name", "by_path", "by_tag",
231
- "by_layer", "by_component"]),
205
+ type=SEARCH_METHOD_CHOICE_RENDERER,
232
206
  default=None,
233
207
  help="How to find the target GameObject."
234
208
  )
@@ -238,6 +212,7 @@ def assign(material_path: str, target: str, search_method: Optional[str], slot:
238
212
  default="property_block",
239
213
  help="Modification mode."
240
214
  )
215
+ @handle_unity_errors
241
216
  def set_renderer_color(target: str, r: float, g: float, b: float, a: float, search_method: Optional[str], mode: str):
242
217
  """Set a renderer's material color directly.
243
218
 
@@ -258,11 +233,7 @@ def set_renderer_color(target: str, r: float, g: float, b: float, a: float, sear
258
233
  if search_method:
259
234
  params["searchMethod"] = search_method
260
235
 
261
- try:
262
- result = run_command("manage_material", params, config)
263
- click.echo(format_output(result, config.format))
264
- if result.get("success"):
265
- print_success(f"Set renderer color on: {target}")
266
- except UnityConnectionError as e:
267
- print_error(str(e))
268
- sys.exit(1)
236
+ result = run_command("manage_material", params, config)
237
+ click.echo(format_output(result, config.format))
238
+ if result.get("success"):
239
+ print_success(f"Set renderer color on: {target}")
cli/commands/prefab.py CHANGED
@@ -6,7 +6,7 @@ from typing import Optional, Any
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, UnityConnectionError
9
+ from cli.utils.connection import run_command, handle_unity_errors
10
10
 
11
11
 
12
12
  @click.group()
@@ -17,6 +17,7 @@ def prefab():
17
17
 
18
18
  @prefab.command("open")
19
19
  @click.argument("path")
20
+ @handle_unity_errors
20
21
  def open_stage(path: str):
21
22
  """Open a prefab in the prefab stage for editing.
22
23
 
@@ -31,14 +32,10 @@ def open_stage(path: str):
31
32
  "prefabPath": path,
32
33
  }
33
34
 
34
- try:
35
- result = run_command("manage_prefabs", params, config)
36
- click.echo(format_output(result, config.format))
37
- if result.get("success"):
38
- print_success(f"Opened prefab: {path}")
39
- except UnityConnectionError as e:
40
- print_error(str(e))
41
- sys.exit(1)
35
+ result = run_command("manage_prefabs", params, config)
36
+ click.echo(format_output(result, config.format))
37
+ if result.get("success"):
38
+ print_success(f"Opened prefab: {path}")
42
39
 
43
40
 
44
41
  @prefab.command("close")
@@ -47,6 +44,7 @@ def open_stage(path: str):
47
44
  is_flag=True,
48
45
  help="Save the prefab before closing."
49
46
  )
47
+ @handle_unity_errors
50
48
  def close_stage(save: bool):
51
49
  """Close the current prefab stage.
52
50
 
@@ -63,14 +61,10 @@ def close_stage(save: bool):
63
61
  if save:
64
62
  params["saveBeforeClose"] = True
65
63
 
66
- try:
67
- result = run_command("manage_prefabs", params, config)
68
- click.echo(format_output(result, config.format))
69
- if result.get("success"):
70
- print_success("Closed prefab stage")
71
- except UnityConnectionError as e:
72
- print_error(str(e))
73
- sys.exit(1)
64
+ result = run_command("manage_prefabs", params, config)
65
+ click.echo(format_output(result, config.format))
66
+ if result.get("success"):
67
+ print_success("Closed prefab stage")
74
68
 
75
69
 
76
70
  @prefab.command("save")
@@ -79,6 +73,7 @@ def close_stage(save: bool):
79
73
  is_flag=True,
80
74
  help="Force save even if no changes detected. Useful for automated workflows."
81
75
  )
76
+ @handle_unity_errors
82
77
  def save_stage(force: bool):
83
78
  """Save the currently open prefab stage.
84
79
 
@@ -95,14 +90,10 @@ def save_stage(force: bool):
95
90
  if force:
96
91
  params["force"] = True
97
92
 
98
- try:
99
- result = run_command("manage_prefabs", params, config)
100
- click.echo(format_output(result, config.format))
101
- if result.get("success"):
102
- print_success("Saved prefab")
103
- except UnityConnectionError as e:
104
- print_error(str(e))
105
- sys.exit(1)
93
+ result = run_command("manage_prefabs", params, config)
94
+ click.echo(format_output(result, config.format))
95
+ if result.get("success"):
96
+ print_success("Saved prefab")
106
97
 
107
98
 
108
99
  @prefab.command("info")
@@ -112,6 +103,7 @@ def save_stage(force: bool):
112
103
  is_flag=True,
113
104
  help="Show compact output (key values only)."
114
105
  )
106
+ @handle_unity_errors
115
107
  def info(path: str, compact: bool):
116
108
  """Get information about a prefab asset.
117
109
 
@@ -127,26 +119,22 @@ def info(path: str, compact: bool):
127
119
  "prefabPath": path,
128
120
  }
129
121
 
130
- try:
131
- result = run_command("manage_prefabs", params, config)
132
- # Get the actual response data from the wrapped result structure
133
- response_data = result.get("result", result)
134
- if compact and response_data.get("success") and response_data.get("data"):
135
- data = response_data["data"]
136
- click.echo(f"Prefab: {data.get('assetPath', path)}")
137
- click.echo(f" Type: {data.get('prefabType', 'Unknown')}")
138
- click.echo(f" Root: {data.get('rootObjectName', 'N/A')}")
139
- click.echo(f" GUID: {data.get('guid', 'N/A')}")
140
- click.echo(
141
- f" Components: {len(data.get('rootComponentTypes', []))}")
142
- click.echo(f" Children: {data.get('childCount', 0)}")
143
- if data.get('isVariant'):
144
- click.echo(f" Variant of: {data.get('parentPrefab', 'N/A')}")
145
- else:
146
- click.echo(format_output(result, config.format))
147
- except UnityConnectionError as e:
148
- print_error(str(e))
149
- sys.exit(1)
122
+ result = run_command("manage_prefabs", params, config)
123
+ # Get the actual response data from the wrapped result structure
124
+ response_data = result.get("result", result)
125
+ if compact and response_data.get("success") and response_data.get("data"):
126
+ data = response_data["data"]
127
+ click.echo(f"Prefab: {data.get('assetPath', path)}")
128
+ click.echo(f" Type: {data.get('prefabType', 'Unknown')}")
129
+ click.echo(f" Root: {data.get('rootObjectName', 'N/A')}")
130
+ click.echo(f" GUID: {data.get('guid', 'N/A')}")
131
+ click.echo(
132
+ f" Components: {len(data.get('rootComponentTypes', []))}")
133
+ click.echo(f" Children: {data.get('childCount', 0)}")
134
+ if data.get('isVariant'):
135
+ click.echo(f" Variant of: {data.get('parentPrefab', 'N/A')}")
136
+ else:
137
+ click.echo(format_output(result, config.format))
150
138
 
151
139
 
152
140
  @prefab.command("hierarchy")
@@ -161,6 +149,7 @@ def info(path: str, compact: bool):
161
149
  is_flag=True,
162
150
  help="Show prefab nesting information."
163
151
  )
152
+ @handle_unity_errors
164
153
  def hierarchy(path: str, compact: bool, show_prefab_info: bool):
165
154
  """Get the hierarchical structure of a prefab.
166
155
 
@@ -177,41 +166,37 @@ def hierarchy(path: str, compact: bool, show_prefab_info: bool):
177
166
  "prefabPath": path,
178
167
  }
179
168
 
180
- try:
181
- result = run_command("manage_prefabs", params, config)
182
- # Get the actual response data from the wrapped result structure
183
- response_data = result.get("result", result)
184
- if compact and response_data.get("success") and response_data.get("data"):
169
+ result = run_command("manage_prefabs", params, config)
170
+ # Get the actual response data from the wrapped result structure
171
+ response_data = result.get("result", result)
172
+ if compact and response_data.get("success") and response_data.get("data"):
173
+ data = response_data["data"]
174
+ items = data.get("items", [])
175
+ for item in items:
176
+ indent = " " * item.get("path", "").count("/")
177
+ prefab_info = ""
178
+ if show_prefab_info and item.get("prefab", {}).get("isNestedRoot"):
179
+ prefab_info = f" [nested: {item['prefab']['assetPath']}]"
180
+ click.echo(f"{indent}{item.get('name')}{prefab_info}")
181
+ click.echo(f"\nTotal: {data.get('total', 0)} objects")
182
+ elif show_prefab_info:
183
+ # Show prefab info in readable format
184
+ if response_data.get("success") and response_data.get("data"):
185
185
  data = response_data["data"]
186
186
  items = data.get("items", [])
187
187
  for item in items:
188
- indent = " " * item.get("path", "").count("/")
188
+ prefab = item.get("prefab", {})
189
189
  prefab_info = ""
190
- if show_prefab_info and item.get("prefab", {}).get("isNestedRoot"):
191
- prefab_info = f" [nested: {item['prefab']['assetPath']}]"
192
- click.echo(f"{indent}{item.get('name')}{prefab_info}")
190
+ if prefab.get("isRoot"):
191
+ prefab_info = " [root]"
192
+ elif prefab.get("isNestedRoot"):
193
+ prefab_info = f" [nested: {prefab.get('nestingDepth', 0)}]"
194
+ click.echo(f"{item.get('path')}{prefab_info}")
193
195
  click.echo(f"\nTotal: {data.get('total', 0)} objects")
194
- elif show_prefab_info:
195
- # Show prefab info in readable format
196
- if response_data.get("success") and response_data.get("data"):
197
- data = response_data["data"]
198
- items = data.get("items", [])
199
- for item in items:
200
- prefab = item.get("prefab", {})
201
- prefab_info = ""
202
- if prefab.get("isRoot"):
203
- prefab_info = " [root]"
204
- elif prefab.get("isNestedRoot"):
205
- prefab_info = f" [nested: {prefab.get('nestingDepth', 0)}]"
206
- click.echo(f"{item.get('path')}{prefab_info}")
207
- click.echo(f"\nTotal: {data.get('total', 0)} objects")
208
- else:
209
- click.echo(format_output(result, config.format))
210
196
  else:
211
197
  click.echo(format_output(result, config.format))
212
- except UnityConnectionError as e:
213
- print_error(str(e))
214
- sys.exit(1)
198
+ else:
199
+ click.echo(format_output(result, config.format))
215
200
 
216
201
 
217
202
  @prefab.command("create")
@@ -232,6 +217,7 @@ def hierarchy(path: str, compact: bool, show_prefab_info: bool):
232
217
  is_flag=True,
233
218
  help="Unlink from existing prefab before creating new one."
234
219
  )
220
+ @handle_unity_errors
235
221
  def create(target: str, path: str, overwrite: bool, include_inactive: bool, unlink_if_instance: bool):
236
222
  """Create a prefab from a scene GameObject.
237
223
 
@@ -256,11 +242,7 @@ def create(target: str, path: str, overwrite: bool, include_inactive: bool, unli
256
242
  if unlink_if_instance:
257
243
  params["unlinkIfInstance"] = True
258
244
 
259
- try:
260
- result = run_command("manage_prefabs", params, config)
261
- click.echo(format_output(result, config.format))
262
- if result.get("success"):
263
- print_success(f"Created prefab: {path}")
264
- except UnityConnectionError as e:
265
- print_error(str(e))
266
- sys.exit(1)
245
+ result = run_command("manage_prefabs", params, config)
246
+ click.echo(format_output(result, config.format))
247
+ if result.get("success"):
248
+ print_success(f"Created prefab: {path}")
cli/commands/scene.py CHANGED
@@ -6,7 +6,7 @@ from typing import Optional, Any
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, UnityConnectionError
9
+ from cli.utils.connection import run_command, handle_unity_errors
10
10
 
11
11
 
12
12
  @click.group()
@@ -44,6 +44,7 @@ def scene():
44
44
  type=int,
45
45
  help="Pagination cursor."
46
46
  )
47
+ @handle_unity_errors
47
48
  def hierarchy(
48
49
  parent: Optional[str],
49
50
  max_depth: Optional[int],
@@ -75,25 +76,17 @@ def hierarchy(
75
76
  if include_transform:
76
77
  params["includeTransform"] = True
77
78
 
78
- try:
79
- result = run_command("manage_scene", params, config)
80
- click.echo(format_output(result, config.format))
81
- except UnityConnectionError as e:
82
- print_error(str(e))
83
- sys.exit(1)
79
+ result = run_command("manage_scene", params, config)
80
+ click.echo(format_output(result, config.format))
84
81
 
85
82
 
86
83
  @scene.command("active")
84
+ @handle_unity_errors
87
85
  def active():
88
86
  """Get information about the active scene."""
89
87
  config = get_config()
90
-
91
- try:
92
- result = run_command("manage_scene", {"action": "get_active"}, config)
93
- click.echo(format_output(result, config.format))
94
- except UnityConnectionError as e:
95
- print_error(str(e))
96
- sys.exit(1)
88
+ result = run_command("manage_scene", {"action": "get_active"}, config)
89
+ click.echo(format_output(result, config.format))
97
90
 
98
91
 
99
92
  @scene.command("load")
@@ -103,6 +96,7 @@ def active():
103
96
  is_flag=True,
104
97
  help="Load by build index instead of path/name."
105
98
  )
99
+ @handle_unity_errors
106
100
  def load(scene: str, by_index: bool):
107
101
  """Load a scene.
108
102
 
@@ -128,14 +122,10 @@ def load(scene: str, by_index: bool):
128
122
  else:
129
123
  params["name"] = scene
130
124
 
131
- try:
132
- result = run_command("manage_scene", params, config)
133
- click.echo(format_output(result, config.format))
134
- if result.get("success"):
135
- print_success(f"Loaded scene: {scene}")
136
- except UnityConnectionError as e:
137
- print_error(str(e))
138
- sys.exit(1)
125
+ result = run_command("manage_scene", params, config)
126
+ click.echo(format_output(result, config.format))
127
+ if result.get("success"):
128
+ print_success(f"Loaded scene: {scene}")
139
129
 
140
130
 
141
131
  @scene.command("save")
@@ -144,6 +134,7 @@ def load(scene: str, by_index: bool):
144
134
  default=None,
145
135
  help="Path to save the scene to (for new scenes)."
146
136
  )
137
+ @handle_unity_errors
147
138
  def save(path: Optional[str]):
148
139
  """Save the current scene.
149
140
 
@@ -158,14 +149,10 @@ def save(path: Optional[str]):
158
149
  if path:
159
150
  params["path"] = path
160
151
 
161
- try:
162
- result = run_command("manage_scene", params, config)
163
- click.echo(format_output(result, config.format))
164
- if result.get("success"):
165
- print_success("Scene saved")
166
- except UnityConnectionError as e:
167
- print_error(str(e))
168
- sys.exit(1)
152
+ result = run_command("manage_scene", params, config)
153
+ click.echo(format_output(result, config.format))
154
+ if result.get("success"):
155
+ print_success("Scene saved")
169
156
 
170
157
 
171
158
  @scene.command("create")
@@ -175,6 +162,7 @@ def save(path: Optional[str]):
175
162
  default=None,
176
163
  help="Path to create the scene at."
177
164
  )
165
+ @handle_unity_errors
178
166
  def create(name: str, path: Optional[str]):
179
167
  """Create a new scene.
180
168
 
@@ -192,28 +180,19 @@ def create(name: str, path: Optional[str]):
192
180
  if path:
193
181
  params["path"] = path
194
182
 
195
- try:
196
- result = run_command("manage_scene", params, config)
197
- click.echo(format_output(result, config.format))
198
- if result.get("success"):
199
- print_success(f"Created scene: {name}")
200
- except UnityConnectionError as e:
201
- print_error(str(e))
202
- sys.exit(1)
183
+ result = run_command("manage_scene", params, config)
184
+ click.echo(format_output(result, config.format))
185
+ if result.get("success"):
186
+ print_success(f"Created scene: {name}")
203
187
 
204
188
 
205
189
  @scene.command("build-settings")
190
+ @handle_unity_errors
206
191
  def build_settings():
207
192
  """Get scenes in build settings."""
208
193
  config = get_config()
209
-
210
- try:
211
- result = run_command(
212
- "manage_scene", {"action": "get_build_settings"}, config)
213
- click.echo(format_output(result, config.format))
214
- except UnityConnectionError as e:
215
- print_error(str(e))
216
- sys.exit(1)
194
+ result = run_command("manage_scene", {"action": "get_build_settings"}, config)
195
+ click.echo(format_output(result, config.format))
217
196
 
218
197
 
219
198
  @scene.command("screenshot")
@@ -228,6 +207,7 @@ def build_settings():
228
207
  type=int,
229
208
  help="Supersize multiplier (1-4)."
230
209
  )
210
+ @handle_unity_errors
231
211
  def screenshot(filename: Optional[str], supersize: int):
232
212
  """Capture a screenshot of the scene.
233
213
 
@@ -245,11 +225,7 @@ def screenshot(filename: Optional[str], supersize: int):
245
225
  if supersize > 1:
246
226
  params["superSize"] = supersize
247
227
 
248
- try:
249
- result = run_command("manage_scene", params, config)
250
- click.echo(format_output(result, config.format))
251
- if result.get("success"):
252
- print_success("Screenshot captured")
253
- except UnityConnectionError as e:
254
- print_error(str(e))
255
- sys.exit(1)
228
+ result = run_command("manage_scene", params, config)
229
+ click.echo(format_output(result, config.format))
230
+ if result.get("success"):
231
+ print_success("Screenshot captured")