diff --git a/src/app/editor/dungeon_editor.cc b/src/app/editor/dungeon_editor.cc index c1b192b2..09ae5c65 100644 --- a/src/app/editor/dungeon_editor.cc +++ b/src/app/editor/dungeon_editor.cc @@ -285,15 +285,15 @@ void DungeonEditor::DrawRoomGraphics() { int current_block = 0; for (int block : blocks) { int offset = height * (current_block + 1); - int top_left_y = room_gfx_canvas_.GetZeroPoint().y + 2; + int top_left_y = room_gfx_canvas_.zero_point().y + 2; if (current_block >= 1) { - top_left_y = room_gfx_canvas_.GetZeroPoint().y + height * current_block; + top_left_y = room_gfx_canvas_.zero_point().y + height * current_block; } room_gfx_canvas_.GetDrawList()->AddImage( (void*)graphics_bin_[block].texture(), - ImVec2(room_gfx_canvas_.GetZeroPoint().x + 2, top_left_y), - ImVec2(room_gfx_canvas_.GetZeroPoint().x + 0x100, - room_gfx_canvas_.GetZeroPoint().y + offset)); + ImVec2(room_gfx_canvas_.zero_point().x + 2, top_left_y), + ImVec2(room_gfx_canvas_.zero_point().x + 0x100, + room_gfx_canvas_.zero_point().y + offset)); current_block += 1; } } diff --git a/src/app/editor/graphics_editor.cc b/src/app/editor/graphics_editor.cc index b79b10d7..c4dcf494 100644 --- a/src/app/editor/graphics_editor.cc +++ b/src/app/editor/graphics_editor.cc @@ -142,13 +142,21 @@ void GraphicsEditor::DrawGfxEditToolset() { } ImGui::TableNextColumn(); - ImGui::ColorEdit4("Palette Color", (float*)¤t_color_, - ImGuiColorEditFlags_NoInputs | - ImGuiColorEditFlags_NoLabel | - ImGuiColorEditFlags_NoAlpha); + auto bitmap = rom()->bitmap_manager()[current_sheet_]; + auto palette = bitmap->palette(); + for (int i = 0; i < 8; i++) { + ImGui::SameLine(); + auto color = + ImVec4(palette[i].GetRGB().x / 255.0f, palette[i].GetRGB().y / 255.0f, + palette[i].GetRGB().z / 255.0f, 255.0f); + if (ImGui::ColorButton(absl::StrFormat("Palette Color %d", i).c_str(), + color)) { + current_color_ = color; + } + } ImGui::TableNextColumn(); - gui::InputHexByte("Tile Size", &tile_size_, 0x02); + gui::InputHexByte("Tile Size", &tile_size_, 0x01); ImGui::EndTable(); } @@ -170,11 +178,11 @@ absl::Status GraphicsEditor::UpdateGfxSheetList() { auto texture = value.get()->texture(); graphics_bin_canvas_.GetDrawList()->AddImage( (void*)texture, - ImVec2(graphics_bin_canvas_.GetZeroPoint().x + 2, - graphics_bin_canvas_.GetZeroPoint().y + 2), - ImVec2(graphics_bin_canvas_.GetZeroPoint().x + + ImVec2(graphics_bin_canvas_.zero_point().x + 2, + graphics_bin_canvas_.zero_point().y + 2), + ImVec2(graphics_bin_canvas_.zero_point().x + value.get()->width() * sheet_scale_, - graphics_bin_canvas_.GetZeroPoint().y + + graphics_bin_canvas_.zero_point().y + value.get()->height() * sheet_scale_)); if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { @@ -183,8 +191,8 @@ absl::Status GraphicsEditor::UpdateGfxSheetList() { } // Add a slightly transparent rectangle behind the text - ImVec2 text_pos(graphics_bin_canvas_.GetZeroPoint().x + 2, - graphics_bin_canvas_.GetZeroPoint().y + 2); + ImVec2 text_pos(graphics_bin_canvas_.zero_point().x + 2, + graphics_bin_canvas_.zero_point().y + 2); ImVec2 text_size = ImGui::CalcTextSize(absl::StrFormat("%02X", key).c_str()); ImVec2 rent_min(text_pos.x, text_pos.y); @@ -220,11 +228,10 @@ absl::Status GraphicsEditor::UpdateGfxTabView() { } for (auto& sheet_id : open_sheets_) { - current_sheet_ = sheet_id; - bool open = true; if (ImGui::BeginTabItem(absl::StrFormat("%d", sheet_id).c_str(), &open, ImGuiTabItemFlags_None)) { + current_sheet_ = sheet_id; if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) { release_queue_.push(sheet_id); } @@ -243,18 +250,17 @@ absl::Status GraphicsEditor::UpdateGfxTabView() { ImGuiWindowFlags_AlwaysHorizontalScrollbar); auto draw_tile_event = [&]() { - uint16_t snes_color = gfx::ConvertRGBtoSNES(current_color_); - auto click_position = current_sheet_canvas_.drawn_tile_position(); - gfx::Bitmap& current_bitmap = *rom()->bitmap_manager()[sheet_id]; - current_sheet_canvas_.DrawTileOnBitmap(click_position, tile_size_, - current_bitmap, snes_color); - auto& bitmap = *rom()->bitmap_manager().mutable_bitmap(sheet_id); - rom()->UpdateBitmap(&bitmap); + gfx::Bitmap& current_bitmap = + *rom()->mutable_bitmap_manager()->mutable_bitmap(sheet_id); + current_sheet_canvas_.DrawTileOnBitmap(tile_size_, current_bitmap, + current_color_); + rom()->UpdateBitmap(¤t_bitmap); }; + auto size = ImVec2(0x80, 0x20); current_sheet_canvas_.UpdateColorPainter( *rom()->bitmap_manager()[sheet_id], current_color_, draw_tile_event, - ImVec2(0x100, 0x40), tile_size_, current_scale_, 8.0f); + size, tile_size_, current_scale_, 8.0f); ImGui::EndChild(); ImGui::EndTabItem(); } diff --git a/src/app/editor/graphics_editor.h b/src/app/editor/graphics_editor.h index 2dbf9719..448cb300 100644 --- a/src/app/editor/graphics_editor.h +++ b/src/app/editor/graphics_editor.h @@ -106,7 +106,7 @@ class GraphicsEditor : public SharedROM { // Member Variables ImVec4 current_color_; uint16_t current_sheet_ = 0; - uint8_t tile_size_ = 0x08; + uint8_t tile_size_ = 0x01; std::set open_sheets_; std::set child_window_sheets_; std::stack release_queue_; diff --git a/src/app/editor/overworld_editor.cc b/src/app/editor/overworld_editor.cc index 64ed9755..f11c115e 100644 --- a/src/app/editor/overworld_editor.cc +++ b/src/app/editor/overworld_editor.cc @@ -27,6 +27,7 @@ namespace yaze { namespace app { namespace editor { +using ImGui::Button; using ImGui::Separator; using ImGui::TableHeadersRow; using ImGui::TableNextColumn; @@ -93,10 +94,19 @@ absl::Status OverworldEditor::DrawToolset() { status_ = Redo(); } - TEXT_COLUMN(ICON_MD_MORE_VERT) // Separator - BUTTON_COLUMN(ICON_MD_ZOOM_OUT) // Zoom Out - BUTTON_COLUMN(ICON_MD_ZOOM_IN) // Zoom In - TEXT_COLUMN(ICON_MD_MORE_VERT) // Separator + TEXT_COLUMN(ICON_MD_MORE_VERT) // Separator + + NEXT_COLUMN() + if (ImGui::Button(ICON_MD_ZOOM_OUT)) { + ow_map_canvas_.ZoomOut(); + } + + NEXT_COLUMN() + if (ImGui::Button(ICON_MD_ZOOM_IN)) { + ow_map_canvas_.ZoomIn(); + } + + TEXT_COLUMN(ICON_MD_MORE_VERT) // Separator NEXT_COLUMN() if (ImGui::Button(ICON_MD_DRAW)) { @@ -288,24 +298,6 @@ bool OverworldEditor::IsMouseHoveringOverEntrance( // ---------------------------------------------------------------------------- -void OverworldEditor::DrawOverworldMaps() { - int xx = 0; - int yy = 0; - for (int i = 0; i < 0x40; i++) { - int world_index = i + (current_world_ * 0x40); - int map_x = (xx * 0x200); - int map_y = (yy * 0x200); - ow_map_canvas_.DrawBitmap(maps_bmp_[world_index], map_x, map_y); - xx++; - if (xx >= 8) { - yy++; - xx = 0; - } - } -} - -// ---------------------------------------------------------------------------- - void OverworldEditor::DrawOverworldSprites() { for (const auto &sprite : overworld_.Sprites(game_state_)) { // Get the sprite's bitmap and real X and Y positions @@ -325,12 +317,28 @@ void OverworldEditor::DrawOverworldSprites() { // ---------------------------------------------------------------------------- +void OverworldEditor::DrawOverworldMaps() { + int xx = 0; + int yy = 0; + for (int i = 0; i < 0x40; i++) { + int world_index = i + (current_world_ * 0x40); + int map_x = (xx * 0x200 * ow_map_canvas_.global_scale()); + int map_y = (yy * 0x200 * ow_map_canvas_.global_scale()); + ow_map_canvas_.DrawBitmap(maps_bmp_[world_index], map_x, map_y, + ow_map_canvas_.global_scale()); + xx++; + if (xx >= 8) { + yy++; + xx = 0; + } + } +} + void OverworldEditor::DrawOverworldEdits() { auto mouse_position = ow_map_canvas_.drawn_tile_position(); - auto canvas_size = ow_map_canvas_.GetCanvasSize(); + auto canvas_size = ow_map_canvas_.canvas_size(); int x = mouse_position.x / canvas_size.x; int y = mouse_position.y / canvas_size.y; - auto index = x + (y * 8); // Determine which overworld map the user is currently editing. DetermineActiveMap(mouse_position); @@ -338,9 +346,6 @@ void OverworldEditor::DrawOverworldEdits() { // Render the updated map bitmap. RenderUpdatedMapBitmap(mouse_position, tile16_individual_data_[current_tile16_]); - - // Queue up the raw ROM changes. - QueueROMChanges(index, current_tile16_); } void OverworldEditor::DetermineActiveMap(const ImVec2 &mouse_position) { @@ -385,7 +390,7 @@ void OverworldEditor::RenderUpdatedMapBitmap(const ImVec2 &click_position, rom()->UpdateBitmap(¤t_bitmap); } -void OverworldEditor::QueueROMChanges(int index, ushort new_tile16) { +void OverworldEditor::SaveOverworldChanges() { // Store the changes made by the user to the ROM (or project file) rom()->QueueChanges([&]() { PRINT_IF_ERROR(overworld_.SaveOverworldMaps()); @@ -398,8 +403,6 @@ void OverworldEditor::QueueROMChanges(int index, ushort new_tile16) { }); } -// ---------------------------------------------------------------------------- - void OverworldEditor::CheckForOverworldEdits() { if (!blockset_canvas_.Points().empty()) { // User has selected a tile they want to draw from the blockset. @@ -471,10 +474,11 @@ void OverworldEditor::DrawOverworldCanvas() { ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar)) { ow_map_canvas_.DrawBackground(ImVec2(0x200 * 8, 0x200 * 8)); + ImGui::PopStyleVar(2); ow_map_canvas_.DrawContextMenu(); if (overworld_.isLoaded()) { DrawOverworldMaps(); - DrawOverworldEntrances(ow_map_canvas_.GetZeroPoint(), + DrawOverworldEntrances(ow_map_canvas_.zero_point(), ow_map_canvas_.Scrolling()); if (flags()->kDrawOverworldSprites) { DrawOverworldSprites(); @@ -486,11 +490,8 @@ void OverworldEditor::DrawOverworldCanvas() { ow_map_canvas_.DrawOverlay(); } ImGui::EndChild(); - ImGui::PopStyleVar(2); } -// ---------------------------------------------------------------------------- - // Tile 8 Selector // Displays all the individual tiles that make up a tile16. void OverworldEditor::DrawTile8Selector() { @@ -501,24 +502,22 @@ void OverworldEditor::DrawTile8Selector() { // for (const auto &[key, value] : graphics_bin_) { for (auto &[key, value] : rom()->bitmap_manager()) { int offset = 0x40 * (key + 1); - int top_left_y = graphics_bin_canvas_.GetZeroPoint().y + 2; + int top_left_y = graphics_bin_canvas_.zero_point().y + 2; if (key >= 1) { - top_left_y = graphics_bin_canvas_.GetZeroPoint().y + 0x40 * key; + top_left_y = graphics_bin_canvas_.zero_point().y + 0x40 * key; } auto texture = value.get()->texture(); graphics_bin_canvas_.GetDrawList()->AddImage( (void *)texture, - ImVec2(graphics_bin_canvas_.GetZeroPoint().x + 2, top_left_y), - ImVec2(graphics_bin_canvas_.GetZeroPoint().x + 0x100, - graphics_bin_canvas_.GetZeroPoint().y + offset)); + ImVec2(graphics_bin_canvas_.zero_point().x + 2, top_left_y), + ImVec2(graphics_bin_canvas_.zero_point().x + 0x100, + graphics_bin_canvas_.zero_point().y + offset)); } } graphics_bin_canvas_.DrawGrid(16.0f); graphics_bin_canvas_.DrawOverlay(); } -// ---------------------------------------------------------------------------- - void OverworldEditor::DrawTileSelector() { if (ImGui::BeginTabBar(kTileSelectorTab.data(), ImGuiTabBarFlags_FittingPolicyScroll)) { diff --git a/src/app/editor/overworld_editor.h b/src/app/editor/overworld_editor.h index b6abaa13..1665e941 100644 --- a/src/app/editor/overworld_editor.h +++ b/src/app/editor/overworld_editor.h @@ -98,7 +98,7 @@ class OverworldEditor : public Editor, void DrawOverworldEdits(); void RenderUpdatedMapBitmap(const ImVec2 &click_position, const Bytes &tile_data); - void QueueROMChanges(int index, ushort new_tile16); + void SaveOverworldChanges(); void DetermineActiveMap(const ImVec2 &mouse_position); void CheckForOverworldEdits(); @@ -109,7 +109,6 @@ class OverworldEditor : public Editor, void DrawTileSelector(); absl::Status LoadSpriteGraphics(); - absl::Status DrawExperimentalModal(); enum class EditingMode { diff --git a/src/app/gfx/bitmap.cc b/src/app/gfx/bitmap.cc index c6168aff..ea6cd549 100644 --- a/src/app/gfx/bitmap.cc +++ b/src/app/gfx/bitmap.cc @@ -348,8 +348,8 @@ void Bitmap::ApplyPalette(const SNESPalette &palette) { void Bitmap::ApplyPaletteWithTransparent(const SNESPalette &palette, int index) { - palette_ = palette; auto start_index = index * 7; + palette_ = palette.sub_palette(start_index, start_index + 7); std::vector colors; colors.push_back(ImVec4(0, 0, 0, 0)); for (int i = start_index; i < start_index + 7; ++i) { diff --git a/src/app/gfx/bitmap.h b/src/app/gfx/bitmap.h index 21348a1b..db269665 100644 --- a/src/app/gfx/bitmap.h +++ b/src/app/gfx/bitmap.h @@ -81,6 +81,40 @@ class Bitmap { } } + Uint8 ConvertImVec4ToIndex8(const ImVec4 &color, SDL_Surface *surface) { + if (surface->format->format != SDL_PIXELFORMAT_INDEX8) { + throw std::runtime_error( + "Surface is not in SDL_PIXELFORMAT_INDEX8 format."); + } + + // Convert ImVec4 (RGBA) to SDL_Color (RGBA) + SDL_Color sdl_color; + sdl_color.r = static_cast(color.x * 255); + sdl_color.g = static_cast(color.y * 255); + sdl_color.b = static_cast(color.z * 255); + sdl_color.a = static_cast(color.w * 255); + + // Map SDL_Color to the nearest color index in the surface's palette + return SDL_MapRGB(surface->format, sdl_color.r, sdl_color.g, sdl_color.b); + } + + void WriteColor(int position, const ImVec4 &color) { + // Convert ImVec4 (RGBA) to SDL_Color (RGBA) + SDL_Color sdl_color; + sdl_color.r = static_cast(color.x * 255); + sdl_color.g = static_cast(color.y * 255); + sdl_color.b = static_cast(color.z * 255); + sdl_color.a = static_cast(color.w * 255); + + // Map SDL_Color to the nearest color index in the surface's palette + Uint8 index = + SDL_MapRGB(surface_->format, sdl_color.r, sdl_color.g, sdl_color.b); + + // Write the color index to the pixel data + this->pixel_data_[position] = index; + modified_ = true; + } + void Cleanup() { // Reset texture_ if (texture_) { @@ -106,6 +140,15 @@ class Bitmap { palette_.Clear(); } + auto sdl_palette() { + if (surface_ == nullptr) { + throw std::runtime_error("Surface is null."); + } + return surface_->format->palette; + } + auto palette() const { return palette_; } + auto palette_size() const { return palette_.size(); } + int width() const { return width_; } int height() const { return height_; } auto depth() const { return depth_; } diff --git a/src/app/gfx/snes_palette.h b/src/app/gfx/snes_palette.h index 1e8386c3..3affce6b 100644 --- a/src/app/gfx/snes_palette.h +++ b/src/app/gfx/snes_palette.h @@ -187,6 +187,14 @@ class SNESPalette { colors[i].SetModified(true); } + SNESPalette sub_palette(int start, int end) const { + SNESPalette pal; + for (int i = start; i < end; i++) { + pal.AddColor(colors[i]); + } + return pal; + } + private: int size_ = 0; /**< The size of the palette. */ std::vector colors; /**< The colors in the palette. */ diff --git a/src/app/gui/canvas.cc b/src/app/gui/canvas.cc index 84b67be5..d1658abc 100644 --- a/src/app/gui/canvas.cc +++ b/src/app/gui/canvas.cc @@ -36,10 +36,6 @@ void Canvas::UpdateColorPainter(const gfx::Bitmap &bitmap, const ImVec4 &color, ImVec2 bg_size, int tile_size, float scale, float grid_size) { global_scale_ = scale; - if (scale != 1.0f) { - bg_size.x *= scale / 2; - bg_size.y *= scale / 2; - } DrawBackground(bg_size); DrawContextMenu(); DrawBitmap(bitmap, 2, scale); @@ -63,7 +59,8 @@ void Canvas::DrawBackground(ImVec2 canvas_size) { canvas_p0_ = ImGui::GetCursorScreenPos(); if (!custom_canvas_size_) canvas_sz_ = ImGui::GetContentRegionAvail(); if (canvas_size.x != 0) canvas_sz_ = canvas_size; - canvas_p1_ = ImVec2(canvas_p0_.x + canvas_sz_.x, canvas_p0_.y + canvas_sz_.y); + canvas_p1_ = ImVec2(canvas_p0_.x + (canvas_sz_.x * global_scale_), + canvas_p0_.y + (canvas_sz_.y * global_scale_)); draw_list_ = ImGui::GetWindowDrawList(); // Draw border and background color draw_list_->AddRectFilled(canvas_p0_, canvas_p1_, kRectangleColor); draw_list_->AddRect(canvas_p0_, canvas_p1_, kRectangleBorder); @@ -71,7 +68,9 @@ void Canvas::DrawBackground(ImVec2 canvas_size) { void Canvas::DrawContextMenu() { const ImGuiIO &io = ImGui::GetIO(); - ImGui::InvisibleButton("canvas", canvas_sz_, kMouseFlags); + auto scaled_sz = + ImVec2(canvas_sz_.x * global_scale_, canvas_sz_.y * global_scale_); + ImGui::InvisibleButton("canvas", scaled_sz, kMouseFlags); const bool is_active = ImGui::IsItemActive(); // Held const ImVec2 origin(canvas_p0_.x + scrolling_.x, canvas_p0_.y + scrolling_.y); // Lock scrolled origin @@ -94,6 +93,11 @@ void Canvas::DrawContextMenu() { if (ImGui::BeginPopup("context")) { ImGui::MenuItem("Show Grid", nullptr, &enable_grid_); ImGui::Selectable("Show Labels", &enable_hex_tile_labels_); + if (ImGui::MenuItem("Reset Position", nullptr, false)) { + scrolling_.x = 0; + scrolling_.y = 0; + } + ImGui::Separator(); if (ImGui::MenuItem("8x8", nullptr, custom_step_ == 8.0f)) { custom_step_ = 8.0f; } @@ -106,10 +110,12 @@ void Canvas::DrawContextMenu() { if (ImGui::MenuItem("64x64", nullptr, custom_step_ == 64.0f)) { custom_step_ = 64.0f; } - if (ImGui::MenuItem("Reset Position", nullptr, false)) { - scrolling_.x = 0; - scrolling_.y = 0; - } + // Display bitmap metadata such as canvas size and global scale + ImGui::Separator(); + ImGui::Text("Canvas Size: %.0f x %.0f", canvas_sz_.x, canvas_sz_.y); + ImGui::Text("Global Scale: %.1f", global_scale_); + ImGui::Text("Mouse Position: %.0f x %.0f", mouse_pos.x, mouse_pos.y); + ImGui::EndPopup(); } } @@ -149,6 +155,8 @@ bool Canvas::DrawTilePainter(const Bitmap &bitmap, int size, float scale) { // Draw the currently selected tile on the overworld here // Save the coordinates of the selected tile. drawn_tile_pos_ = io.MousePos; + SDL_Log("Drawn tile position: %.0f, %.0f", drawn_tile_pos_.x, + drawn_tile_pos_.y); return true; } @@ -159,13 +167,17 @@ bool Canvas::DrawTilePainter(const Bitmap &bitmap, int size, float scale) { return false; } -bool Canvas::DrawSolidTilePainter(const ImVec4 &color, int size) { +bool Canvas::DrawSolidTilePainter(const ImVec4 &color, int tile_size) { const ImGuiIO &io = ImGui::GetIO(); const bool is_hovered = ImGui::IsItemHovered(); is_hovered_ = is_hovered; // Lock scrolled origin 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); + auto scaled_tile_size = tile_size * global_scale_; + + static bool is_dragging = false; + static ImVec2 start_drag_pos; if (is_hovered) { // Reset the previous tile hover @@ -175,25 +187,36 @@ bool Canvas::DrawSolidTilePainter(const ImVec4 &color, int size) { // Calculate the coordinates of the mouse ImVec2 painter_pos; - painter_pos.x = std::floor((double)mouse_pos.x / size) * size; - painter_pos.y = std::floor((double)mouse_pos.y / size) * size; + painter_pos.x = + std::floor((double)mouse_pos.x / scaled_tile_size) * scaled_tile_size; + painter_pos.y = + std::floor((double)mouse_pos.y / scaled_tile_size) * scaled_tile_size; // Clamp the size to a grid - painter_pos.x = std::clamp(painter_pos.x, 0.0f, canvas_sz_.x); - painter_pos.y = std::clamp(painter_pos.y, 0.0f, canvas_sz_.y); + painter_pos.x = + std::clamp(painter_pos.x, 0.0f, canvas_sz_.x * global_scale_); + painter_pos.y = + std::clamp(painter_pos.y, 0.0f, canvas_sz_.y * global_scale_); - auto painter_pos_end = ImVec2(painter_pos.x + size, painter_pos.y + size); + auto painter_pos_end = ImVec2(painter_pos.x + scaled_tile_size, + painter_pos.y + scaled_tile_size); points_.push_back(painter_pos); points_.push_back(painter_pos_end); draw_list_->AddRectFilled( - ImVec2(origin.x + painter_pos.x, origin.y + painter_pos.y), - ImVec2(origin.x + painter_pos.x + size, - origin.y + painter_pos.y + size), + ImVec2(origin.x + painter_pos.x + 1, origin.y + painter_pos.y + 1), + ImVec2(origin.x + painter_pos.x + scaled_tile_size, + origin.y + painter_pos.y + scaled_tile_size), IM_COL32(color.x * 255, color.y * 255, color.z * 255, 255)); if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) { - drawn_tile_pos_ = mouse_pos; + is_dragging = true; + start_drag_pos = painter_pos; + } + + if (is_dragging && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) { + is_dragging = false; + drawn_tile_pos_ = start_drag_pos; return true; } @@ -204,13 +227,12 @@ bool Canvas::DrawSolidTilePainter(const ImVec4 &color, int size) { return false; } -void Canvas::DrawTileOnBitmap(const ImVec2 &position, int tile_size, - gfx::Bitmap &bitmap, uint16_t color) { - // Calculate the tile indices based on the click position - int tile_index_x = static_cast(position.x) / tile_size; - int tile_index_y = static_cast(position.y) / tile_size; +void Canvas::DrawTileOnBitmap(int tile_size, gfx::Bitmap &bitmap, + ImVec4 color) { + const ImVec2 position = drawn_tile_pos_; + int tile_index_x = static_cast(position.x / global_scale_) / tile_size; + int tile_index_y = static_cast(position.y / global_scale_) / tile_size; - // Calculate the pixel start position based on tile index and tile size ImVec2 start_position(tile_index_x * tile_size, tile_index_y * tile_size); // Update the bitmap's pixel data based on the start_position and color @@ -221,7 +243,7 @@ void Canvas::DrawTileOnBitmap(const ImVec2 &position, int tile_size, (start_position.y + y) * bitmap.width() + (start_position.x + x); // Write the color to the pixel - bitmap.WriteToPixel(pixel_index, color); + bitmap.WriteColor(pixel_index, color); } } } @@ -299,11 +321,11 @@ void Canvas::DrawBitmap(const Bitmap &bitmap, int border_offset, bool ready) { } void Canvas::DrawBitmap(const Bitmap &bitmap, int border_offset, float scale) { - draw_list_->AddImage( - (void *)bitmap.texture(), - ImVec2(canvas_p0_.x + border_offset, canvas_p0_.y + border_offset), - ImVec2(canvas_p0_.x + (bitmap.width() * scale), - canvas_p0_.y + (bitmap.height() * scale))); + draw_list_->AddImage((void *)bitmap.texture(), + ImVec2(canvas_p0_.x, canvas_p0_.y), + ImVec2(canvas_p0_.x + (bitmap.width() * scale), + canvas_p0_.y + (bitmap.height() * scale))); + draw_list_->AddRect(canvas_p0_, canvas_p1_, kRectangleBorder); } void Canvas::DrawBitmap(const Bitmap &bitmap, int x_offset, int y_offset, @@ -417,23 +439,23 @@ void Canvas::DrawGrid(float grid_step) { if (custom_step_ != 0.f) grid_step = custom_step_; grid_step *= global_scale_; // Apply global scale to grid step - for (float x = fmodf(scrolling_.x, grid_step); x < canvas_sz_.x; - x += grid_step) + for (float x = fmodf(scrolling_.x, grid_step); + x < canvas_sz_.x * global_scale_; x += grid_step) draw_list_->AddLine(ImVec2(canvas_p0_.x + x, canvas_p0_.y), ImVec2(canvas_p0_.x + x, canvas_p1_.y), IM_COL32(200, 200, 200, 50), 0.5f); - for (float y = fmodf(scrolling_.y, grid_step); y < canvas_sz_.y; - y += grid_step) + for (float y = fmodf(scrolling_.y, grid_step); + y < canvas_sz_.y * global_scale_; y += grid_step) draw_list_->AddLine(ImVec2(canvas_p0_.x, canvas_p0_.y + y), ImVec2(canvas_p1_.x, canvas_p0_.y + y), IM_COL32(200, 200, 200, 50), 0.5f); if (enable_hex_tile_labels_) { // Draw the hex ID of the tile in the center of the tile square - for (float x = fmodf(scrolling_.x, grid_step); x < canvas_sz_.x; - x += grid_step) { - for (float y = fmodf(scrolling_.y, grid_step); y < canvas_sz_.y; - y += grid_step) { + for (float x = fmodf(scrolling_.x, grid_step); + x < canvas_sz_.x * global_scale_; x += grid_step) { + for (float y = fmodf(scrolling_.y, grid_step); + y < canvas_sz_.y * global_scale_; y += grid_step) { int tile_x = (x - scrolling_.x) / grid_step; int tile_y = (y - scrolling_.y) / grid_step; int tile_id = tile_x + (tile_y * 16); diff --git a/src/app/gui/canvas.h b/src/app/gui/canvas.h index 0b805bf2..3c89aeb5 100644 --- a/src/app/gui/canvas.h +++ b/src/app/gui/canvas.h @@ -48,8 +48,7 @@ class Canvas { bool DrawSolidTilePainter(const ImVec4& color, int size); // Draws a tile on the canvas at the specified position - void DrawTileOnBitmap(const ImVec2& position, int tile_size, - gfx::Bitmap& bitmap, uint16_t color); + void DrawTileOnBitmap(int tile_size, gfx::Bitmap& bitmap, ImVec4 color); // Dictates which tile is currently selected based on what the user clicks // in the canvas window. Represented and split apart into a grid of tiles. @@ -81,15 +80,17 @@ class Canvas { auto Points() const { return points_; } auto GetDrawList() const { return draw_list_; } - auto GetZeroPoint() const { return canvas_p0_; } + auto zero_point() const { return canvas_p0_; } auto Scrolling() const { return scrolling_; } auto drawn_tile_position() const { return drawn_tile_pos_; } - auto GetCanvasSize() const { return canvas_sz_; } + auto canvas_size() const { return canvas_sz_; } void SetCanvasSize(ImVec2 canvas_size) { canvas_sz_ = canvas_size; custom_canvas_size_ = true; } auto IsMouseHovering() const { return is_hovered_; } + void ZoomIn() { global_scale_ += 0.1f; } + void ZoomOut() { global_scale_ -= 0.1f; } void set_global_scale(float scale) { global_scale_ = scale; } auto global_scale() const { return global_scale_; } diff --git a/src/app/gui/pipeline.cc b/src/app/gui/pipeline.cc index e94f1685..d91713c0 100644 --- a/src/app/gui/pipeline.cc +++ b/src/app/gui/pipeline.cc @@ -23,18 +23,19 @@ namespace gui { void SelectablePalettePipeline(uint64_t& palette_id, bool& refresh_graphics, gfx::SNESPalette& palette) { + const auto palette_row_size = 7; if (ImGuiID child_id = ImGui::GetID((void*)(intptr_t)100); ImGui::BeginChild(child_id, ImGui::GetContentRegionAvail(), true, ImGuiWindowFlags_AlwaysVerticalScrollbar)) { ImGui::BeginGroup(); // Lock X position ImGui::Text("Palette"); for (int n = 0; n < palette.size(); n++) { - ImGui::PushID(n); - if ((n % 7) != 0) ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y); + if ((n % palette_row_size) != 0) + ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y); // Check if the current row is selected - bool is_selected = (palette_id == n / 7); + bool is_selected = (palette_id == n / palette_row_size); // Add outline rectangle to the selected row if (is_selected) { @@ -47,7 +48,7 @@ void SelectablePalettePipeline(uint64_t& palette_id, bool& refresh_graphics, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip, ImVec2(20, 20))) { - palette_id = n / 7; + palette_id = n / palette_row_size; refresh_graphics = true; } @@ -76,15 +77,15 @@ void GraphicsBinCanvasPipeline(int width, int height, int tile_size, if (is_loaded) { for (const auto& [key, value] : graphics_bin) { int offset = height * (key + 1); - int top_left_y = canvas.GetZeroPoint().y + 2; + int top_left_y = canvas.zero_point().y + 2; if (key >= 1) { - top_left_y = canvas.GetZeroPoint().y + height * key; + top_left_y = canvas.zero_point().y + height * key; } canvas.GetDrawList()->AddImage( (void*)value.texture(), - ImVec2(canvas.GetZeroPoint().x + 2, top_left_y), - ImVec2(canvas.GetZeroPoint().x + 0x100, - canvas.GetZeroPoint().y + offset)); + ImVec2(canvas.zero_point().x + 2, top_left_y), + ImVec2(canvas.zero_point().x + 0x100, + canvas.zero_point().y + offset)); } } canvas.DrawTileSelector(tile_size); @@ -108,15 +109,15 @@ void GraphicsManagerCanvasPipeline(int width, int height, int tile_size, if (is_loaded) { for (const auto& [key, value] : graphics_manager) { int offset = height * (key + 1); - int top_left_y = canvas.GetZeroPoint().y + 2; + int top_left_y = canvas.zero_point().y + 2; if (key >= 1) { - top_left_y = canvas.GetZeroPoint().y + height * key; + top_left_y = canvas.zero_point().y + height * key; } canvas.GetDrawList()->AddImage( (void*)value->texture(), - ImVec2(canvas.GetZeroPoint().x + 2, top_left_y), - ImVec2(canvas.GetZeroPoint().x + 0x100, - canvas.GetZeroPoint().y + offset)); + ImVec2(canvas.zero_point().x + 2, top_left_y), + ImVec2(canvas.zero_point().x + 0x100, + canvas.zero_point().y + offset)); } } canvas.DrawTileSelector(tile_size);