refactor: 拆分 claude-dev-stack 为 windows-dev-stack 和 wsl-dev-stack
将原 claude-dev-stack 目录拆分为独立的 Windows 和 WSL 部署栈,便于分别维护和使用。 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,298 @@
|
||||
@tool
|
||||
extends "res://addons/godot_mcp/commands/base_command.gd"
|
||||
|
||||
|
||||
func get_commands() -> Dictionary:
|
||||
return {
|
||||
"list_animations": _list_animations,
|
||||
"create_animation": _create_animation,
|
||||
"add_animation_track": _add_animation_track,
|
||||
"set_animation_keyframe": _set_animation_keyframe,
|
||||
"get_animation_info": _get_animation_info,
|
||||
"remove_animation": _remove_animation,
|
||||
}
|
||||
|
||||
|
||||
func _find_animation_player(node_path: String) -> AnimationPlayer:
|
||||
var node := find_node_by_path(node_path)
|
||||
if node is AnimationPlayer:
|
||||
return node as AnimationPlayer
|
||||
return null
|
||||
|
||||
|
||||
func _list_animations(params: Dictionary) -> Dictionary:
|
||||
var result := require_string(params, "node_path")
|
||||
if result[1] != null:
|
||||
return result[1]
|
||||
var node_path: String = result[0]
|
||||
|
||||
var player := _find_animation_player(node_path)
|
||||
if player == null:
|
||||
return error_not_found("AnimationPlayer at '%s'" % node_path)
|
||||
|
||||
var animations: Array = []
|
||||
for anim_name in player.get_animation_list():
|
||||
var anim := player.get_animation(anim_name)
|
||||
animations.append({
|
||||
"name": anim_name,
|
||||
"length": anim.length,
|
||||
"loop_mode": anim.loop_mode,
|
||||
"track_count": anim.get_track_count(),
|
||||
})
|
||||
|
||||
return success({"node_path": node_path, "animations": animations, "count": animations.size()})
|
||||
|
||||
|
||||
func _create_animation(params: Dictionary) -> Dictionary:
|
||||
var result := require_string(params, "node_path")
|
||||
if result[1] != null:
|
||||
return result[1]
|
||||
var node_path: String = result[0]
|
||||
|
||||
var result2 := require_string(params, "name")
|
||||
if result2[1] != null:
|
||||
return result2[1]
|
||||
var anim_name: String = result2[0]
|
||||
|
||||
var player := _find_animation_player(node_path)
|
||||
if player == null:
|
||||
return error_not_found("AnimationPlayer at '%s'" % node_path)
|
||||
|
||||
var length: float = float(params.get("length", 1.0))
|
||||
var loop_mode: int = int(params.get("loop_mode", 0)) # 0=none, 1=linear, 2=pingpong
|
||||
|
||||
var anim := Animation.new()
|
||||
anim.length = length
|
||||
anim.loop_mode = loop_mode as Animation.LoopMode
|
||||
|
||||
var lib := player.get_animation_library("")
|
||||
var created_library := false
|
||||
if lib == null:
|
||||
lib = AnimationLibrary.new()
|
||||
created_library = true
|
||||
|
||||
if lib.has_animation(anim_name):
|
||||
return error_invalid_params("Animation '%s' already exists" % anim_name)
|
||||
|
||||
var undo_redo := get_undo_redo()
|
||||
undo_redo.create_action("MCP: Create animation %s" % anim_name)
|
||||
if created_library:
|
||||
undo_redo.add_do_method(player, "add_animation_library", "", lib)
|
||||
undo_redo.add_do_reference(lib)
|
||||
undo_redo.add_undo_method(player, "remove_animation_library", "")
|
||||
undo_redo.add_do_method(lib, "add_animation", anim_name, anim)
|
||||
undo_redo.add_do_reference(anim)
|
||||
undo_redo.add_undo_method(lib, "remove_animation", anim_name)
|
||||
undo_redo.commit_action()
|
||||
|
||||
return success({"name": anim_name, "length": length, "created": true})
|
||||
|
||||
|
||||
func _add_animation_track(params: Dictionary) -> Dictionary:
|
||||
var result := require_string(params, "node_path")
|
||||
if result[1] != null:
|
||||
return result[1]
|
||||
var node_path: String = result[0]
|
||||
|
||||
var result2 := require_string(params, "animation")
|
||||
if result2[1] != null:
|
||||
return result2[1]
|
||||
var anim_name: String = result2[0]
|
||||
|
||||
var result3 := require_string(params, "track_path")
|
||||
if result3[1] != null:
|
||||
return result3[1]
|
||||
var track_path: String = result3[0]
|
||||
|
||||
var player := _find_animation_player(node_path)
|
||||
if player == null:
|
||||
return error_not_found("AnimationPlayer at '%s'" % node_path)
|
||||
|
||||
var anim := player.get_animation(anim_name)
|
||||
if anim == null:
|
||||
return error_not_found("Animation '%s'" % anim_name)
|
||||
|
||||
var track_type_str: String = optional_string(params, "track_type", "value")
|
||||
var track_type: int
|
||||
match track_type_str:
|
||||
"value": track_type = Animation.TYPE_VALUE
|
||||
"position_2d": track_type = Animation.TYPE_POSITION_3D # Godot uses 3D type for 2D too
|
||||
"rotation_2d": track_type = Animation.TYPE_ROTATION_3D
|
||||
"scale_2d": track_type = Animation.TYPE_SCALE_3D
|
||||
"method": track_type = Animation.TYPE_METHOD
|
||||
"bezier": track_type = Animation.TYPE_BEZIER
|
||||
"blend_shape": track_type = Animation.TYPE_BLEND_SHAPE
|
||||
_: track_type = Animation.TYPE_VALUE
|
||||
|
||||
var track_idx := anim.get_track_count()
|
||||
var undo_redo := get_undo_redo()
|
||||
undo_redo.create_action("MCP: Add animation track")
|
||||
undo_redo.add_do_method(anim, "add_track", track_type, track_idx)
|
||||
undo_redo.add_do_method(anim, "track_set_path", track_idx, NodePath(track_path))
|
||||
|
||||
var update_mode_str: String = optional_string(params, "update_mode", "")
|
||||
if not update_mode_str.is_empty() and track_type == Animation.TYPE_VALUE:
|
||||
match update_mode_str:
|
||||
"continuous": undo_redo.add_do_method(anim, "value_track_set_update_mode", track_idx, Animation.UPDATE_CONTINUOUS)
|
||||
"discrete": undo_redo.add_do_method(anim, "value_track_set_update_mode", track_idx, Animation.UPDATE_DISCRETE)
|
||||
"capture": undo_redo.add_do_method(anim, "value_track_set_update_mode", track_idx, Animation.UPDATE_CAPTURE)
|
||||
undo_redo.add_undo_method(anim, "remove_track", track_idx)
|
||||
undo_redo.commit_action()
|
||||
|
||||
return success({"track_index": track_idx, "track_path": track_path, "track_type": track_type_str})
|
||||
|
||||
|
||||
func _set_animation_keyframe(params: Dictionary) -> Dictionary:
|
||||
var result := require_string(params, "node_path")
|
||||
if result[1] != null:
|
||||
return result[1]
|
||||
var node_path: String = result[0]
|
||||
|
||||
var result2 := require_string(params, "animation")
|
||||
if result2[1] != null:
|
||||
return result2[1]
|
||||
var anim_name: String = result2[0]
|
||||
|
||||
var player := _find_animation_player(node_path)
|
||||
if player == null:
|
||||
return error_not_found("AnimationPlayer at '%s'" % node_path)
|
||||
|
||||
var anim := player.get_animation(anim_name)
|
||||
if anim == null:
|
||||
return error_not_found("Animation '%s'" % anim_name)
|
||||
|
||||
var track_index: int = int(params.get("track_index", 0))
|
||||
if track_index < 0 or track_index >= anim.get_track_count():
|
||||
return error_invalid_params("Invalid track_index: %d" % track_index)
|
||||
|
||||
var time: float = float(params.get("time", 0.0))
|
||||
var value = params.get("value")
|
||||
|
||||
# Parse value string for common types
|
||||
if value is String:
|
||||
var s: String = value
|
||||
var expr := Expression.new()
|
||||
if expr.parse(s) == OK:
|
||||
var parsed = expr.execute()
|
||||
if parsed != null:
|
||||
value = parsed
|
||||
|
||||
var easing: float = float(params.get("easing", 1.0))
|
||||
var old_key_idx := _find_animation_key_at_time(anim, track_index, time)
|
||||
var had_old_key := old_key_idx >= 0
|
||||
var old_value: Variant = anim.track_get_key_value(track_index, old_key_idx) if had_old_key else null
|
||||
var old_easing: float = anim.track_get_key_transition(track_index, old_key_idx) if had_old_key else 1.0
|
||||
|
||||
var undo_redo := get_undo_redo()
|
||||
undo_redo.create_action("MCP: Set animation keyframe")
|
||||
undo_redo.add_do_method(self, "_upsert_animation_key", anim, track_index, time, value, easing)
|
||||
undo_redo.add_undo_method(self, "_restore_animation_key", anim, track_index, time, had_old_key, old_value, old_easing)
|
||||
undo_redo.commit_action()
|
||||
|
||||
var key_idx := _find_animation_key_at_time(anim, track_index, time)
|
||||
|
||||
return success({"track_index": track_index, "time": time, "key_index": key_idx, "easing": anim.track_get_key_transition(track_index, key_idx)})
|
||||
|
||||
|
||||
func _get_animation_info(params: Dictionary) -> Dictionary:
|
||||
var result := require_string(params, "node_path")
|
||||
if result[1] != null:
|
||||
return result[1]
|
||||
var node_path: String = result[0]
|
||||
|
||||
var result2 := require_string(params, "animation")
|
||||
if result2[1] != null:
|
||||
return result2[1]
|
||||
var anim_name: String = result2[0]
|
||||
|
||||
var player := _find_animation_player(node_path)
|
||||
if player == null:
|
||||
return error_not_found("AnimationPlayer at '%s'" % node_path)
|
||||
|
||||
var anim := player.get_animation(anim_name)
|
||||
if anim == null:
|
||||
return error_not_found("Animation '%s'" % anim_name)
|
||||
|
||||
var tracks: Array = []
|
||||
for i in anim.get_track_count():
|
||||
var track_info := {
|
||||
"index": i,
|
||||
"path": str(anim.track_get_path(i)),
|
||||
"type": anim.track_get_type(i),
|
||||
"key_count": anim.track_get_key_count(i),
|
||||
}
|
||||
var keys: Array = []
|
||||
for k in anim.track_get_key_count(i):
|
||||
keys.append({
|
||||
"time": anim.track_get_key_time(i, k),
|
||||
"value": str(anim.track_get_key_value(i, k)),
|
||||
"easing": anim.track_get_key_transition(i, k),
|
||||
})
|
||||
track_info["keys"] = keys
|
||||
tracks.append(track_info)
|
||||
|
||||
return success({
|
||||
"name": anim_name,
|
||||
"length": anim.length,
|
||||
"loop_mode": anim.loop_mode,
|
||||
"step": anim.step,
|
||||
"tracks": tracks,
|
||||
})
|
||||
|
||||
|
||||
func _remove_animation(params: Dictionary) -> Dictionary:
|
||||
var result := require_string(params, "node_path")
|
||||
if result[1] != null:
|
||||
return result[1]
|
||||
var node_path: String = result[0]
|
||||
|
||||
var result2 := require_string(params, "name")
|
||||
if result2[1] != null:
|
||||
return result2[1]
|
||||
var anim_name: String = result2[0]
|
||||
|
||||
var player := _find_animation_player(node_path)
|
||||
if player == null:
|
||||
return error_not_found("AnimationPlayer at '%s'" % node_path)
|
||||
|
||||
var lib := player.get_animation_library("")
|
||||
if lib == null or not lib.has_animation(anim_name):
|
||||
return error_not_found("Animation '%s'" % anim_name)
|
||||
|
||||
var anim := lib.get_animation(anim_name)
|
||||
var undo_redo := get_undo_redo()
|
||||
undo_redo.create_action("MCP: Remove animation %s" % anim_name)
|
||||
undo_redo.add_do_method(lib, "remove_animation", anim_name)
|
||||
undo_redo.add_undo_method(lib, "add_animation", anim_name, anim)
|
||||
undo_redo.add_undo_reference(anim)
|
||||
undo_redo.commit_action()
|
||||
return success({"name": anim_name, "removed": true})
|
||||
|
||||
|
||||
func _find_animation_key_at_time(anim: Animation, track_index: int, time: float) -> int:
|
||||
for key_index: int in anim.track_get_key_count(track_index):
|
||||
if is_equal_approx(anim.track_get_key_time(track_index, key_index), time):
|
||||
return key_index
|
||||
return -1
|
||||
|
||||
|
||||
func _upsert_animation_key(anim: Animation, track_index: int, time: float, value: Variant, easing: float) -> void:
|
||||
var key_idx := _find_animation_key_at_time(anim, track_index, time)
|
||||
if key_idx < 0:
|
||||
key_idx = anim.track_insert_key(track_index, time, value)
|
||||
else:
|
||||
anim.track_set_key_value(track_index, key_idx, value)
|
||||
if easing != 1.0:
|
||||
anim.track_set_key_transition(track_index, key_idx, easing)
|
||||
|
||||
|
||||
func _restore_animation_key(anim: Animation, track_index: int, time: float, had_old_key: bool, old_value: Variant, old_easing: float) -> void:
|
||||
var key_idx := _find_animation_key_at_time(anim, track_index, time)
|
||||
if had_old_key:
|
||||
if key_idx < 0:
|
||||
key_idx = anim.track_insert_key(track_index, time, old_value)
|
||||
else:
|
||||
anim.track_set_key_value(track_index, key_idx, old_value)
|
||||
anim.track_set_key_transition(track_index, key_idx, old_easing)
|
||||
elif key_idx >= 0:
|
||||
anim.track_remove_key(track_index, key_idx)
|
||||
Reference in New Issue
Block a user