Enhance tile selection and editing functionality in OverworldEditor and Tile16Editor
- Improved handling of single and double clicks for tile selection and editing in OverworldEditor, allowing for more intuitive user interactions. - Added logging for tile selection actions to aid debugging and user feedback. - Updated Tile16Editor to ensure proper synchronization with the overworld editor during tile changes, enhancing workflow reliability. - Implemented critical fixes in Canvas to prevent ImGui assertions by ensuring minimum canvas size during rendering.
This commit is contained in:
@@ -1287,10 +1287,17 @@ absl::Status OverworldEditor::DrawTile16Selector() {
|
||||
// First, call DrawTileSelector to handle the visual feedback
|
||||
blockset_canvas_.DrawTileSelector(32.0f);
|
||||
|
||||
// Then check for single click to update tile selection
|
||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Left) && blockset_canvas_.IsMouseHovering()) {
|
||||
// Handle both single click (select) and double click (edit) properly
|
||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && blockset_canvas_.IsMouseHovering()) {
|
||||
tile_selected = true;
|
||||
}
|
||||
|
||||
// Check for double click to open tile16 editor
|
||||
bool open_tile16_editor = false;
|
||||
if (blockset_canvas_.IsMouseHovering() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
|
||||
tile_selected = true;
|
||||
open_tile16_editor = true;
|
||||
}
|
||||
|
||||
if (tile_selected) {
|
||||
// Get mouse position relative to canvas
|
||||
@@ -1305,8 +1312,15 @@ absl::Status OverworldEditor::DrawTile16Selector() {
|
||||
|
||||
if (id != current_tile16_ && id >= 0 && id < 512) {
|
||||
current_tile16_ = id;
|
||||
// CRITICAL FIX: Always sync tile16 editor with overworld editor selection
|
||||
RETURN_IF_ERROR(tile16_editor_.SetCurrentTile(id));
|
||||
show_tile16_editor_ = true;
|
||||
|
||||
if (open_tile16_editor) {
|
||||
show_tile16_editor_ = true;
|
||||
util::logf("Opened Tile16 editor for tile %d (double-click)", id);
|
||||
} else {
|
||||
util::logf("Selected Tile16: %d (single-click)", id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,15 +53,13 @@ absl::Status Tile16Editor::Initialize(
|
||||
current_tile16_bmp_.SetPalette(tile16_blockset_bmp.palette());
|
||||
core::Renderer::Get().RenderBitmap(¤t_tile16_bmp_);
|
||||
|
||||
// Initialize enhanced canvas features
|
||||
// Initialize enhanced canvas features with proper sizing
|
||||
tile16_edit_canvas_.InitializeDefaults();
|
||||
tile8_source_canvas_.InitializeDefaults();
|
||||
|
||||
// Configure canvases for table integration - keep fixed sizes but ensure proper content reporting
|
||||
tile16_edit_canvas_.SetAutoResize(
|
||||
false); // Keep fixed size for precise editing
|
||||
tile8_source_canvas_.SetAutoResize(
|
||||
false); // Keep fixed size for consistent layout
|
||||
// Configure canvases with proper initialization
|
||||
tile16_edit_canvas_.SetAutoResize(false);
|
||||
tile8_source_canvas_.SetAutoResize(false);
|
||||
|
||||
// Initialize enhanced palette editors if ROM is available
|
||||
if (rom_) {
|
||||
@@ -280,19 +278,33 @@ absl::Status Tile16Editor::UpdateBlockset() {
|
||||
gui::EndPadding();
|
||||
|
||||
blockset_canvas_.DrawContextMenu();
|
||||
if (blockset_canvas_.DrawTileSelector(32)) {
|
||||
auto tile_pos = blockset_canvas_.GetLastClickPosition();
|
||||
int clicked_x =
|
||||
static_cast<int>(tile_pos.x / blockset_canvas_.GetGridStep());
|
||||
int clicked_y =
|
||||
static_cast<int>(tile_pos.y / blockset_canvas_.GetGridStep());
|
||||
int selected_tile =
|
||||
clicked_x + (clicked_y * 8); // 8 tiles per row in blockset
|
||||
if (selected_tile != current_tile16_ && selected_tile >= 0 &&
|
||||
selected_tile < 512) {
|
||||
|
||||
// CRITICAL FIX: Handle single clicks properly like the overworld editor
|
||||
bool tile_selected = false;
|
||||
|
||||
// First, call DrawTileSelector for visual feedback
|
||||
blockset_canvas_.DrawTileSelector(32.0f);
|
||||
|
||||
// Then check for single click to update tile selection
|
||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Left) && blockset_canvas_.IsMouseHovering()) {
|
||||
tile_selected = true;
|
||||
}
|
||||
|
||||
if (tile_selected) {
|
||||
// Get mouse position relative to canvas
|
||||
const ImGuiIO& io = ImGui::GetIO();
|
||||
ImVec2 canvas_pos = blockset_canvas_.zero_point();
|
||||
ImVec2 mouse_pos = ImVec2(io.MousePos.x - canvas_pos.x, io.MousePos.y - canvas_pos.y);
|
||||
|
||||
// Calculate grid position (32x32 tiles in blockset)
|
||||
int grid_x = static_cast<int>(mouse_pos.x / 32);
|
||||
int grid_y = static_cast<int>(mouse_pos.y / 32);
|
||||
int selected_tile = grid_x + grid_y * 8; // 8 tiles per row in blockset
|
||||
|
||||
if (selected_tile != current_tile16_ && selected_tile >= 0 && selected_tile < 512) {
|
||||
RETURN_IF_ERROR(SetCurrentTile(selected_tile));
|
||||
util::logf("Selected Tile16 from blockset: %d (grid: %d,%d)",
|
||||
selected_tile, clicked_x, clicked_y);
|
||||
selected_tile, grid_x, grid_y);
|
||||
}
|
||||
}
|
||||
blockset_canvas_.DrawBitmap(tile16_blockset_bmp_, 0, true, 2.0f);
|
||||
@@ -695,7 +707,7 @@ absl::Status Tile16Editor::UpdateTile16Edit() {
|
||||
ImVec2(tile8_source_canvas_.width(), tile8_source_canvas_.height()),
|
||||
true, ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
|
||||
|
||||
// Enable dragging for scrolling behavior
|
||||
// Enable dragging for scrolling behavior
|
||||
tile8_source_canvas_.set_draggable(true);
|
||||
tile8_source_canvas_.DrawBackground();
|
||||
tile8_source_canvas_.DrawContextMenu();
|
||||
@@ -735,8 +747,7 @@ absl::Status Tile16Editor::UpdateTile16Edit() {
|
||||
ImGuiWindowFlags_NoScrollbar |
|
||||
ImGuiWindowFlags_NoScrollWithMouse)) {
|
||||
|
||||
tile16_edit_canvas_.DrawBackground(
|
||||
ImVec2(64, 64)); // Fixed 64x64 display size
|
||||
tile16_edit_canvas_.DrawBackground(ImVec2(64, 64));
|
||||
tile16_edit_canvas_.DrawContextMenu();
|
||||
|
||||
// Draw current tile16 bitmap at 4x scale for clarity (16x16 pixels -> 64x64 display)
|
||||
@@ -1547,21 +1558,44 @@ absl::Status Tile16Editor::CommitChangesToBlockset() {
|
||||
}
|
||||
|
||||
absl::Status Tile16Editor::CommitChangesToOverworld() {
|
||||
// Write all tile16 changes to ROM
|
||||
RETURN_IF_ERROR(SaveTile16ToROM());
|
||||
// CRITICAL FIX: Complete workflow for tile16 changes
|
||||
|
||||
// Step 1: Update ROM data with current tile16 changes
|
||||
RETURN_IF_ERROR(UpdateROMTile16Data());
|
||||
|
||||
// Step 2: Update the local blockset to reflect changes
|
||||
RETURN_IF_ERROR(UpdateBlocksetBitmap());
|
||||
|
||||
// Step 3: Update the atlas directly (bypass problematic tile cache)
|
||||
if (tile16_blockset_->atlas.is_active()) {
|
||||
// Calculate the position of this tile in the blockset atlas
|
||||
constexpr int kTilesPerRow = 8;
|
||||
int tile_x = (current_tile16_ % kTilesPerRow) * kTile16Size;
|
||||
int tile_y = (current_tile16_ / kTilesPerRow) * kTile16Size;
|
||||
|
||||
// Copy current tile16 bitmap data directly to atlas
|
||||
for (int ty = 0; ty < kTile16Size; ++ty) {
|
||||
for (int tx = 0; tx < kTile16Size; ++tx) {
|
||||
int src_index = ty * kTile16Size + tx;
|
||||
int dst_index = (tile_y + ty) * tile16_blockset_->atlas.width() + (tile_x + tx);
|
||||
|
||||
if (src_index < static_cast<int>(current_tile16_bmp_.size()) &&
|
||||
dst_index < static_cast<int>(tile16_blockset_->atlas.size())) {
|
||||
tile16_blockset_->atlas.WriteToPixel(dst_index, current_tile16_bmp_.data()[src_index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tile16_blockset_->atlas.set_modified(true);
|
||||
core::Renderer::Get().UpdateBitmap(&tile16_blockset_->atlas);
|
||||
}
|
||||
|
||||
// Regenerate the tile16 blockset to reflect changes
|
||||
RETURN_IF_ERROR(RefreshTile16Blockset());
|
||||
|
||||
// Update the overworld tilemap to use the new tile16 data
|
||||
RETURN_IF_ERROR(UpdateOverworldTilemap());
|
||||
|
||||
// Notify the parent editor (overworld editor) to regenerate its blockset
|
||||
// Step 4: Notify the parent editor (overworld editor) to regenerate its blockset
|
||||
if (on_changes_committed_) {
|
||||
RETURN_IF_ERROR(on_changes_committed_());
|
||||
}
|
||||
|
||||
util::logf("Committed all Tile16 changes to overworld system");
|
||||
util::logf("Committed Tile16 %d changes to overworld system", current_tile16_);
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
|
||||
@@ -211,6 +211,11 @@ void Canvas::DrawBackground(ImVec2 canvas_size) {
|
||||
|
||||
// Calculate scaled canvas bounds
|
||||
ImVec2 scaled_size = CanvasUtils::CalculateScaledCanvasSize(canvas_sz_, config_.global_scale);
|
||||
|
||||
// CRITICAL FIX: Ensure minimum size to prevent ImGui assertions
|
||||
if (scaled_size.x <= 0.0f) scaled_size.x = 1.0f;
|
||||
if (scaled_size.y <= 0.0f) scaled_size.y = 1.0f;
|
||||
|
||||
canvas_p1_ = ImVec2(canvas_p0_.x + scaled_size.x, canvas_p0_.y + scaled_size.y);
|
||||
|
||||
// Draw border and background color
|
||||
@@ -672,6 +677,7 @@ void Canvas::DrawTileOnBitmap(int tile_size, gfx::Bitmap *bitmap,
|
||||
bool Canvas::DrawTileSelector(int size, int size_y) {
|
||||
const ImGuiIO &io = GetIO();
|
||||
const bool is_hovered = IsItemHovered();
|
||||
is_hovered_ = is_hovered;
|
||||
const ImVec2 origin(canvas_p0_.x + scrolling_.x, canvas_p0_.y + scrolling_.y);
|
||||
const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
|
||||
if (size_y == 0) {
|
||||
|
||||
Reference in New Issue
Block a user