feat: Enhance Agent Tools with Dialogue, Music, and Sprite Commands

- Added new command handlers for dialogue inspection tools: `dialogue-list`, `dialogue-read`, and `dialogue-search`, allowing users to interact with dialogue messages in the ROM.
- Introduced music data tools: `music-list`, `music-info`, and `music-tracks`, enabling users to retrieve information about music tracks and their properties.
- Implemented sprite property tools: `sprite-list`, `sprite-properties`, and `sprite-palette`, providing access to sprite details and color palettes.
- Updated the command dispatcher to support the new tools, enhancing the functionality and usability of the CLI for users working with ROM data.
This commit is contained in:
scawful
2025-10-06 01:10:50 -04:00
parent e0f0805426
commit 73df4af850
8 changed files with 1180 additions and 2 deletions

View File

@@ -1371,11 +1371,18 @@ void AgentChatWidget::RenderMultimodalPanel() {
ImGui::RadioButton("Window##mm_window",
reinterpret_cast<int*>(&multimodal_state_.capture_mode),
static_cast<int>(CaptureMode::kSpecificWindow));
ImGui::SameLine();
ImGui::RadioButton("Region##mm_region",
reinterpret_cast<int*>(&multimodal_state_.capture_mode),
static_cast<int>(CaptureMode::kRegionSelect));
if (!can_capture)
ImGui::BeginDisabled();
if (ImGui::SmallButton(ICON_MD_PHOTO_CAMERA " Capture##mm_cap")) {
if (multimodal_callbacks_.capture_snapshot) {
if (multimodal_state_.capture_mode == CaptureMode::kRegionSelect) {
// Begin region selection mode
BeginRegionSelection();
} else if (multimodal_callbacks_.capture_snapshot) {
std::filesystem::path captured_path;
absl::Status status =
multimodal_callbacks_.capture_snapshot(&captured_path);
@@ -1384,6 +1391,7 @@ void AgentChatWidget::RenderMultimodalPanel() {
multimodal_state_.status_message =
absl::StrFormat("Captured %s", captured_path.string());
multimodal_state_.last_updated = absl::Now();
LoadScreenshotPreview(captured_path);
if (toast_manager_) {
toast_manager_->Show("Snapshot captured", ToastType::kSuccess, 3.0f);
}
@@ -1449,9 +1457,32 @@ void AgentChatWidget::RenderMultimodalPanel() {
if (!can_send)
ImGui::EndDisabled();
// Screenshot preview section
if (multimodal_state_.preview.loaded && multimodal_state_.preview.show_preview) {
ImGui::Spacing();
ImGui::Separator();
ImGui::Text(ICON_MD_IMAGE " Preview:");
RenderScreenshotPreview();
}
// Region selection active indicator
if (multimodal_state_.region_selection.active) {
ImGui::Spacing();
ImGui::Separator();
ImGui::TextColored(theme.provider_ollama, ICON_MD_CROP " Drag to select region");
if (ImGui::SmallButton("Cancel##region_cancel")) {
multimodal_state_.region_selection.active = false;
}
}
ImGui::EndChild();
AgentUI::PopPanelStyle();
ImGui::PopID();
// Handle region selection (overlay)
if (multimodal_state_.region_selection.active) {
HandleRegionSelection();
}
}
void AgentChatWidget::RefreshCollaboration() {
@@ -2613,5 +2644,223 @@ void AgentChatWidget::SyncHistoryToPopup() {
chat_history_popup_->UpdateHistory(history);
}
// Screenshot Preview Implementation
void AgentChatWidget::LoadScreenshotPreview(const std::filesystem::path& image_path) {
// For now, store the path and mark as loaded
// Actual texture loading would need to use SDL_image or stb_image
// and then upload to GPU via ImGui backend
multimodal_state_.preview.loaded = true;
multimodal_state_.preview.show_preview = true;
// TODO: Implement actual texture loading using SDL_image or stb_image
// For now, just track that we have a valid image path
if (toast_manager_) {
toast_manager_->Show("Screenshot preview loaded", ToastType::kInfo, 2.0f);
}
}
void AgentChatWidget::UnloadScreenshotPreview() {
if (multimodal_state_.preview.texture_id != nullptr) {
// TODO: Free the texture from GPU
// This requires backend-specific cleanup
multimodal_state_.preview.texture_id = nullptr;
}
multimodal_state_.preview.loaded = false;
multimodal_state_.preview.width = 0;
multimodal_state_.preview.height = 0;
}
void AgentChatWidget::RenderScreenshotPreview() {
if (!multimodal_state_.last_capture_path.has_value()) {
ImGui::TextDisabled("No screenshot to preview");
return;
}
const auto& theme = AgentUI::GetTheme();
// Display filename
std::string filename = multimodal_state_.last_capture_path->filename().string();
ImGui::TextColored(theme.text_secondary, "%s", filename.c_str());
// Preview controls
if (ImGui::SmallButton(ICON_MD_CLOSE " Hide")) {
multimodal_state_.preview.show_preview = false;
}
ImGui::SameLine();
if (multimodal_state_.preview.loaded && multimodal_state_.preview.texture_id) {
// Display the actual texture
ImVec2 preview_size(
multimodal_state_.preview.width * multimodal_state_.preview.preview_scale,
multimodal_state_.preview.height * multimodal_state_.preview.preview_scale
);
ImGui::Image(multimodal_state_.preview.texture_id, preview_size);
// Scale slider
ImGui::SetNextItemWidth(150);
ImGui::SliderFloat("##preview_scale", &multimodal_state_.preview.preview_scale,
0.1f, 2.0f, "Scale: %.1fx");
} else {
// Placeholder when texture not loaded
ImGui::BeginChild("PreviewPlaceholder", ImVec2(200, 150), true);
ImGui::SetCursorPos(ImVec2(60, 60));
ImGui::TextColored(theme.text_secondary, ICON_MD_IMAGE);
ImGui::SetCursorPosX(40);
ImGui::TextWrapped("Preview placeholder");
ImGui::TextDisabled("(Texture loading not yet implemented)");
ImGui::EndChild();
}
}
// Region Selection Implementation
void AgentChatWidget::BeginRegionSelection() {
multimodal_state_.region_selection.active = true;
multimodal_state_.region_selection.dragging = false;
if (toast_manager_) {
toast_manager_->Show(ICON_MD_CROP " Drag to select region",
ToastType::kInfo, 3.0f);
}
}
void AgentChatWidget::HandleRegionSelection() {
if (!multimodal_state_.region_selection.active) {
return;
}
// Get the full window viewport
ImGuiViewport* viewport = ImGui::GetMainViewport();
ImVec2 viewport_pos = viewport->Pos;
ImVec2 viewport_size = viewport->Size;
// Draw semi-transparent overlay
ImDrawList* draw_list = ImGui::GetForegroundDrawList();
ImVec2 overlay_min = viewport_pos;
ImVec2 overlay_max = ImVec2(viewport_pos.x + viewport_size.x,
viewport_pos.y + viewport_size.y);
draw_list->AddRectFilled(overlay_min, overlay_max,
IM_COL32(0, 0, 0, 100));
// Handle mouse input for region selection
ImGuiIO& io = ImGui::GetIO();
ImVec2 mouse_pos = io.MousePos;
// Start dragging
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) &&
!multimodal_state_.region_selection.dragging) {
multimodal_state_.region_selection.dragging = true;
multimodal_state_.region_selection.start_pos = mouse_pos;
multimodal_state_.region_selection.end_pos = mouse_pos;
}
// Update drag
if (multimodal_state_.region_selection.dragging &&
ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
multimodal_state_.region_selection.end_pos = mouse_pos;
// Calculate selection rectangle
ImVec2 start = multimodal_state_.region_selection.start_pos;
ImVec2 end = multimodal_state_.region_selection.end_pos;
multimodal_state_.region_selection.selection_min = ImVec2(
std::min(start.x, end.x),
std::min(start.y, end.y)
);
multimodal_state_.region_selection.selection_max = ImVec2(
std::max(start.x, end.x),
std::max(start.y, end.y)
);
// Draw selection rectangle
draw_list->AddRect(
multimodal_state_.region_selection.selection_min,
multimodal_state_.region_selection.selection_max,
IM_COL32(100, 180, 255, 255), 0.0f, 0, 2.0f
);
// Draw dimensions label
float width = multimodal_state_.region_selection.selection_max.x -
multimodal_state_.region_selection.selection_min.x;
float height = multimodal_state_.region_selection.selection_max.y -
multimodal_state_.region_selection.selection_min.y;
std::string dimensions = absl::StrFormat("%.0f x %.0f", width, height);
ImVec2 label_pos = ImVec2(
multimodal_state_.region_selection.selection_min.x + 5,
multimodal_state_.region_selection.selection_min.y + 5
);
draw_list->AddText(label_pos, IM_COL32(255, 255, 255, 255),
dimensions.c_str());
}
// End dragging
if (multimodal_state_.region_selection.dragging &&
ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
multimodal_state_.region_selection.dragging = false;
CaptureSelectedRegion();
multimodal_state_.region_selection.active = false;
}
// Cancel on Escape
if (ImGui::IsKeyPressed(ImGuiKey_Escape)) {
multimodal_state_.region_selection.active = false;
multimodal_state_.region_selection.dragging = false;
if (toast_manager_) {
toast_manager_->Show("Region selection cancelled", ToastType::kInfo);
}
}
// Instructions overlay
ImVec2 text_pos = ImVec2(viewport_pos.x + 20, viewport_pos.y + 20);
draw_list->AddText(text_pos, IM_COL32(255, 255, 255, 255),
"Drag to select region (ESC to cancel)");
}
void AgentChatWidget::CaptureSelectedRegion() {
// Calculate region bounds
ImVec2 min = multimodal_state_.region_selection.selection_min;
ImVec2 max = multimodal_state_.region_selection.selection_max;
float width = max.x - min.x;
float height = max.y - min.y;
// Validate selection
if (width < 10 || height < 10) {
if (toast_manager_) {
toast_manager_->Show("Region too small", ToastType::kWarning);
}
return;
}
// TODO: Implement actual region capture
// This would involve:
// 1. Capturing the full screenshot
// 2. Cropping to the selected region
// 3. Saving the cropped image
if (toast_manager_) {
toast_manager_->Show(
absl::StrFormat("Region captured: %.0fx%.0f", width, height),
ToastType::kSuccess, 3.0f
);
}
// For now, just call the regular capture callback
if (multimodal_callbacks_.capture_snapshot) {
std::filesystem::path captured_path;
auto status = multimodal_callbacks_.capture_snapshot(&captured_path);
if (status.ok()) {
multimodal_state_.last_capture_path = captured_path;
multimodal_state_.status_message = "Region captured";
multimodal_state_.last_updated = absl::Now();
LoadScreenshotPreview(captured_path);
MarkHistoryDirty();
}
}
}
} // namespace editor
} // namespace yaze

View File

@@ -100,6 +100,15 @@ class AgentChatWidget {
};
void RenderSnapshotPreviewPanel();
// Screenshot preview and region selection
void LoadScreenshotPreview(const std::filesystem::path& image_path);
void UnloadScreenshotPreview();
void RenderScreenshotPreview();
void RenderRegionSelection();
void BeginRegionSelection();
void HandleRegionSelection();
void CaptureSelectedRegion();
void SetToastManager(ToastManager* toast_manager);
@@ -149,7 +158,26 @@ public:
enum class CaptureMode {
kFullWindow = 0,
kActiveEditor = 1,
kSpecificWindow = 2
kSpecificWindow = 2,
kRegionSelect = 3 // New: drag to select region
};
struct ScreenshotPreviewState {
void* texture_id = nullptr; // ImTextureID
int width = 0;
int height = 0;
bool loaded = false;
float preview_scale = 1.0f;
bool show_preview = true;
};
struct RegionSelectionState {
bool active = false;
bool dragging = false;
ImVec2 start_pos;
ImVec2 end_pos;
ImVec2 selection_min;
ImVec2 selection_max;
};
struct MultimodalState {
@@ -158,6 +186,8 @@ public:
absl::Time last_updated = absl::InfinitePast();
CaptureMode capture_mode = CaptureMode::kActiveEditor;
char specific_window_buffer[128] = {};
ScreenshotPreviewState preview;
RegionSelectionState region_selection;
};
struct AutomationState {