Replace dasher-pack with unified animation-pack using original Blender bone names
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
@tool
|
||||
extends VBoxContainer
|
||||
|
||||
## Dock subpanel — renders the MCP request/response log buffer. Owns its own
|
||||
## UI subtree, the line-count cursor, and the display-visibility toggle. Emits
|
||||
## `logging_enabled_changed` so the dock can route the flag onto the
|
||||
## connection dispatcher without the panel knowing the routing exists.
|
||||
##
|
||||
## Extracted from mcp_dock.gd as part of audit-v2 #360 — see the comment at
|
||||
## the top of mcp_dock.gd for the broader extraction story.
|
||||
|
||||
signal logging_enabled_changed(enabled: bool)
|
||||
|
||||
const Dock := preload("res://addons/godot_ai/mcp_dock.gd")
|
||||
|
||||
## Untyped: a `: McpLogBuffer` annotation hits the class_name registry at
|
||||
## script-load and trips the self-update parse hazard (#398). The type fence
|
||||
## stays on the `setup(log_buffer: McpLogBuffer)` parameter.
|
||||
var _log_buffer
|
||||
var _log_display: RichTextLabel
|
||||
var _log_toggle: CheckButton
|
||||
## Last `McpLogBuffer.total_logged()` value painted into the display. Tracking
|
||||
## the buffer's monotonic sequence (rather than its bounded `total_count()`)
|
||||
## keeps the viewer painting once the ring fills — a size-based cursor would
|
||||
## freeze at MAX_LINES on every subsequent append. See PR #392 for the bug.
|
||||
var _last_log_seq := 0
|
||||
|
||||
|
||||
## Build the UI synchronously here so callers (and detached-tree tests that
|
||||
## instantiate the dock with `McpDockScript.new()` and never enter the tree)
|
||||
## can interact with the panel's controls right after `setup()`. Mirrors the
|
||||
## pre-extraction inline-build behavior that test_dock.gd relies on.
|
||||
##
|
||||
## Idempotent: `_log_display == null` covers an unlikely double-`setup()` call
|
||||
## without rebuilding (which would orphan the prior controls).
|
||||
func setup(log_buffer: McpLogBuffer) -> void:
|
||||
_log_buffer = log_buffer
|
||||
if _log_display == null:
|
||||
_build_ui()
|
||||
|
||||
|
||||
func _build_ui() -> void:
|
||||
size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
add_child(HSeparator.new())
|
||||
|
||||
var log_header_row := HBoxContainer.new()
|
||||
var log_header := Dock._make_header("MCP Log")
|
||||
log_header.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
log_header_row.add_child(log_header)
|
||||
|
||||
_log_toggle = CheckButton.new()
|
||||
_log_toggle.text = "Log"
|
||||
_log_toggle.button_pressed = true
|
||||
_log_toggle.toggled.connect(_on_log_toggled)
|
||||
log_header_row.add_child(_log_toggle)
|
||||
|
||||
add_child(log_header_row)
|
||||
|
||||
_log_display = RichTextLabel.new()
|
||||
_log_display.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
_log_display.custom_minimum_size = Vector2(0, 120)
|
||||
_log_display.scroll_following = true
|
||||
_log_display.bbcode_enabled = false
|
||||
_log_display.selection_enabled = true
|
||||
add_child(_log_display)
|
||||
|
||||
|
||||
## Called from McpDock._process when the panel is visible. Appends any new
|
||||
## log lines since the last tick.
|
||||
func tick() -> void:
|
||||
if _log_buffer == null or _log_display == null:
|
||||
return
|
||||
var seq: int = _log_buffer.total_logged()
|
||||
if seq == _last_log_seq:
|
||||
return
|
||||
if seq < _last_log_seq:
|
||||
## Buffer cleared via `McpLogBuffer.clear()` (the `clear_logs` MCP
|
||||
## tool / `logs_clear` handler). The buffer resets `_total_logged`
|
||||
## to 0, flipping the sequence backward. Without this branch the
|
||||
## display would keep showing pre-clear lines forever — the viewer
|
||||
## drifts permanently out of sync with the buffer. Reset display +
|
||||
## cursor so the next append paints over a clean slate.
|
||||
_log_display.clear()
|
||||
_last_log_seq = 0
|
||||
if seq == 0:
|
||||
return
|
||||
var new_lines: Array[String] = _log_buffer.get_recent(seq - _last_log_seq)
|
||||
for line in new_lines:
|
||||
_log_display.add_text(line + "\n")
|
||||
_last_log_seq = seq
|
||||
|
||||
|
||||
func _on_log_toggled(enabled: bool) -> void:
|
||||
_log_display.visible = enabled
|
||||
logging_enabled_changed.emit(enabled)
|
||||
@@ -0,0 +1 @@
|
||||
uid://cr5nbnd6vj3b8
|
||||
@@ -0,0 +1,78 @@
|
||||
@tool
|
||||
extends VBoxContainer
|
||||
|
||||
## Dock subpanel — port-change escape hatch surfaced inside the spawn-failure
|
||||
## crash panel when the HTTP port is contested (PORT_EXCLUDED, FOREIGN_PORT).
|
||||
## Emits `port_apply_requested(new_port)` after range-validation; the dock
|
||||
## handles writing the EditorSetting and reloading the plugin.
|
||||
##
|
||||
## Extracted from mcp_dock.gd as part of audit-v2 #360 — see the comment at
|
||||
## the top of mcp_dock.gd for the broader extraction story.
|
||||
|
||||
const ClientConfigurator := preload("res://addons/godot_ai/client_configurator.gd")
|
||||
|
||||
signal port_apply_requested(new_port: int)
|
||||
|
||||
var _spinbox: SpinBox
|
||||
|
||||
|
||||
## Build the UI synchronously here so callers (and detached-tree tests that
|
||||
## instantiate the dock with `McpDockScript.new()` and never enter the tree)
|
||||
## can interact with the panel's controls right after `setup()`. Mirrors the
|
||||
## pre-extraction inline-build behavior that test_dock.gd relies on.
|
||||
##
|
||||
## Idempotent: `_spinbox == null` covers an unlikely double-`setup()` call
|
||||
## without rebuilding (which would orphan the prior controls).
|
||||
func setup() -> void:
|
||||
if _spinbox == null:
|
||||
_build_ui()
|
||||
|
||||
|
||||
func _build_ui() -> void:
|
||||
add_theme_constant_override("separation", 4)
|
||||
visible = false
|
||||
|
||||
var picker_row := HBoxContainer.new()
|
||||
picker_row.add_theme_constant_override("separation", 6)
|
||||
|
||||
_spinbox = SpinBox.new()
|
||||
_spinbox.min_value = ClientConfigurator.MIN_PORT
|
||||
_spinbox.max_value = ClientConfigurator.MAX_PORT
|
||||
_spinbox.step = 1
|
||||
_spinbox.value = ClientConfigurator.http_port()
|
||||
_spinbox.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
picker_row.add_child(_spinbox)
|
||||
|
||||
var apply_btn := Button.new()
|
||||
apply_btn.text = "Apply + Reload"
|
||||
apply_btn.tooltip_text = (
|
||||
"Saves godot_ai/http_port to Editor Settings and reloads the plugin so"
|
||||
+ " the server spawns on the new port."
|
||||
)
|
||||
apply_btn.pressed.connect(_on_apply_pressed)
|
||||
picker_row.add_child(apply_btn)
|
||||
|
||||
add_child(picker_row)
|
||||
|
||||
|
||||
## Re-seed the spinbox with a fresh suggestion every time the panel surfaces,
|
||||
## so a stale value from a previous spawn-failure round can't carry over. Note
|
||||
## that this OVERWRITES any unsaved user input — fine in practice because the
|
||||
## dock's `_update_crash_panel` only calls this on `server_status` transitions
|
||||
## (`if server_status == _last_server_status: return` short-circuit), so a
|
||||
## user typing into the spinbox between transitions keeps their value. If the
|
||||
## state flips while the picker is visible (e.g. `PORT_EXCLUDED` → `FOREIGN_PORT`),
|
||||
## the in-flight edit is clobbered — accept that, the suggestion is more current.
|
||||
func seed_suggested_port() -> void:
|
||||
if _spinbox == null:
|
||||
return
|
||||
_spinbox.value = ClientConfigurator.suggest_free_port(
|
||||
ClientConfigurator.http_port() + 1
|
||||
)
|
||||
|
||||
|
||||
func _on_apply_pressed() -> void:
|
||||
var new_port: int = int(_spinbox.value)
|
||||
if new_port < ClientConfigurator.MIN_PORT or new_port > ClientConfigurator.MAX_PORT:
|
||||
return
|
||||
port_apply_requested.emit(new_port)
|
||||
@@ -0,0 +1 @@
|
||||
uid://hlggbo1q65eq
|
||||
Reference in New Issue
Block a user