227 lines
5.8 KiB
Python
227 lines
5.8 KiB
Python
"""Shader CLI commands for managing Unity shaders."""
|
|
|
|
import sys
|
|
import click
|
|
from typing import Optional
|
|
|
|
from cli.utils.config import get_config
|
|
from cli.utils.output import format_output, print_error, print_success
|
|
from cli.utils.connection import run_command, handle_unity_errors
|
|
from cli.utils.confirmation import confirm_destructive_action
|
|
|
|
|
|
@click.group()
|
|
def shader():
|
|
"""Shader operations - create, read, update, delete shaders."""
|
|
pass
|
|
|
|
|
|
@shader.command("read")
|
|
@click.argument("path")
|
|
@handle_unity_errors
|
|
def read_shader(path: str):
|
|
"""Read a shader file.
|
|
|
|
\\b
|
|
Examples:
|
|
unity-mcp shader read "Assets/Shaders/MyShader.shader"
|
|
"""
|
|
config = get_config()
|
|
|
|
# Extract name from path
|
|
import os
|
|
name = os.path.splitext(os.path.basename(path))[0]
|
|
directory = os.path.dirname(path)
|
|
|
|
result = run_command("manage_shader", {
|
|
"action": "read",
|
|
"name": name,
|
|
"path": directory or "Assets/",
|
|
}, config)
|
|
|
|
# If successful, display the contents nicely
|
|
if result.get("success") and result.get("data", {}).get("contents"):
|
|
click.echo(result["data"]["contents"])
|
|
else:
|
|
click.echo(format_output(result, config.format))
|
|
|
|
|
|
@shader.command("create")
|
|
@click.argument("name")
|
|
@click.option(
|
|
"--path", "-p",
|
|
default="Assets/Shaders",
|
|
help="Directory to create shader in."
|
|
)
|
|
@click.option(
|
|
"--contents", "-c",
|
|
default=None,
|
|
help="Shader code (reads from stdin if not provided)."
|
|
)
|
|
@click.option(
|
|
"--file", "-f",
|
|
"file_path",
|
|
default=None,
|
|
type=click.Path(exists=True),
|
|
help="Read shader code from file."
|
|
)
|
|
@handle_unity_errors
|
|
def create_shader(name: str, path: str, contents: Optional[str], file_path: Optional[str]):
|
|
"""Create a new shader.
|
|
|
|
\\b
|
|
Examples:
|
|
unity-mcp shader create "MyShader" --path "Assets/Shaders"
|
|
unity-mcp shader create "MyShader" --file local_shader.shader
|
|
echo "Shader code..." | unity-mcp shader create "MyShader"
|
|
"""
|
|
config = get_config()
|
|
|
|
# Get contents from file, option, or stdin
|
|
if file_path:
|
|
with open(file_path, 'r') as f:
|
|
shader_contents = f.read()
|
|
elif contents:
|
|
shader_contents = contents
|
|
else:
|
|
# Read from stdin if available
|
|
import sys
|
|
if not sys.stdin.isatty():
|
|
shader_contents = sys.stdin.read()
|
|
else:
|
|
# Provide default shader template
|
|
shader_contents = f'''Shader "Custom/{name}"
|
|
{{
|
|
Properties
|
|
{{
|
|
_Color ("Color", Color) = (1,1,1,1)
|
|
_MainTex ("Albedo (RGB)", 2D) = "white" {{}}
|
|
}}
|
|
SubShader
|
|
{{
|
|
Tags {{ "RenderType"="Opaque" }}
|
|
LOD 200
|
|
|
|
CGPROGRAM
|
|
#pragma surface surf Standard fullforwardshadows
|
|
#pragma target 3.0
|
|
|
|
sampler2D _MainTex;
|
|
fixed4 _Color;
|
|
|
|
struct Input
|
|
{{
|
|
float2 uv_MainTex;
|
|
}};
|
|
|
|
void surf (Input IN, inout SurfaceOutputStandard o)
|
|
{{
|
|
fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
|
|
o.Albedo = c.rgb;
|
|
o.Alpha = c.a;
|
|
}}
|
|
ENDCG
|
|
}}
|
|
FallBack "Diffuse"
|
|
}}
|
|
'''
|
|
|
|
result = run_command("manage_shader", {
|
|
"action": "create",
|
|
"name": name,
|
|
"path": path,
|
|
"contents": shader_contents,
|
|
}, config)
|
|
click.echo(format_output(result, config.format))
|
|
if result.get("success"):
|
|
print_success(f"Created shader: {path}/{name}.shader")
|
|
|
|
|
|
@shader.command("update")
|
|
@click.argument("path")
|
|
@click.option(
|
|
"--contents", "-c",
|
|
default=None,
|
|
help="New shader code."
|
|
)
|
|
@click.option(
|
|
"--file", "-f",
|
|
"file_path",
|
|
default=None,
|
|
type=click.Path(exists=True),
|
|
help="Read shader code from file."
|
|
)
|
|
@handle_unity_errors
|
|
def update_shader(path: str, contents: Optional[str], file_path: Optional[str]):
|
|
"""Update an existing shader.
|
|
|
|
\\b
|
|
Examples:
|
|
unity-mcp shader update "Assets/Shaders/MyShader.shader" --file updated.shader
|
|
echo "New shader code" | unity-mcp shader update "Assets/Shaders/MyShader.shader"
|
|
"""
|
|
config = get_config()
|
|
|
|
import os
|
|
name = os.path.splitext(os.path.basename(path))[0]
|
|
directory = os.path.dirname(path)
|
|
|
|
# Get contents from file, option, or stdin
|
|
if file_path:
|
|
with open(file_path, 'r') as f:
|
|
shader_contents = f.read()
|
|
elif contents:
|
|
shader_contents = contents
|
|
else:
|
|
import sys
|
|
if not sys.stdin.isatty():
|
|
shader_contents = sys.stdin.read()
|
|
else:
|
|
print_error(
|
|
"No shader contents provided. Use --contents, --file, or pipe via stdin.")
|
|
sys.exit(1)
|
|
|
|
result = run_command("manage_shader", {
|
|
"action": "update",
|
|
"name": name,
|
|
"path": directory or "Assets/",
|
|
"contents": shader_contents,
|
|
}, config)
|
|
click.echo(format_output(result, config.format))
|
|
if result.get("success"):
|
|
print_success(f"Updated shader: {path}")
|
|
|
|
|
|
@shader.command("delete")
|
|
@click.argument("path")
|
|
@click.option(
|
|
"--force", "-f",
|
|
is_flag=True,
|
|
help="Skip confirmation prompt."
|
|
)
|
|
@handle_unity_errors
|
|
def delete_shader(path: str, force: bool):
|
|
"""Delete a shader.
|
|
|
|
\\b
|
|
Examples:
|
|
unity-mcp shader delete "Assets/Shaders/OldShader.shader"
|
|
unity-mcp shader delete "Assets/Shaders/OldShader.shader" --force
|
|
"""
|
|
config = get_config()
|
|
|
|
confirm_destructive_action("Delete", "shader", path, force)
|
|
|
|
import os
|
|
name = os.path.splitext(os.path.basename(path))[0]
|
|
directory = os.path.dirname(path)
|
|
|
|
result = run_command("manage_shader", {
|
|
"action": "delete",
|
|
"name": name,
|
|
"path": directory or "Assets/",
|
|
}, config)
|
|
click.echo(format_output(result, config.format))
|
|
if result.get("success"):
|
|
print_success(f"Deleted shader: {path}")
|