godot-mcp-tool 0.0.0-stage → 0.1.0
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 +57 -2
- package/addon/godot_mcp_tool/addon_info.gd +10 -0
- package/addon/godot_mcp_tool/addon_info.gd.uid +1 -0
- package/addon/godot_mcp_tool/animation/animation_reference.gd +50 -0
- package/addon/godot_mcp_tool/animation/animation_reference.gd.uid +1 -0
- package/addon/godot_mcp_tool/animation/animation_report.gd +48 -0
- package/addon/godot_mcp_tool/animation/animation_report.gd.uid +1 -0
- package/addon/godot_mcp_tool/animation/animation_track_planner.gd +188 -0
- package/addon/godot_mcp_tool/animation/animation_track_planner.gd.uid +1 -0
- package/addon/godot_mcp_tool/animation/animation_vocabulary.gd +50 -0
- package/addon/godot_mcp_tool/animation/animation_vocabulary.gd.uid +1 -0
- package/addon/godot_mcp_tool/animation/state_machine_plan.gd +157 -0
- package/addon/godot_mcp_tool/animation/state_machine_plan.gd.uid +1 -0
- package/addon/godot_mcp_tool/animation/state_machine_report.gd +74 -0
- package/addon/godot_mcp_tool/animation/state_machine_report.gd.uid +1 -0
- package/addon/godot_mcp_tool/assets/import_options.gd +75 -0
- package/addon/godot_mcp_tool/assets/import_options.gd.uid +1 -0
- package/addon/godot_mcp_tool/assets/import_settings.gd +92 -0
- package/addon/godot_mcp_tool/assets/import_settings.gd.uid +1 -0
- package/addon/godot_mcp_tool/assets/imported_scene_report.gd +69 -0
- package/addon/godot_mcp_tool/assets/imported_scene_report.gd.uid +1 -0
- package/addon/godot_mcp_tool/bridge/authenticator.gd +39 -0
- package/addon/godot_mcp_tool/bridge/authenticator.gd.uid +1 -0
- package/addon/godot_mcp_tool/bridge/bridge_connection.gd +84 -0
- package/addon/godot_mcp_tool/bridge/bridge_connection.gd.uid +1 -0
- package/addon/godot_mcp_tool/bridge/bridge_probe.gd +29 -0
- package/addon/godot_mcp_tool/bridge/bridge_probe.gd.uid +1 -0
- package/addon/godot_mcp_tool/bridge/bridge_server.gd +53 -0
- package/addon/godot_mcp_tool/bridge/bridge_server.gd.uid +1 -0
- package/addon/godot_mcp_tool/bridge/bridge_session.gd +126 -0
- package/addon/godot_mcp_tool/bridge/bridge_session.gd.uid +1 -0
- package/addon/godot_mcp_tool/bridge/discovery_file.gd +67 -0
- package/addon/godot_mcp_tool/bridge/discovery_file.gd.uid +1 -0
- package/addon/godot_mcp_tool/bridge/json_rpc.gd +37 -0
- package/addon/godot_mcp_tool/bridge/json_rpc.gd.uid +1 -0
- package/addon/godot_mcp_tool/bridge/ndjson_buffer.gd +31 -0
- package/addon/godot_mcp_tool/bridge/ndjson_buffer.gd.uid +1 -0
- package/addon/godot_mcp_tool/bridge/token_generator.gd +7 -0
- package/addon/godot_mcp_tool/bridge/token_generator.gd.uid +1 -0
- package/addon/godot_mcp_tool/capture/bounds.gd +58 -0
- package/addon/godot_mcp_tool/capture/bounds.gd.uid +1 -0
- package/addon/godot_mcp_tool/capture/bounds_report.gd +50 -0
- package/addon/godot_mcp_tool/capture/bounds_report.gd.uid +1 -0
- package/addon/godot_mcp_tool/capture/camera_views.gd +28 -0
- package/addon/godot_mcp_tool/capture/camera_views.gd.uid +1 -0
- package/addon/godot_mcp_tool/capture/capture_params.gd +29 -0
- package/addon/godot_mcp_tool/capture/capture_params.gd.uid +1 -0
- package/addon/godot_mcp_tool/capture/capture_store.gd +45 -0
- package/addon/godot_mcp_tool/capture/capture_store.gd.uid +1 -0
- package/addon/godot_mcp_tool/capture/image_fitter.gd +44 -0
- package/addon/godot_mcp_tool/capture/image_fitter.gd.uid +1 -0
- package/addon/godot_mcp_tool/capture/preview_lighting.gd +22 -0
- package/addon/godot_mcp_tool/capture/preview_lighting.gd.uid +1 -0
- package/addon/godot_mcp_tool/capture/screenshot_file.gd +22 -0
- package/addon/godot_mcp_tool/capture/screenshot_file.gd.uid +1 -0
- package/addon/godot_mcp_tool/capture/view_renderer.gd +67 -0
- package/addon/godot_mcp_tool/capture/view_renderer.gd.uid +1 -0
- package/addon/godot_mcp_tool/capture/view_requests.gd +125 -0
- package/addon/godot_mcp_tool/capture/view_requests.gd.uid +1 -0
- package/addon/godot_mcp_tool/codec/converters/array_converter.gd +70 -0
- package/addon/godot_mcp_tool/codec/converters/array_converter.gd.uid +1 -0
- package/addon/godot_mcp_tool/codec/converters/color_converter.gd +40 -0
- package/addon/godot_mcp_tool/codec/converters/color_converter.gd.uid +1 -0
- package/addon/godot_mcp_tool/codec/converters/converter.gd +82 -0
- package/addon/godot_mcp_tool/codec/converters/converter.gd.uid +1 -0
- package/addon/godot_mcp_tool/codec/converters/dictionary_converter.gd +19 -0
- package/addon/godot_mcp_tool/codec/converters/dictionary_converter.gd.uid +1 -0
- package/addon/godot_mcp_tool/codec/converters/enum_converter.gd +54 -0
- package/addon/godot_mcp_tool/codec/converters/enum_converter.gd.uid +1 -0
- package/addon/godot_mcp_tool/codec/converters/flags_converter.gd +60 -0
- package/addon/godot_mcp_tool/codec/converters/flags_converter.gd.uid +1 -0
- package/addon/godot_mcp_tool/codec/converters/godot_syntax_converter.gd +23 -0
- package/addon/godot_mcp_tool/codec/converters/godot_syntax_converter.gd.uid +1 -0
- package/addon/godot_mcp_tool/codec/converters/node_reference_converter.gd +25 -0
- package/addon/godot_mcp_tool/codec/converters/node_reference_converter.gd.uid +1 -0
- package/addon/godot_mcp_tool/codec/converters/primitive_converter.gd +25 -0
- package/addon/godot_mcp_tool/codec/converters/primitive_converter.gd.uid +1 -0
- package/addon/godot_mcp_tool/codec/converters/resource_converter.gd +82 -0
- package/addon/godot_mcp_tool/codec/converters/resource_converter.gd.uid +1 -0
- package/addon/godot_mcp_tool/codec/converters/untyped_converter.gd +11 -0
- package/addon/godot_mcp_tool/codec/converters/untyped_converter.gd.uid +1 -0
- package/addon/godot_mcp_tool/codec/converters/vector_converter.gd +68 -0
- package/addon/godot_mcp_tool/codec/converters/vector_converter.gd.uid +1 -0
- package/addon/godot_mcp_tool/codec/decode_outcome.gd +11 -0
- package/addon/godot_mcp_tool/codec/decode_outcome.gd.uid +1 -0
- package/addon/godot_mcp_tool/codec/enum_options.gd +24 -0
- package/addon/godot_mcp_tool/codec/enum_options.gd.uid +1 -0
- package/addon/godot_mcp_tool/codec/value_comparison.gd +66 -0
- package/addon/godot_mcp_tool/codec/value_comparison.gd.uid +1 -0
- package/addon/godot_mcp_tool/codec/value_decoder.gd +7 -0
- package/addon/godot_mcp_tool/codec/value_decoder.gd.uid +1 -0
- package/addon/godot_mcp_tool/codec/variant_codec.gd +94 -0
- package/addon/godot_mcp_tool/codec/variant_codec.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/animation/animation_delete_command.gd +47 -0
- package/addon/godot_mcp_tool/commands/animation/animation_delete_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/animation/animation_get_command.gd +51 -0
- package/addon/godot_mcp_tool/commands/animation/animation_get_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/animation/animation_set_command.gd +104 -0
- package/addon/godot_mcp_tool/commands/animation/animation_set_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/animation/animation_tree_get_command.gd +39 -0
- package/addon/godot_mcp_tool/commands/animation/animation_tree_get_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/animation/animation_tree_set_command.gd +92 -0
- package/addon/godot_mcp_tool/commands/animation/animation_tree_set_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/asset/asset_import_settings_get_command.gd +53 -0
- package/addon/godot_mcp_tool/commands/asset/asset_import_settings_get_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/asset/asset_import_settings_set_command.gd +112 -0
- package/addon/godot_mcp_tool/commands/asset/asset_import_settings_set_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/command.gd +8 -0
- package/addon/godot_mcp_tool/commands/command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/command_catalog.gd +135 -0
- package/addon/godot_mcp_tool/commands/command_catalog.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/command_error.gd +11 -0
- package/addon/godot_mcp_tool/commands/command_error.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/command_router.gd +19 -0
- package/addon/godot_mcp_tool/commands/command_router.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/editor/editor_breakpoints_command.gd +13 -0
- package/addon/godot_mcp_tool/commands/editor/editor_breakpoints_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/editor/editor_rescan_command.gd +30 -0
- package/addon/godot_mcp_tool/commands/editor/editor_rescan_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/editor/editor_run_script_command.gd +55 -0
- package/addon/godot_mcp_tool/commands/editor/editor_run_script_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/editor/editor_screenshot_command.gd +75 -0
- package/addon/godot_mcp_tool/commands/editor/editor_screenshot_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/editor/editor_select_command.gd +69 -0
- package/addon/godot_mcp_tool/commands/editor/editor_select_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/editor/editor_unsaved_files_command.gd +26 -0
- package/addon/godot_mcp_tool/commands/editor/editor_unsaved_files_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/file/filesystem_delete_command.gd +112 -0
- package/addon/godot_mcp_tool/commands/file/filesystem_delete_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/file/filesystem_move_command.gd +174 -0
- package/addon/godot_mcp_tool/commands/file/filesystem_move_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/file/resource_find_usages_command.gd +24 -0
- package/addon/godot_mcp_tool/commands/file/resource_find_usages_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/game/game_get_output_command.gd +31 -0
- package/addon/godot_mcp_tool/commands/game/game_get_output_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/game/game_request_command.gd +32 -0
- package/addon/godot_mcp_tool/commands/game/game_request_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/game/game_run_command.gd +117 -0
- package/addon/godot_mcp_tool/commands/game/game_run_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/game/game_stop_command.gd +22 -0
- package/addon/godot_mcp_tool/commands/game/game_stop_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/input/input_map_get_command.gd +25 -0
- package/addon/godot_mcp_tool/commands/input/input_map_get_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/input/input_map_set_command.gd +89 -0
- package/addon/godot_mcp_tool/commands/input/input_map_set_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/navigation/navigation_bake_command.gd +90 -0
- package/addon/godot_mcp_tool/commands/navigation/navigation_bake_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/node/node_add_command.gd +7 -0
- package/addon/godot_mcp_tool/commands/node/node_add_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/node/node_call_method_command.gd +102 -0
- package/addon/godot_mcp_tool/commands/node/node_call_method_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/node/node_delete_command.gd +7 -0
- package/addon/godot_mcp_tool/commands/node/node_delete_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/node/node_duplicate_command.gd +7 -0
- package/addon/godot_mcp_tool/commands/node/node_duplicate_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/node/node_find_command.gd +55 -0
- package/addon/godot_mcp_tool/commands/node/node_find_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/node/node_get_bounds_command.gd +49 -0
- package/addon/godot_mcp_tool/commands/node/node_get_bounds_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/node/node_get_properties_command.gd +40 -0
- package/addon/godot_mcp_tool/commands/node/node_get_properties_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/node/node_reparent_command.gd +7 -0
- package/addon/godot_mcp_tool/commands/node/node_reparent_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/node/node_set_groups_command.gd +7 -0
- package/addon/godot_mcp_tool/commands/node/node_set_groups_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/node/node_set_properties_command.gd +7 -0
- package/addon/godot_mcp_tool/commands/node/node_set_properties_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/params.gd +65 -0
- package/addon/godot_mcp_tool/commands/params.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/ping_command.gd +5 -0
- package/addon/godot_mcp_tool/commands/ping_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/project/autoload_add_command.gd +55 -0
- package/addon/godot_mcp_tool/commands/project/autoload_add_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/project/autoload_remove_command.gd +32 -0
- package/addon/godot_mcp_tool/commands/project/autoload_remove_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/project/project_info_command.gd +43 -0
- package/addon/godot_mcp_tool/commands/project/project_info_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/project/project_settings_get_command.gd +55 -0
- package/addon/godot_mcp_tool/commands/project/project_settings_get_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/project/project_settings_set_command.gd +49 -0
- package/addon/godot_mcp_tool/commands/project/project_settings_set_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/resource/resource_create_command.gd +41 -0
- package/addon/godot_mcp_tool/commands/resource/resource_create_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/resource/resource_get_command.gd +31 -0
- package/addon/godot_mcp_tool/commands/resource/resource_get_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/resource/resource_set_properties_command.gd +42 -0
- package/addon/godot_mcp_tool/commands/resource/resource_set_properties_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/scene/scene_batch_edit_command.gd +91 -0
- package/addon/godot_mcp_tool/commands/scene/scene_batch_edit_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/scene/scene_close_command.gd +70 -0
- package/addon/godot_mcp_tool/commands/scene/scene_close_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/scene/scene_create_command.gd +77 -0
- package/addon/godot_mcp_tool/commands/scene/scene_create_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/scene/scene_get_tree_command.gd +39 -0
- package/addon/godot_mcp_tool/commands/scene/scene_get_tree_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/scene/scene_open_command.gd +33 -0
- package/addon/godot_mcp_tool/commands/scene/scene_open_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/scene/scene_save_command.gd +42 -0
- package/addon/godot_mcp_tool/commands/scene/scene_save_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/scene_edit_command.gd +33 -0
- package/addon/godot_mcp_tool/commands/scene_edit_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/signal/signal_connect_command.gd +7 -0
- package/addon/godot_mcp_tool/commands/signal/signal_connect_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/signal/signal_disconnect_command.gd +7 -0
- package/addon/godot_mcp_tool/commands/signal/signal_disconnect_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/signal/signal_list_command.gd +58 -0
- package/addon/godot_mcp_tool/commands/signal/signal_list_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/commands/unsafe_command.gd +21 -0
- package/addon/godot_mcp_tool/commands/unsafe_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/editor/autoload_registry.gd +9 -0
- package/addon/godot_mcp_tool/editor/autoload_registry.gd.uid +1 -0
- package/addon/godot_mcp_tool/editor/bottom_panel.gd +26 -0
- package/addon/godot_mcp_tool/editor/bottom_panel.gd.uid +1 -0
- package/addon/godot_mcp_tool/editor/command_journal.gd +32 -0
- package/addon/godot_mcp_tool/editor/command_journal.gd.uid +1 -0
- package/addon/godot_mcp_tool/editor/editor_autoload_registry.gd +21 -0
- package/addon/godot_mcp_tool/editor/editor_autoload_registry.gd.uid +1 -0
- package/addon/godot_mcp_tool/editor/editor_file_system_access.gd +32 -0
- package/addon/godot_mcp_tool/editor/editor_file_system_access.gd.uid +1 -0
- package/addon/godot_mcp_tool/editor/editor_script_editor_access.gd +46 -0
- package/addon/godot_mcp_tool/editor/editor_script_editor_access.gd.uid +1 -0
- package/addon/godot_mcp_tool/editor/editor_services.gd +225 -0
- package/addon/godot_mcp_tool/editor/editor_services.gd.uid +1 -0
- package/addon/godot_mcp_tool/editor/editor_viewport_access.gd +33 -0
- package/addon/godot_mcp_tool/editor/editor_viewport_access.gd.uid +1 -0
- package/addon/godot_mcp_tool/editor/file_system_access.gd +21 -0
- package/addon/godot_mcp_tool/editor/file_system_access.gd.uid +1 -0
- package/addon/godot_mcp_tool/editor/file_trash.gd +5 -0
- package/addon/godot_mcp_tool/editor/file_trash.gd.uid +1 -0
- package/addon/godot_mcp_tool/editor/first_scan_gate.gd +25 -0
- package/addon/godot_mcp_tool/editor/first_scan_gate.gd.uid +1 -0
- package/addon/godot_mcp_tool/editor/godot_version_text.gd +15 -0
- package/addon/godot_mcp_tool/editor/godot_version_text.gd.uid +1 -0
- package/addon/godot_mcp_tool/editor/mcp_dock.gd +114 -0
- package/addon/godot_mcp_tool/editor/mcp_dock.gd.uid +1 -0
- package/addon/godot_mcp_tool/editor/responsiveness_controller.gd +36 -0
- package/addon/godot_mcp_tool/editor/responsiveness_controller.gd.uid +1 -0
- package/addon/godot_mcp_tool/editor/responsiveness_policy.gd +10 -0
- package/addon/godot_mcp_tool/editor/responsiveness_policy.gd.uid +1 -0
- package/addon/godot_mcp_tool/editor/script_editor_access.gd +21 -0
- package/addon/godot_mcp_tool/editor/script_editor_access.gd.uid +1 -0
- package/addon/godot_mcp_tool/editor/script_error_capture.gd +19 -0
- package/addon/godot_mcp_tool/editor/script_error_capture.gd.uid +1 -0
- package/addon/godot_mcp_tool/editor/script_sync.gd +40 -0
- package/addon/godot_mcp_tool/editor/script_sync.gd.uid +1 -0
- package/addon/godot_mcp_tool/editor/supported_engine.gd +15 -0
- package/addon/godot_mcp_tool/editor/supported_engine.gd.uid +1 -0
- package/addon/godot_mcp_tool/editor/unsafe_tools_switch.gd +40 -0
- package/addon/godot_mcp_tool/editor/unsafe_tools_switch.gd.uid +1 -0
- package/addon/godot_mcp_tool/files/file_usages.gd +84 -0
- package/addon/godot_mcp_tool/files/file_usages.gd.uid +1 -0
- package/addon/godot_mcp_tool/files/project_file_index.gd +28 -0
- package/addon/godot_mcp_tool/files/project_file_index.gd.uid +1 -0
- package/addon/godot_mcp_tool/files/project_paths.gd +43 -0
- package/addon/godot_mcp_tool/files/project_paths.gd.uid +1 -0
- package/addon/godot_mcp_tool/files/reference_rewriter.gd +29 -0
- package/addon/godot_mcp_tool/files/reference_rewriter.gd.uid +1 -0
- package/addon/godot_mcp_tool/input/input_actions.gd +53 -0
- package/addon/godot_mcp_tool/input/input_actions.gd.uid +1 -0
- package/addon/godot_mcp_tool/input/input_event_codec.gd +178 -0
- package/addon/godot_mcp_tool/input/input_event_codec.gd.uid +1 -0
- package/addon/godot_mcp_tool/navigation/navigation_bake_report.gd +79 -0
- package/addon/godot_mcp_tool/navigation/navigation_bake_report.gd.uid +1 -0
- package/addon/godot_mcp_tool/plugin.cfg +7 -0
- package/addon/godot_mcp_tool/plugin.gd +43 -0
- package/addon/godot_mcp_tool/plugin.gd.uid +1 -0
- package/addon/godot_mcp_tool/project/autoload_list.gd +34 -0
- package/addon/godot_mcp_tool/project/autoload_list.gd.uid +1 -0
- package/addon/godot_mcp_tool/project/autoload_names.gd +38 -0
- package/addon/godot_mcp_tool/project/autoload_names.gd.uid +1 -0
- package/addon/godot_mcp_tool/project/global_class_summary.gd +26 -0
- package/addon/godot_mcp_tool/project/global_class_summary.gd.uid +1 -0
- package/addon/godot_mcp_tool/project/project_query.gd +66 -0
- package/addon/godot_mcp_tool/project/project_query.gd.uid +1 -0
- package/addon/godot_mcp_tool/project/script_indentation.gd +39 -0
- package/addon/godot_mcp_tool/project/script_indentation.gd.uid +1 -0
- package/addon/godot_mcp_tool/resources/resource_factory.gd +59 -0
- package/addon/godot_mcp_tool/resources/resource_factory.gd.uid +1 -0
- package/addon/godot_mcp_tool/resources/resource_files.gd +70 -0
- package/addon/godot_mcp_tool/resources/resource_files.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/debugger_sink.gd +15 -0
- package/addon/godot_mcp_tool/runtime/debugger_sink.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/editor_game_launcher.gd +31 -0
- package/addon/godot_mcp_tool/runtime/editor_game_launcher.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/game_channel.gd +61 -0
- package/addon/godot_mcp_tool/runtime/game_channel.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_bounds_command.gd +31 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_bounds_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_command_catalog.gd +40 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_command_catalog.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_eval_command.gd +40 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_eval_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_input_command.gd +308 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_input_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_pause_command.gd +23 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_pause_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_performance_command.gd +75 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_performance_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_properties_get_command.gd +78 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_properties_get_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_properties_set_command.gd +35 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_properties_set_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_scene.gd +54 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_scene.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_screenshot_command.gd +66 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_screenshot_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_step_command.gd +28 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_step_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_tree_command.gd +29 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_tree_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_wait_command.gd +103 -0
- package/addon/godot_mcp_tool/runtime/game_commands/game_wait_command.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/game_launcher.gd +29 -0
- package/addon/godot_mcp_tool/runtime/game_launcher.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/game_request_responder.gd +28 -0
- package/addon/godot_mcp_tool/runtime/game_request_responder.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/game_state.gd +53 -0
- package/addon/godot_mcp_tool/runtime/game_state.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/game_time.gd +69 -0
- package/addon/godot_mcp_tool/runtime/game_time.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/log_entry_builder.gd +58 -0
- package/addon/godot_mcp_tool/runtime/log_entry_builder.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/log_file_writer.gd +38 -0
- package/addon/godot_mcp_tool/runtime/log_file_writer.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/log_store.gd +77 -0
- package/addon/godot_mcp_tool/runtime/log_store.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/run_arguments.gd +21 -0
- package/addon/godot_mcp_tool/runtime/run_arguments.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/run_request.gd +7 -0
- package/addon/godot_mcp_tool/runtime/run_request.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/runtime_activation.gd +13 -0
- package/addon/godot_mcp_tool/runtime/runtime_activation.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/runtime_agent.gd +108 -0
- package/addon/godot_mcp_tool/runtime/runtime_agent.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/runtime_context.gd +18 -0
- package/addon/godot_mcp_tool/runtime/runtime_context.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/runtime_debugger.gd +65 -0
- package/addon/godot_mcp_tool/runtime/runtime_debugger.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/runtime_logger.gd +57 -0
- package/addon/godot_mcp_tool/runtime/runtime_logger.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/runtime_protocol.gd +8 -0
- package/addon/godot_mcp_tool/runtime/runtime_protocol.gd.uid +1 -0
- package/addon/godot_mcp_tool/runtime/server_connection.gd +70 -0
- package/addon/godot_mcp_tool/runtime/server_connection.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/change_set.gd +79 -0
- package/addon/godot_mcp_tool/scene/change_set.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/editing_context.gd +26 -0
- package/addon/godot_mcp_tool/scene/editing_context.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/editor_scene_access.gd +64 -0
- package/addon/godot_mcp_tool/scene/editor_scene_access.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/editor_undo_history.gd +39 -0
- package/addon/godot_mcp_tool/scene/editor_undo_history.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/edits/group_change.gd +71 -0
- package/addon/godot_mcp_tool/scene/edits/group_change.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/edits/node_addition.gd +47 -0
- package/addon/godot_mcp_tool/scene/edits/node_addition.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/edits/node_deletion.gd +51 -0
- package/addon/godot_mcp_tool/scene/edits/node_deletion.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/edits/node_duplication.gd +63 -0
- package/addon/godot_mcp_tool/scene/edits/node_duplication.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/edits/node_move.gd +109 -0
- package/addon/godot_mcp_tool/scene/edits/node_move.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/edits/property_change.gd +37 -0
- package/addon/godot_mcp_tool/scene/edits/property_change.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/edits/scene_edit.gd +47 -0
- package/addon/godot_mcp_tool/scene/edits/scene_edit.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/edits/signal_connection.gd +74 -0
- package/addon/godot_mcp_tool/scene/edits/signal_connection.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/edits/signal_disconnection.gd +61 -0
- package/addon/godot_mcp_tool/scene/edits/signal_disconnection.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/node_factory.gd +73 -0
- package/addon/godot_mcp_tool/scene/node_factory.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/node_locator.gd +45 -0
- package/addon/godot_mcp_tool/scene/node_locator.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/node_matcher.gd +52 -0
- package/addon/godot_mcp_tool/scene/node_matcher.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/node_path_updates.gd +70 -0
- package/addon/godot_mcp_tool/scene/node_path_updates.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/plain_undo_history.gd +51 -0
- package/addon/godot_mcp_tool/scene/plain_undo_history.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/property_editor.gd +211 -0
- package/addon/godot_mcp_tool/scene/property_editor.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/scene_access.gd +45 -0
- package/addon/godot_mcp_tool/scene/scene_access.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/scene_resolver.gd +95 -0
- package/addon/godot_mcp_tool/scene/scene_resolver.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/scene_snapshot.gd +16 -0
- package/addon/godot_mcp_tool/scene/scene_snapshot.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/scene_tree_describer.gd +69 -0
- package/addon/godot_mcp_tool/scene/scene_tree_describer.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/signal_catalog.gd +112 -0
- package/addon/godot_mcp_tool/scene/signal_catalog.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/spatial_transforms.gd +12 -0
- package/addon/godot_mcp_tool/scene/spatial_transforms.gd.uid +1 -0
- package/addon/godot_mcp_tool/scene/undo_history.gd +44 -0
- package/addon/godot_mcp_tool/scene/undo_history.gd.uid +1 -0
- package/addon/godot_mcp_tool/util/global_classes.gd +24 -0
- package/addon/godot_mcp_tool/util/global_classes.gd.uid +1 -0
- package/addon/godot_mcp_tool/util/indefinite_article.gd +8 -0
- package/addon/godot_mcp_tool/util/indefinite_article.gd.uid +1 -0
- package/addon/godot_mcp_tool/util/number_text.gd +5 -0
- package/addon/godot_mcp_tool/util/number_text.gd.uid +1 -0
- package/addon/godot_mcp_tool/util/resource_paths.gd +8 -0
- package/addon/godot_mcp_tool/util/resource_paths.gd.uid +1 -0
- package/addon/godot_mcp_tool/util/similar_names.gd +48 -0
- package/addon/godot_mcp_tool/util/similar_names.gd.uid +1 -0
- package/addon/godot_mcp_tool/util/waiting.gd +10 -0
- package/addon/godot_mcp_tool/util/waiting.gd.uid +1 -0
- package/dist/addon/AddonInstaller.js +99 -0
- package/dist/addon/InstalledAddon.js +38 -0
- package/dist/addon/PluginActivation.js +56 -0
- package/dist/bridge/BridgeClient.js +174 -0
- package/dist/bridge/BridgeErrors.js +19 -0
- package/dist/bridge/DiscoveryFileReader.js +95 -0
- package/dist/bridge/EditorConnection.js +131 -0
- package/dist/bridge/NdjsonDecoder.js +29 -0
- package/dist/cli/CommandLine.js +51 -0
- package/dist/cli/CommandReport.js +7 -0
- package/dist/cli/Doctor.js +102 -0
- package/dist/cli/runCommand.js +115 -0
- package/dist/createApplication.js +150 -0
- package/dist/createGodotContext.js +41 -0
- package/dist/debug/DebugAdapterClient.js +158 -0
- package/dist/debug/GameDebugger.js +225 -0
- package/dist/docs/BbcodeMarkdown.js +140 -0
- package/dist/docs/ClassDoc.js +21 -0
- package/dist/docs/DocsLibrary.js +148 -0
- package/dist/docs/DocsSource.js +167 -0
- package/dist/docs/EngineApiDocs.js +127 -0
- package/dist/docs/ProjectClassDocs.js +88 -0
- package/dist/editor/EditorGateway.js +4 -0
- package/dist/editor/EditorLauncher.js +73 -0
- package/dist/editor/EditorOrHeadlessGateway.js +21 -0
- package/dist/export/ExportDestination.js +108 -0
- package/dist/export/ExportError.js +4 -0
- package/dist/export/ExportOutput.js +51 -0
- package/dist/export/ExportPresets.js +16 -0
- package/dist/export/ProjectExporter.js +169 -0
- package/dist/godot/GodotBinaryLocator.js +66 -0
- package/dist/godot/GodotCli.js +24 -0
- package/dist/godot/GodotVersion.js +35 -0
- package/dist/godot/supportedGodotVersion.js +7 -0
- package/dist/hooks/EditedScriptCheck.js +42 -0
- package/dist/hooks/hookResponse.js +15 -0
- package/dist/index.js +28 -0
- package/dist/lsp/LanguageServerClient.js +234 -0
- package/dist/packageFiles.js +3 -0
- package/dist/process/DetachedLauncher.js +36 -0
- package/dist/process/ProcessLauncher.js +66 -0
- package/dist/process/ProcessRunner.js +24 -0
- package/dist/project/ConfigText.js +72 -0
- package/dist/project/HeadlessProjectQuery.js +60 -0
- package/dist/project/ProjectFile.js +29 -0
- package/dist/project/ProjectFiles.js +36 -0
- package/dist/project/ProjectLocator.js +65 -0
- package/dist/project/ScriptLines.js +20 -0
- package/dist/prompts/FixLastRunPrompt.js +46 -0
- package/dist/prompts/McpPrompt.js +2 -0
- package/dist/prompts/PlaytestPrompt.js +28 -0
- package/dist/protocol/ContentLengthMessages.js +34 -0
- package/dist/resources/McpResource.js +2 -0
- package/dist/resources/ToolViewResource.js +17 -0
- package/dist/resources/godotResources.js +33 -0
- package/dist/runtime/ErrorSummary.js +121 -0
- package/dist/runtime/GameGatewayRouter.js +52 -0
- package/dist/runtime/GameOutputCursor.js +10 -0
- package/dist/runtime/LocalGameChannel.js +158 -0
- package/dist/runtime/LocalGameGateway.js +279 -0
- package/dist/runtime/LogBook.js +48 -0
- package/dist/runtime/RecordFile.js +56 -0
- package/dist/scripts/CheckOnlyOutput.js +21 -0
- package/dist/scripts/ScriptErrorOutput.js +17 -0
- package/dist/scripts/ScriptFiles.js +40 -0
- package/dist/scripts/ScriptLoadErrors.js +23 -0
- package/dist/scripts/ScriptProblem.js +2 -0
- package/dist/scripts/ScriptValidator.js +71 -0
- package/dist/scripts/createScriptValidator.js +27 -0
- package/dist/serveOverStdio.js +23 -0
- package/dist/server/ToolPolicy.js +37 -0
- package/dist/server/createMcpServer.js +55 -0
- package/dist/server/serverInstructions.js +23 -0
- package/dist/serverInfo.js +4 -0
- package/dist/testing/JUnitReport.js +53 -0
- package/dist/testing/TestFrameworks.js +53 -0
- package/dist/testing/TestRunner.js +178 -0
- package/dist/tools/EditorLaunchTool.js +48 -0
- package/dist/tools/ErrorReportingTool.js +31 -0
- package/dist/tools/ExportProjectTool.js +79 -0
- package/dist/tools/GodotStatusTool.js +57 -0
- package/dist/tools/TestRunTool.js +130 -0
- package/dist/tools/Tool.js +2 -0
- package/dist/tools/animationTools.js +163 -0
- package/dist/tools/animationTreeTools.js +160 -0
- package/dist/tools/annotations.js +10 -0
- package/dist/tools/assetTools.js +120 -0
- package/dist/tools/autoloadTools.js +52 -0
- package/dist/tools/batchTools.js +91 -0
- package/dist/tools/bridge/BridgeTool.js +49 -0
- package/dist/tools/captureTools.js +124 -0
- package/dist/tools/debugTools.js +225 -0
- package/dist/tools/docsTools.js +108 -0
- package/dist/tools/editorTools.js +61 -0
- package/dist/tools/fileTools.js +82 -0
- package/dist/tools/formatting/classReference.js +229 -0
- package/dist/tools/formatting/counting.js +4 -0
- package/dist/tools/formatting/fileUsageReports.js +29 -0
- package/dist/tools/formatting/logEntries.js +26 -0
- package/dist/tools/formatting/propertyReports.js +75 -0
- package/dist/tools/formatting/sceneTree.js +70 -0
- package/dist/tools/formatting/scriptReports.js +49 -0
- package/dist/tools/gameControlTools.js +134 -0
- package/dist/tools/gameInspectionTools.js +145 -0
- package/dist/tools/gameTools.js +203 -0
- package/dist/tools/inputTools.js +276 -0
- package/dist/tools/navigationTools.js +64 -0
- package/dist/tools/nodeStructureTools.js +85 -0
- package/dist/tools/nodeTools.js +263 -0
- package/dist/tools/parameters.js +23 -0
- package/dist/tools/projectTools.js +184 -0
- package/dist/tools/resourceTools.js +99 -0
- package/dist/tools/results.js +7 -0
- package/dist/tools/sceneTools.js +134 -0
- package/dist/tools/scriptTools.js +47 -0
- package/dist/tools/signalTools.js +121 -0
- package/dist/tools/unsafeTools.js +156 -0
- package/dist/util/CacheDirectory.js +20 -0
- package/dist/util/SimilarNames.js +60 -0
- package/dist/util/XmlDocument.js +56 -0
- package/dist/util/errors.js +7 -0
- package/dist/util/ports.js +5 -0
- package/package.json +59 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 facelessdiplomat
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,58 @@
|
|
|
1
|
-
#
|
|
1
|
+
# godot-mcp-tool
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The MCP server and command-line tool of [Godot MCP Tool](https://github.com/facelessdiplomat/godot-mcp-tool). With
|
|
4
|
+
it, Claude Code makes Godot 4 games through the Godot editor: it builds scenes that Ctrl+Z can undo, writes and checks
|
|
5
|
+
GDScript, runs the game, plays input into it and reads its errors with stack traces.
|
|
6
|
+
|
|
7
|
+
You need Godot 4.7 or newer, Node.js 22 or newer and Claude Code.
|
|
8
|
+
|
|
9
|
+
## Quick start
|
|
10
|
+
|
|
11
|
+
1. Install the editor addon into your Godot project. In the project folder, with the editor closed, run:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx godot-mcp-tool install-addon
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
2. Connect Claude Code. The Claude Code plugin is the best way: it also checks every GDScript file Claude writes.
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
claude plugin marketplace add facelessdiplomat/godot-mcp-tool
|
|
21
|
+
claude plugin install godot@godot-mcp-tool
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Without the plugin, add the server to the project:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
claude mcp add --scope project godot -- npx -y godot-mcp-tool
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
3. Open the project in Godot, start `claude` in the project folder and ask: "Check the Godot connection."
|
|
31
|
+
|
|
32
|
+
## Commands
|
|
33
|
+
|
|
34
|
+
```text
|
|
35
|
+
godot-mcp-tool Run the MCP server; Claude Code starts it
|
|
36
|
+
godot-mcp-tool install-addon [folder] Copy the addon into the Godot project and enable its plugin
|
|
37
|
+
godot-mcp-tool update-addon [folder] Replace the addon of the project with the version of this package
|
|
38
|
+
godot-mcp-tool doctor [folder] Check Node.js, Godot, the addon, the plugin and the connection to the editor
|
|
39
|
+
godot-mcp-tool check-edited-script Check the .gd file of a Claude Code hook input; the plugin's hook runs it
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The folder is the Godot project: by default `GODOT_PROJECT_PATH`, or the current folder or the nearest folder above
|
|
43
|
+
it that has a `project.godot`.
|
|
44
|
+
|
|
45
|
+
## Documentation
|
|
46
|
+
|
|
47
|
+
- [Setup guide](https://github.com/facelessdiplomat/godot-mcp-tool/blob/master/docs/setup.md): installing, connecting,
|
|
48
|
+
settings and troubleshooting.
|
|
49
|
+
- [Usage guide](https://github.com/facelessdiplomat/godot-mcp-tool/blob/master/docs/usage.md): example requests,
|
|
50
|
+
safety and limitations.
|
|
51
|
+
- [Tool reference](https://github.com/facelessdiplomat/godot-mcp-tool/blob/master/docs/tools.md): every tool with its
|
|
52
|
+
parameters.
|
|
53
|
+
- [Security](https://github.com/facelessdiplomat/godot-mcp-tool/blob/master/SECURITY.md): how to report a problem and
|
|
54
|
+
how the tool protects your project.
|
|
55
|
+
|
|
56
|
+
## License
|
|
57
|
+
|
|
58
|
+
[MIT](https://github.com/facelessdiplomat/godot-mcp-tool/blob/master/LICENSE)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
extends RefCounted
|
|
2
|
+
|
|
3
|
+
const ADDON_VERSION := "0.1.0"
|
|
4
|
+
const BRIDGE_PROTOCOL_VERSION := 1
|
|
5
|
+
const DISCOVERY_RELATIVE_PATH := ".godot/godot_mcp_tool/bridge.json"
|
|
6
|
+
const CAPTURES_RELATIVE_PATH := ".godot/godot_mcp_tool/captures"
|
|
7
|
+
const LOOPBACK_ADDRESS := "127.0.0.1"
|
|
8
|
+
const RUNTIME_AUTOLOAD_NAME := "GodotMcpRuntime"
|
|
9
|
+
const SETTINGS_SECTION := "godot_mcp_tool"
|
|
10
|
+
const UNSAFE_TOOLS_KEY := "allow_unsafe_tools"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
uid://cmkw424ct17bi
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
extends RefCounted
|
|
2
|
+
|
|
3
|
+
const CommandError := preload("../commands/command_error.gd")
|
|
4
|
+
const IndefiniteArticle := preload("../util/indefinite_article.gd")
|
|
5
|
+
const JsonRpc := preload("../bridge/json_rpc.gd")
|
|
6
|
+
const NodeFactory := preload("../scene/node_factory.gd")
|
|
7
|
+
const NodeLocator := preload("../scene/node_locator.gd")
|
|
8
|
+
|
|
9
|
+
const FORBIDDEN_NAME_CHARACTERS := ["/", ":", ",", "["]
|
|
10
|
+
const LIBRARY_SEPARATOR := "/"
|
|
11
|
+
|
|
12
|
+
var library_name := ""
|
|
13
|
+
var animation_name := ""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
static func find_player(scene_root: Node, player_path: String) -> Variant:
|
|
17
|
+
var node := NodeLocator.find(scene_root, player_path)
|
|
18
|
+
if node == null:
|
|
19
|
+
return CommandError.new(JsonRpc.NOT_FOUND, "Node \"%s\" not found" % player_path, NodeLocator.not_found_hint(scene_root, player_path))
|
|
20
|
+
if not node is AnimationPlayer:
|
|
21
|
+
return CommandError.new(
|
|
22
|
+
JsonRpc.INVALID_PARAMS,
|
|
23
|
+
"%s is %s, not an AnimationPlayer" % [player_path, IndefiniteArticle.before(NodeFactory.display_class(node))],
|
|
24
|
+
"Add an AnimationPlayer with node_add; its tracks animate the nodes under its parent.",
|
|
25
|
+
)
|
|
26
|
+
return node
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
static func parse(full_name: String) -> Variant:
|
|
30
|
+
var reference := new()
|
|
31
|
+
var name := full_name.strip_edges()
|
|
32
|
+
if name.contains(LIBRARY_SEPARATOR):
|
|
33
|
+
reference.library_name = name.get_slice(LIBRARY_SEPARATOR, 0)
|
|
34
|
+
name = name.substr(reference.library_name.length() + 1)
|
|
35
|
+
reference.animation_name = name
|
|
36
|
+
if name.is_empty() or FORBIDDEN_NAME_CHARACTERS.any(func(character: String) -> bool: return name.contains(character)) or _has_forbidden_character(reference.library_name):
|
|
37
|
+
return CommandError.new(
|
|
38
|
+
JsonRpc.INVALID_PARAMS,
|
|
39
|
+
"\"%s\" is not a valid animation name" % full_name,
|
|
40
|
+
"Animation names cannot be empty or contain / : , [; write \"library/name\" for an animation of another library than the default one.",
|
|
41
|
+
)
|
|
42
|
+
return reference
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
static func _has_forbidden_character(library_name: String) -> bool:
|
|
46
|
+
return FORBIDDEN_NAME_CHARACTERS.any(func(character: String) -> bool: return library_name.contains(character))
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
func full_name() -> String:
|
|
50
|
+
return animation_name if library_name.is_empty() else "%s%s%s" % [library_name, LIBRARY_SEPARATOR, animation_name]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
uid://deaayqfs2ns82
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
extends RefCounted
|
|
2
|
+
|
|
3
|
+
const AnimationVocabulary := preload("animation_vocabulary.gd")
|
|
4
|
+
const VariantCodec := preload("../codec/variant_codec.gd")
|
|
5
|
+
|
|
6
|
+
const MAXIMUM_KEYS_SHOWN := 20
|
|
7
|
+
const DECIMAL_SCALE := 1000.0
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
static func list(player: AnimationPlayer) -> Array:
|
|
11
|
+
var animations: Array = []
|
|
12
|
+
for name in player.get_animation_list():
|
|
13
|
+
var animation := player.get_animation(name)
|
|
14
|
+
animations.append({"name": str(name), "length": _rounded(animation.length), "loop": loop_name(animation), "tracks": animation.get_track_count()})
|
|
15
|
+
return animations
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
static func detail(animation: Animation, name: String, codec: VariantCodec) -> Dictionary:
|
|
19
|
+
var tracks: Array = []
|
|
20
|
+
for index in animation.get_track_count():
|
|
21
|
+
tracks.append(_track(animation, index, codec))
|
|
22
|
+
return {"name": name, "length": _rounded(animation.length), "loop": loop_name(animation), "tracks": tracks}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
static func loop_name(animation: Animation) -> String:
|
|
26
|
+
return AnimationVocabulary.name_of(AnimationVocabulary.LOOP_MODES, animation.loop_mode)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
static func _track(animation: Animation, index: int, codec: VariantCodec) -> Dictionary:
|
|
30
|
+
var type := animation.track_get_type(index)
|
|
31
|
+
var track := {
|
|
32
|
+
"path": str(animation.track_get_path(index)),
|
|
33
|
+
"type": AnimationVocabulary.name_of(AnimationVocabulary.TRACK_TYPES, type),
|
|
34
|
+
"interpolation": AnimationVocabulary.name_of(AnimationVocabulary.INTERPOLATIONS, animation.track_get_interpolation_type(index)),
|
|
35
|
+
}
|
|
36
|
+
if type == Animation.TYPE_VALUE:
|
|
37
|
+
track["update"] = AnimationVocabulary.name_of(AnimationVocabulary.UPDATE_MODES, animation.value_track_get_update_mode(index))
|
|
38
|
+
var key_count := animation.track_get_key_count(index)
|
|
39
|
+
var keys: Array = []
|
|
40
|
+
for key_index in mini(key_count, MAXIMUM_KEYS_SHOWN):
|
|
41
|
+
keys.append({"time": _rounded(animation.track_get_key_time(index, key_index)), "value": codec.encode(animation.track_get_key_value(index, key_index))})
|
|
42
|
+
track["key_count"] = key_count
|
|
43
|
+
track["keys"] = keys
|
|
44
|
+
return track
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
static func _rounded(value: float) -> float:
|
|
48
|
+
return roundf(value * DECIMAL_SCALE) / DECIMAL_SCALE
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
uid://dmelrjna2x0rf
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
extends RefCounted
|
|
2
|
+
|
|
3
|
+
const AnimationVocabulary := preload("animation_vocabulary.gd")
|
|
4
|
+
const NodeLocator := preload("../scene/node_locator.gd")
|
|
5
|
+
const SimilarNames := preload("../util/similar_names.gd")
|
|
6
|
+
const VariantCodec := preload("../codec/variant_codec.gd")
|
|
7
|
+
|
|
8
|
+
const STEPPED_TYPES := [TYPE_BOOL, TYPE_STRING, TYPE_STRING_NAME, TYPE_NODE_PATH, TYPE_OBJECT]
|
|
9
|
+
const DEFAULT_LENGTH := 1.0
|
|
10
|
+
const DECIMAL_SCALE := 1000.0
|
|
11
|
+
const RESET_LENGTH := 0.001
|
|
12
|
+
|
|
13
|
+
var _codec: VariantCodec
|
|
14
|
+
var _root: Node
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
func _init(codec: VariantCodec, root: Node) -> void:
|
|
18
|
+
_codec = codec
|
|
19
|
+
_root = root
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
func plan(track_descriptions: Array, requested_length: Variant) -> Dictionary:
|
|
23
|
+
var planned: Array = []
|
|
24
|
+
var rejected: Array = []
|
|
25
|
+
var used_paths: Array = []
|
|
26
|
+
for index in track_descriptions.size():
|
|
27
|
+
var description: Variant = track_descriptions[index]
|
|
28
|
+
var path := str(description.get("path", "")) if description is Dictionary else ""
|
|
29
|
+
var track: Variant = _plan_track(description)
|
|
30
|
+
if track is String:
|
|
31
|
+
rejected.append({"index": index, "path": path, "reason": track})
|
|
32
|
+
continue
|
|
33
|
+
if path in used_paths:
|
|
34
|
+
rejected.append({"index": index, "path": path, "reason": "this track is given twice; give each property one track with all its keys"})
|
|
35
|
+
continue
|
|
36
|
+
used_paths.append(path)
|
|
37
|
+
track["index"] = index
|
|
38
|
+
planned.append(track)
|
|
39
|
+
var length: float = requested_length if requested_length != null else _last_key_time(planned)
|
|
40
|
+
var within_length: Array = []
|
|
41
|
+
for track in planned:
|
|
42
|
+
var late_key := _first_key_after(track, length)
|
|
43
|
+
if late_key >= 0.0:
|
|
44
|
+
var reason := "the key at %s s is after the end of the animation at %s s; make the animation longer with length" % [_seconds(late_key), _seconds(length)]
|
|
45
|
+
rejected.append({"index": track["index"], "path": track["path"], "reason": reason})
|
|
46
|
+
continue
|
|
47
|
+
within_length.append(track)
|
|
48
|
+
rejected.sort_custom(func(left: Dictionary, right: Dictionary) -> bool: return left["index"] < right["index"])
|
|
49
|
+
var rejections := rejected.map(func(rejection: Dictionary) -> Dictionary: return {"path": rejection["path"], "reason": rejection["reason"]})
|
|
50
|
+
return {"tracks": within_length, "rejected": rejections, "length": length}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
func build(planned_tracks: Array, length: float, loop_mode: int) -> Animation:
|
|
54
|
+
var animation := Animation.new()
|
|
55
|
+
animation.length = length
|
|
56
|
+
animation.loop_mode = loop_mode
|
|
57
|
+
for track in planned_tracks:
|
|
58
|
+
var index := animation.add_track(Animation.TYPE_VALUE)
|
|
59
|
+
animation.track_set_path(index, NodePath(track["path"]))
|
|
60
|
+
animation.track_set_interpolation_type(index, track["interpolation"])
|
|
61
|
+
animation.value_track_set_update_mode(index, track["update"])
|
|
62
|
+
for key in track["keys"]:
|
|
63
|
+
animation.track_insert_key(index, key["time"], key["value"])
|
|
64
|
+
return animation
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
func build_reset(previous: Animation, planned_tracks: Array) -> Animation:
|
|
68
|
+
var reset := previous.duplicate() as Animation if previous != null else Animation.new()
|
|
69
|
+
if previous == null:
|
|
70
|
+
reset.length = RESET_LENGTH
|
|
71
|
+
for track in planned_tracks:
|
|
72
|
+
var index := reset.add_track(Animation.TYPE_VALUE)
|
|
73
|
+
reset.track_set_path(index, NodePath(track["path"]))
|
|
74
|
+
reset.track_set_interpolation_type(index, track["interpolation"])
|
|
75
|
+
reset.value_track_set_update_mode(index, track["update"])
|
|
76
|
+
reset.track_insert_key(index, 0.0, current_value(track))
|
|
77
|
+
return reset
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
func current_value(track: Dictionary) -> Variant:
|
|
81
|
+
var path := str(track["path"])
|
|
82
|
+
var node_part := path.get_slice(":", 0)
|
|
83
|
+
return _root.get_node(NodePath(node_part)).get_indexed(NodePath(":" + path.substr(node_part.length() + 1)))
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
func describe(track: Dictionary) -> Dictionary:
|
|
87
|
+
var keys: Array = track["keys"]
|
|
88
|
+
return {
|
|
89
|
+
"path": track["path"],
|
|
90
|
+
"keys": keys.size(),
|
|
91
|
+
"interpolation": AnimationVocabulary.name_of(AnimationVocabulary.INTERPOLATIONS, track["interpolation"]),
|
|
92
|
+
"update": AnimationVocabulary.name_of(AnimationVocabulary.UPDATE_MODES, track["update"]),
|
|
93
|
+
"from": _codec.encode(keys.front()["value"]),
|
|
94
|
+
"to": _codec.encode(keys.back()["value"]),
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
func _plan_track(description: Variant) -> Variant:
|
|
99
|
+
if not description is Dictionary:
|
|
100
|
+
return "a track is an object such as {\"path\": \"Door:position\", \"keys\": [{\"time\": 0, \"value\": [0, 0, 0]}]}"
|
|
101
|
+
var path := str(description.get("path", ""))
|
|
102
|
+
var node_part := path.get_slice(":", 0)
|
|
103
|
+
var property_path := path.substr(node_part.length() + 1) if path.contains(":") else ""
|
|
104
|
+
if node_part.is_empty() or property_path.is_empty():
|
|
105
|
+
return "track paths are Node:property relative to the parent of the AnimationPlayer, such as \"Door:position\" or \".:visible\""
|
|
106
|
+
var target := _root.get_node_or_null(NodePath(node_part))
|
|
107
|
+
if target == null:
|
|
108
|
+
return "there is no node %s under %s. %s" % [node_part, _root.name, NodeLocator.not_found_hint(_root, node_part)]
|
|
109
|
+
var property: Variant = _property_of(target, property_path)
|
|
110
|
+
if property is String:
|
|
111
|
+
return property
|
|
112
|
+
var interpolation: Variant = _named_value(description, "interpolation", AnimationVocabulary.INTERPOLATIONS, "linear")
|
|
113
|
+
if interpolation is String:
|
|
114
|
+
return interpolation
|
|
115
|
+
var default_update := "discrete" if _is_stepped(property) else "continuous"
|
|
116
|
+
var update: Variant = _named_value(description, "update", AnimationVocabulary.UPDATE_MODES, default_update)
|
|
117
|
+
if update is String:
|
|
118
|
+
return update
|
|
119
|
+
var keys: Variant = _decode_keys(description.get("keys", []), property, target, property_path)
|
|
120
|
+
if keys is String:
|
|
121
|
+
return keys
|
|
122
|
+
return {"path": path, "interpolation": interpolation, "update": update, "keys": keys}
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
func _property_of(target: Node, property_path: String) -> Variant:
|
|
126
|
+
var property_name := property_path.get_slice(":", 0)
|
|
127
|
+
var properties := {}
|
|
128
|
+
for property in target.get_property_list():
|
|
129
|
+
properties[str(property["name"])] = property
|
|
130
|
+
if not properties.has(property_name):
|
|
131
|
+
var similar := SimilarNames.hint(property_name, properties.keys())
|
|
132
|
+
return "%s has no property \"%s\"%s" % [target.name, property_name, "" if similar.is_empty() else ". " + similar]
|
|
133
|
+
if property_path == property_name:
|
|
134
|
+
return properties[property_name]
|
|
135
|
+
var current: Variant = target.get_indexed(NodePath(":" + property_path))
|
|
136
|
+
if current == null:
|
|
137
|
+
return "%s has no part \"%s\"" % [target.name, property_path]
|
|
138
|
+
return {"name": property_path, "type": typeof(current), "hint": PROPERTY_HINT_NONE, "hint_string": "", "usage": PROPERTY_USAGE_DEFAULT}
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
func _decode_keys(key_descriptions: Variant, property: Dictionary, target: Node, property_path: String) -> Variant:
|
|
142
|
+
if not key_descriptions is Array or (key_descriptions as Array).is_empty():
|
|
143
|
+
return "a track needs keys, such as [{\"time\": 0, \"value\": [0, 0, 0]}, {\"time\": 1, \"value\": [0, 3, 0]}]"
|
|
144
|
+
var keys: Array = []
|
|
145
|
+
for key_description in key_descriptions:
|
|
146
|
+
if not key_description is Dictionary or not (key_description.get("time") is int or key_description.get("time") is float) or float(key_description["time"]) < 0.0:
|
|
147
|
+
return "each key is {\"time\": seconds from 0, \"value\": ...}"
|
|
148
|
+
if not key_description.has("value"):
|
|
149
|
+
return "the key at %s s has no value" % _seconds(key_description["time"])
|
|
150
|
+
var outcome := _codec.decode(key_description["value"], property, target)
|
|
151
|
+
if not outcome.is_success:
|
|
152
|
+
return "%s at %s s: %s" % [property_path, _seconds(key_description["time"]), outcome.error]
|
|
153
|
+
keys.append({"time": float(key_description["time"]), "value": outcome.value})
|
|
154
|
+
keys.sort_custom(func(left: Dictionary, right: Dictionary) -> bool: return left["time"] < right["time"])
|
|
155
|
+
return keys
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
static func _named_value(description: Dictionary, key: String, names: Dictionary, default_name: String) -> Variant:
|
|
159
|
+
var name: Variant = description.get(key, default_name)
|
|
160
|
+
var value: Variant = AnimationVocabulary.value_of(names, name)
|
|
161
|
+
if value == null:
|
|
162
|
+
return "unknown %s \"%s\"; use one of: %s" % [key, name, AnimationVocabulary.listed(names)]
|
|
163
|
+
return value
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
static func _is_stepped(property: Dictionary) -> bool:
|
|
167
|
+
if property["type"] in STEPPED_TYPES:
|
|
168
|
+
return true
|
|
169
|
+
return property["type"] == TYPE_INT and property.get("hint") == PROPERTY_HINT_ENUM
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
static func _last_key_time(tracks: Array) -> float:
|
|
173
|
+
var last := 0.0
|
|
174
|
+
for track in tracks:
|
|
175
|
+
last = maxf(last, (track["keys"] as Array).back()["time"])
|
|
176
|
+
return last if last > 0.0 else DEFAULT_LENGTH
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
static func _first_key_after(track: Dictionary, length: float) -> float:
|
|
180
|
+
for key in track["keys"]:
|
|
181
|
+
if key["time"] > length + 0.0001:
|
|
182
|
+
return key["time"]
|
|
183
|
+
return -1.0
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
static func _seconds(value: Variant) -> String:
|
|
187
|
+
var rounded := roundf(float(value) * DECIMAL_SCALE) / DECIMAL_SCALE
|
|
188
|
+
return str(roundi(rounded)) if is_equal_approx(rounded, roundf(rounded)) else str(rounded)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
uid://x5xohexuoo0t
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
extends RefCounted
|
|
2
|
+
|
|
3
|
+
const INTERPOLATIONS := {
|
|
4
|
+
"nearest": Animation.INTERPOLATION_NEAREST,
|
|
5
|
+
"linear": Animation.INTERPOLATION_LINEAR,
|
|
6
|
+
"cubic": Animation.INTERPOLATION_CUBIC,
|
|
7
|
+
"linear_angle": Animation.INTERPOLATION_LINEAR_ANGLE,
|
|
8
|
+
"cubic_angle": Animation.INTERPOLATION_CUBIC_ANGLE,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const UPDATE_MODES := {
|
|
12
|
+
"continuous": Animation.UPDATE_CONTINUOUS,
|
|
13
|
+
"discrete": Animation.UPDATE_DISCRETE,
|
|
14
|
+
"capture": Animation.UPDATE_CAPTURE,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const LOOP_MODES := {
|
|
18
|
+
"none": Animation.LOOP_NONE,
|
|
19
|
+
"linear": Animation.LOOP_LINEAR,
|
|
20
|
+
"pingpong": Animation.LOOP_PINGPONG,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const TRACK_TYPES := {
|
|
24
|
+
"value": Animation.TYPE_VALUE,
|
|
25
|
+
"position_3d": Animation.TYPE_POSITION_3D,
|
|
26
|
+
"rotation_3d": Animation.TYPE_ROTATION_3D,
|
|
27
|
+
"scale_3d": Animation.TYPE_SCALE_3D,
|
|
28
|
+
"blend_shape": Animation.TYPE_BLEND_SHAPE,
|
|
29
|
+
"method": Animation.TYPE_METHOD,
|
|
30
|
+
"bezier": Animation.TYPE_BEZIER,
|
|
31
|
+
"audio": Animation.TYPE_AUDIO,
|
|
32
|
+
"animation": Animation.TYPE_ANIMATION,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
static func name_of(names: Dictionary, value: int) -> String:
|
|
37
|
+
for name in names:
|
|
38
|
+
if names[name] == value:
|
|
39
|
+
return name
|
|
40
|
+
return str(value)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
static func value_of(names: Dictionary, name: Variant) -> Variant:
|
|
44
|
+
if not name is String:
|
|
45
|
+
return null
|
|
46
|
+
return names.get((name as String).to_lower(), null)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
static func listed(names: Dictionary) -> String:
|
|
50
|
+
return ", ".join(PackedStringArray(names.keys()))
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
uid://c0ybwpwuqs80q
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
extends RefCounted
|
|
2
|
+
|
|
3
|
+
const SimilarNames := preload("../util/similar_names.gd")
|
|
4
|
+
|
|
5
|
+
const START := "Start"
|
|
6
|
+
const END := "End"
|
|
7
|
+
const SWITCH_MODES := {
|
|
8
|
+
"immediate": AnimationNodeStateMachineTransition.SWITCH_MODE_IMMEDIATE,
|
|
9
|
+
"sync": AnimationNodeStateMachineTransition.SWITCH_MODE_SYNC,
|
|
10
|
+
"at_end": AnimationNodeStateMachineTransition.SWITCH_MODE_AT_END,
|
|
11
|
+
}
|
|
12
|
+
const ADVANCE_MODES := {
|
|
13
|
+
"disabled": AnimationNodeStateMachineTransition.ADVANCE_MODE_DISABLED,
|
|
14
|
+
"enabled": AnimationNodeStateMachineTransition.ADVANCE_MODE_ENABLED,
|
|
15
|
+
"auto": AnimationNodeStateMachineTransition.ADVANCE_MODE_AUTO,
|
|
16
|
+
}
|
|
17
|
+
const MAXIMUM_PRIORITY := 32
|
|
18
|
+
const STATES_PER_ROW := 4
|
|
19
|
+
const FIRST_STATE_POSITION := Vector2(200, 250)
|
|
20
|
+
const STATE_SPACING := Vector2(200, 150)
|
|
21
|
+
|
|
22
|
+
var states: Array = []
|
|
23
|
+
var transitions: Array = []
|
|
24
|
+
var rejected: Array = []
|
|
25
|
+
var warnings: Array = []
|
|
26
|
+
var _player: AnimationPlayer
|
|
27
|
+
var _condition_pattern := RegEx.create_from_string("^[A-Za-z_][A-Za-z0-9_]*$")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
func _init(player: AnimationPlayer) -> void:
|
|
31
|
+
_player = player
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
func plan(state_descriptions: Array, transition_descriptions: Array) -> void:
|
|
35
|
+
for description in state_descriptions:
|
|
36
|
+
_plan_state(description)
|
|
37
|
+
for description in transition_descriptions:
|
|
38
|
+
_plan_transition(description)
|
|
39
|
+
if not states.is_empty() and not transitions.any(func(transition: Dictionary) -> bool: return transition["from"] == START):
|
|
40
|
+
warnings.append("no transition leaves Start, so the tree plays nothing until a script calls travel() or start() on parameters/playback; add one such as {\"from\": \"Start\", \"to\": \"%s\"}" % states[0]["name"])
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
func build() -> AnimationNodeStateMachine:
|
|
44
|
+
var machine := AnimationNodeStateMachine.new()
|
|
45
|
+
for index in states.size():
|
|
46
|
+
var node := AnimationNodeAnimation.new()
|
|
47
|
+
node.animation = states[index]["animation"]
|
|
48
|
+
var grid_cell := Vector2(index % STATES_PER_ROW, index / STATES_PER_ROW)
|
|
49
|
+
machine.add_node(states[index]["name"], node, FIRST_STATE_POSITION + grid_cell * STATE_SPACING)
|
|
50
|
+
for planned in transitions:
|
|
51
|
+
var transition := AnimationNodeStateMachineTransition.new()
|
|
52
|
+
transition.advance_mode = ADVANCE_MODES[planned["advance"]]
|
|
53
|
+
transition.switch_mode = SWITCH_MODES[planned["switch"]]
|
|
54
|
+
transition.xfade_time = planned["xfade"]
|
|
55
|
+
transition.advance_condition = planned.get("condition", "")
|
|
56
|
+
transition.advance_expression = planned.get("expression", "")
|
|
57
|
+
transition.priority = planned.get("priority", 1)
|
|
58
|
+
machine.add_transition(planned["from"], planned["to"], transition)
|
|
59
|
+
return machine
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
func _plan_state(description: Variant) -> void:
|
|
63
|
+
if not description is Dictionary or not description.get("name") is String or not description.get("animation") is String:
|
|
64
|
+
rejected.append({"item": str(description), "reason": "a state is {\"name\": \"walk\", \"animation\": \"walk\"}"})
|
|
65
|
+
return
|
|
66
|
+
var name: String = description["name"]
|
|
67
|
+
var animation: String = description["animation"]
|
|
68
|
+
var reason := ""
|
|
69
|
+
if name.is_empty() or name.contains("/"):
|
|
70
|
+
reason = "state names cannot be empty or contain /"
|
|
71
|
+
elif name == START or name == END:
|
|
72
|
+
reason = "%s and %s are the built-in entry and exit of every state machine; give the state another name" % [START, END]
|
|
73
|
+
elif states.any(func(state: Dictionary) -> bool: return state["name"] == name):
|
|
74
|
+
reason = "this state is given twice"
|
|
75
|
+
elif not _player.has_animation(animation):
|
|
76
|
+
var known := Array(_player.get_animation_list()).map(func(animation_name: StringName) -> String: return str(animation_name))
|
|
77
|
+
var similar := SimilarNames.hint(animation, known)
|
|
78
|
+
reason = "%s has no animation \"%s\"%s" % [_player.name, animation, "" if similar.is_empty() else ". " + similar]
|
|
79
|
+
if not reason.is_empty():
|
|
80
|
+
rejected.append({"item": name, "reason": reason})
|
|
81
|
+
return
|
|
82
|
+
states.append({"name": name, "animation": animation})
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
func _plan_transition(description: Variant) -> void:
|
|
86
|
+
if not description is Dictionary or not description.get("from") is String or not description.get("to") is String:
|
|
87
|
+
rejected.append({"item": str(description), "reason": "a transition is {\"from\": \"idle\", \"to\": \"walk\"}"})
|
|
88
|
+
return
|
|
89
|
+
var from: String = description["from"]
|
|
90
|
+
var to: String = description["to"]
|
|
91
|
+
var label := "%s -> %s" % [from, to]
|
|
92
|
+
var planned: Variant = _transition(description, from, to)
|
|
93
|
+
if planned is String:
|
|
94
|
+
rejected.append({"item": label, "reason": planned})
|
|
95
|
+
return
|
|
96
|
+
transitions.append(planned)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
func _transition(description: Dictionary, from: String, to: String) -> Variant:
|
|
100
|
+
if from == END:
|
|
101
|
+
return "no transition can leave %s" % END
|
|
102
|
+
if to == START:
|
|
103
|
+
return "no transition can enter %s" % START
|
|
104
|
+
if from == to:
|
|
105
|
+
return "a state cannot have a transition to itself"
|
|
106
|
+
for state_name in [from, to]:
|
|
107
|
+
if not _is_known_state(state_name):
|
|
108
|
+
return "there is no state %s. %s" % [state_name, SimilarNames.hint(state_name, _state_names())]
|
|
109
|
+
if transitions.any(func(transition: Dictionary) -> bool: return transition["from"] == from and transition["to"] == to):
|
|
110
|
+
return "this transition is given twice"
|
|
111
|
+
var planned := {"from": from, "to": to}
|
|
112
|
+
var condition: Variant = description.get("condition")
|
|
113
|
+
if condition != null:
|
|
114
|
+
if not condition is String or not _condition_pattern.search(condition):
|
|
115
|
+
return "the condition \"%s\" is not a valid name; use letters, digits and _, such as moving" % condition
|
|
116
|
+
planned["condition"] = condition
|
|
117
|
+
var expression: Variant = description.get("expression")
|
|
118
|
+
if expression != null:
|
|
119
|
+
var parsed := Expression.new()
|
|
120
|
+
if not expression is String or parsed.parse(expression) != OK:
|
|
121
|
+
return "the expression \"%s\" does not parse: %s" % [expression, parsed.get_error_text()]
|
|
122
|
+
planned["expression"] = expression
|
|
123
|
+
var default_advance := "auto" if from == START or planned.has("condition") or planned.has("expression") else "enabled"
|
|
124
|
+
var advance: Variant = description.get("advance", default_advance)
|
|
125
|
+
if not advance in ADVANCE_MODES:
|
|
126
|
+
return "unknown advance \"%s\"; use one of: %s" % [advance, ", ".join(PackedStringArray(ADVANCE_MODES.keys()))]
|
|
127
|
+
var switch: Variant = description.get("switch", "immediate")
|
|
128
|
+
if not switch in SWITCH_MODES:
|
|
129
|
+
return "unknown switch \"%s\"; use one of: %s" % [switch, ", ".join(PackedStringArray(SWITCH_MODES.keys()))]
|
|
130
|
+
var xfade: Variant = description.get("xfade", 0.0)
|
|
131
|
+
if not (xfade is int or xfade is float) or float(xfade) < 0.0:
|
|
132
|
+
return "xfade is the cross-fade time in seconds, 0 or more"
|
|
133
|
+
planned["advance"] = advance
|
|
134
|
+
planned["switch"] = switch
|
|
135
|
+
planned["xfade"] = float(xfade)
|
|
136
|
+
var priority: Variant = description.get("priority")
|
|
137
|
+
if priority != null:
|
|
138
|
+
if not (priority is int or priority is float) or int(priority) < 0 or int(priority) > MAXIMUM_PRIORITY:
|
|
139
|
+
return "priority is a whole number from 0 to %d; lower numbers win" % MAXIMUM_PRIORITY
|
|
140
|
+
planned["priority"] = int(priority)
|
|
141
|
+
return _ordered(planned)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
func _is_known_state(state_name: String) -> bool:
|
|
145
|
+
return state_name == START or state_name == END or states.any(func(state: Dictionary) -> bool: return state["name"] == state_name)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
func _state_names() -> Array:
|
|
149
|
+
return [START, END] + states.map(func(state: Dictionary) -> String: return state["name"])
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
static func _ordered(planned: Dictionary) -> Dictionary:
|
|
153
|
+
var ordered := {"from": planned["from"], "to": planned["to"], "advance": planned["advance"], "switch": planned["switch"], "xfade": planned["xfade"]}
|
|
154
|
+
for optional in ["condition", "expression", "priority"]:
|
|
155
|
+
if planned.has(optional):
|
|
156
|
+
ordered[optional] = planned[optional]
|
|
157
|
+
return ordered
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
uid://bgf2wtiyqaon4
|