Refactor canvas drawing methods to remove unnecessary bitmap parameters in context menu and bitmap drawing functions; update inventory and graphics editors to use new method signatures for improved consistency and clarity.

This commit is contained in:
scawful
2025-04-16 21:44:07 -04:00
parent e7f976fcf0
commit 97788fc033
7 changed files with 165 additions and 154 deletions

View File

@@ -10,6 +10,8 @@
#include "app/gui/style.h"
#include "app/rom.h"
#include "imgui/imgui.h"
#include "imgui/imgui_internal.h"
#include "imgui_memory_editor.h"
namespace yaze {
namespace gui {
@@ -40,6 +42,13 @@ constexpr uint32_t kOutlineRect = IM_COL32(255, 255, 255, 200);
constexpr ImGuiButtonFlags kMouseFlags =
ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight;
namespace {
ImVec2 AlignPosToGrid(ImVec2 pos, float scale) {
return ImVec2(std::floor((double)pos.x / scale) * scale,
std::floor((double)pos.y / scale) * scale);
}
} // namespace
void Canvas::UpdateColorPainter(gfx::Bitmap &bitmap, const ImVec4 &color,
const std::function<void()> &event,
int tile_size, float scale) {
@@ -97,7 +106,7 @@ void Canvas::DrawBackground(ImVec2 canvas_size, bool can_drag) {
}
}
void Canvas::DrawContextMenu(gfx::Bitmap *bitmap) {
void Canvas::DrawContextMenu() {
const ImGuiIO &io = GetIO();
const ImVec2 scaled_sz(canvas_sz_.x * global_scale_,
canvas_sz_.y * global_scale_);
@@ -105,6 +114,13 @@ void Canvas::DrawContextMenu(gfx::Bitmap *bitmap) {
canvas_p0_.y + scrolling_.y); // Lock scrolled origin
const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
static bool show_bitmap_data = false;
if (show_bitmap_data && bitmap_ != nullptr) {
MemoryEditor mem_edit;
mem_edit.DrawWindow("Bitmap Data", (void *)bitmap_->data(), bitmap_->size(),
0);
}
// Context menu (under default mouse threshold)
if (ImVec2 drag_delta = GetMouseDragDelta(ImGuiMouseButton_Right);
enable_context_menu_ && drag_delta.x == 0.0f && drag_delta.y == 0.0f)
@@ -124,30 +140,30 @@ void Canvas::DrawContextMenu(gfx::Bitmap *bitmap) {
Text("Mouse Position: %.0f x %.0f", mouse_pos.x, mouse_pos.y);
EndMenu();
}
if (bitmap != nullptr) {
if (bitmap_ != nullptr) {
if (BeginMenu("Bitmap Properties")) {
Text("Size: %.0f x %.0f", scaled_sz.x, scaled_sz.y);
Text("Pitch: %d", bitmap->surface()->pitch);
Text("BitsPerPixel: %d", bitmap->surface()->format->BitsPerPixel);
Text("BytesPerPixel: %d", bitmap->surface()->format->BytesPerPixel);
Text("Pitch: %d", bitmap_->surface()->pitch);
Text("BitsPerPixel: %d", bitmap_->surface()->format->BitsPerPixel);
Text("BytesPerPixel: %d", bitmap_->surface()->format->BytesPerPixel);
EndMenu();
}
if (BeginMenu("Bitmap Format")) {
if (MenuItem("Indexed")) {
bitmap->Reformat(gfx::BitmapFormat::kIndexed);
Renderer::GetInstance().UpdateBitmap(bitmap);
bitmap_->Reformat(gfx::BitmapFormat::kIndexed);
Renderer::GetInstance().UpdateBitmap(bitmap_);
}
if (MenuItem("2BPP")) {
bitmap->Reformat(gfx::BitmapFormat::k2bpp);
Renderer::GetInstance().UpdateBitmap(bitmap);
bitmap_->Reformat(gfx::BitmapFormat::k2bpp);
Renderer::GetInstance().UpdateBitmap(bitmap_);
}
if (MenuItem("4BPP")) {
bitmap->Reformat(gfx::BitmapFormat::k4bpp);
Renderer::GetInstance().UpdateBitmap(bitmap);
bitmap_->Reformat(gfx::BitmapFormat::k4bpp);
Renderer::GetInstance().UpdateBitmap(bitmap_);
}
if (MenuItem("8BPP")) {
bitmap->Reformat(gfx::BitmapFormat::k8bpp);
Renderer::GetInstance().UpdateBitmap(bitmap);
bitmap_->Reformat(gfx::BitmapFormat::k8bpp);
Renderer::GetInstance().UpdateBitmap(bitmap_);
}
EndMenu();
}
@@ -170,9 +186,9 @@ void Canvas::DrawContextMenu(gfx::Bitmap *bitmap) {
refresh_graphics_, *palette);
if (refresh_graphics_) {
auto status = bitmap->SetPaletteWithTransparent(
auto status = bitmap_->SetPaletteWithTransparent(
*palette, edit_palette_sub_index_);
Renderer::GetInstance().UpdateBitmap(bitmap);
Renderer::GetInstance().UpdateBitmap(bitmap_);
refresh_graphics_ = false;
}
ImGui::EndChild();
@@ -180,6 +196,7 @@ void Canvas::DrawContextMenu(gfx::Bitmap *bitmap) {
}
EndMenu();
}
MenuItem("Bitmap Data", nullptr, &show_bitmap_data);
}
ImGui::Separator();
if (BeginMenu("Grid Tile Size")) {
@@ -209,50 +226,46 @@ bool Canvas::DrawTilePainter(const Bitmap &bitmap, int size, float scale) {
// 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);
const auto scaled_size = size * scale;
if (is_hovered) {
// Reset the previous tile hover
if (!points_.empty()) {
points_.clear();
}
// Erase the hover when the mouse is not in the canvas window.
if (!is_hovered) {
points_.clear();
return false;
}
// Calculate the coordinates of the mouse
ImVec2 painter_pos;
painter_pos.x =
std::floor((double)mouse_pos.x / (size * scale)) * (size * scale);
painter_pos.y =
std::floor((double)mouse_pos.y / (size * scale)) * (size * scale);
mouse_pos_in_canvas_ = painter_pos;
auto painter_pos_end =
ImVec2(painter_pos.x + (size * scale), painter_pos.y + (size * scale));
points_.push_back(painter_pos);
points_.push_back(painter_pos_end);
if (bitmap.is_active()) {
draw_list_->AddImage(
(ImTextureID)(intptr_t)bitmap.texture(),
ImVec2(origin.x + painter_pos.x, origin.y + painter_pos.y),
ImVec2(origin.x + painter_pos.x + (size)*scale,
origin.y + painter_pos.y + size * scale));
}
if (IsMouseClicked(ImGuiMouseButton_Left)) {
// Draw the currently selected tile on the overworld here
// Save the coordinates of the selected tile.
drawn_tile_pos_ = painter_pos;
return true;
} else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
// Draw the currently selected tile on the overworld here
// Save the coordinates of the selected tile.
drawn_tile_pos_ = painter_pos;
return true;
}
} else {
// Erase the hover when the mouse is not in the canvas window.
// Reset the previous tile hover
if (!points_.empty()) {
points_.clear();
}
// Calculate the coordinates of the mouse
ImVec2 paint_pos = AlignPosToGrid(mouse_pos, scaled_size);
mouse_pos_in_canvas_ = paint_pos;
auto paint_pos_end =
ImVec2(paint_pos.x + scaled_size, paint_pos.y + scaled_size);
points_.push_back(paint_pos);
points_.push_back(paint_pos_end);
if (bitmap.is_active()) {
draw_list_->AddImage((ImTextureID)(intptr_t)bitmap.texture(),
ImVec2(origin.x + paint_pos.x, origin.y + paint_pos.y),
ImVec2(origin.x + paint_pos.x + scaled_size,
origin.y + paint_pos.y + scaled_size));
}
if (IsMouseClicked(ImGuiMouseButton_Left)) {
// Draw the currently selected tile on the overworld here
// Save the coordinates of the selected tile.
drawn_tile_pos_ = paint_pos;
return true;
} else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
// Draw the currently selected tile on the overworld here
// Save the coordinates of the selected tile.
drawn_tile_pos_ = paint_pos;
return true;
}
return false;
}
@@ -264,54 +277,49 @@ bool Canvas::DrawSolidTilePainter(const ImVec4 &color, int tile_size) {
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
if (!points_.empty()) {
points_.clear();
}
// Erase the hover when the mouse is not in the canvas window.
if (!is_hovered) {
points_.clear();
return false;
}
// Calculate the coordinates of the mouse
ImVec2 painter_pos;
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 * global_scale_);
painter_pos.y =
std::clamp(painter_pos.y, 0.0f, canvas_sz_.y * global_scale_);
points_.push_back(painter_pos);
points_.push_back(ImVec2(painter_pos.x + scaled_tile_size,
painter_pos.y + scaled_tile_size));
draw_list_->AddRectFilled(
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 (IsMouseClicked(ImGuiMouseButton_Left)) {
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;
}
} else {
// Erase the hover when the mouse is not in the canvas window.
// Reset the previous tile hover
if (!points_.empty()) {
points_.clear();
}
// Calculate the coordinates of the mouse
ImVec2 paint_pos = AlignPosToGrid(mouse_pos, scaled_tile_size);
mouse_pos_in_canvas_ = paint_pos;
// Clamp the size to a grid
paint_pos.x = std::clamp(paint_pos.x, 0.0f, canvas_sz_.x * global_scale_);
paint_pos.y = std::clamp(paint_pos.y, 0.0f, canvas_sz_.y * global_scale_);
points_.push_back(paint_pos);
points_.push_back(
ImVec2(paint_pos.x + scaled_tile_size, paint_pos.y + scaled_tile_size));
draw_list_->AddRectFilled(
ImVec2(origin.x + paint_pos.x + 1, origin.y + paint_pos.y + 1),
ImVec2(origin.x + paint_pos.x + scaled_tile_size,
origin.y + paint_pos.y + scaled_tile_size),
IM_COL32(color.x * 255, color.y * 255, color.z * 255, 255));
if (IsMouseClicked(ImGuiMouseButton_Left)) {
is_dragging = true;
start_drag_pos = paint_pos;
}
if (is_dragging && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
is_dragging = false;
drawn_tile_pos_ = start_drag_pos;
return true;
}
return false;
}
@@ -362,13 +370,6 @@ bool Canvas::DrawTileSelector(int size) {
return false;
}
namespace {
ImVec2 AlignPosToGrid(ImVec2 pos, float scale) {
return ImVec2(std::floor((double)pos.x / scale) * scale,
std::floor((double)pos.y / scale) * scale);
}
} // namespace
void Canvas::DrawSelectRect(int current_map, int tile_size, float scale) {
const ImGuiIO &io = GetIO();
const ImVec2 origin(canvas_p0_.x + scrolling_.x, canvas_p0_.y + scrolling_.y);
@@ -457,8 +458,9 @@ void Canvas::DrawSelectRect(int current_map, int tile_size, float scale) {
}
}
void Canvas::DrawBitmap(const Bitmap &bitmap, int border_offset, bool ready) {
void Canvas::DrawBitmap(Bitmap &bitmap, int border_offset, bool ready) {
if (ready) {
bitmap_ = &bitmap;
draw_list_->AddImage(
(ImTextureID)(intptr_t)bitmap.texture(),
ImVec2(canvas_p0_.x + border_offset, canvas_p0_.y + border_offset),
@@ -467,10 +469,11 @@ void Canvas::DrawBitmap(const Bitmap &bitmap, int border_offset, bool ready) {
}
}
void Canvas::DrawBitmap(const Bitmap &bitmap, int border_offset, float scale) {
void Canvas::DrawBitmap(Bitmap &bitmap, int border_offset, float scale) {
if (!bitmap.is_active()) {
return;
}
bitmap_ = &bitmap;
draw_list_->AddImage((ImTextureID)(intptr_t)bitmap.texture(),
ImVec2(canvas_p0_.x, canvas_p0_.y),
ImVec2(canvas_p0_.x + (bitmap.width() * scale),
@@ -478,11 +481,12 @@ void Canvas::DrawBitmap(const Bitmap &bitmap, int border_offset, float scale) {
draw_list_->AddRect(canvas_p0_, canvas_p1_, kWhiteColor);
}
void Canvas::DrawBitmap(const Bitmap &bitmap, int x_offset, int y_offset,
float scale, int alpha) {
void Canvas::DrawBitmap(Bitmap &bitmap, int x_offset, int y_offset, float scale,
int alpha) {
if (!bitmap.is_active()) {
return;
}
bitmap_ = &bitmap;
draw_list_->AddImage(
(ImTextureID)(intptr_t)bitmap.texture(),
ImVec2(canvas_p0_.x + x_offset + scrolling_.x,
@@ -828,11 +832,11 @@ void GraphicsBinCanvasPipeline(int width, int height, int tile_size,
ImGui::EndChild();
}
void BitmapCanvasPipeline(gui::Canvas &canvas, const gfx::Bitmap &bitmap,
int width, int height, int tile_size, bool is_loaded,
void BitmapCanvasPipeline(gui::Canvas &canvas, gfx::Bitmap &bitmap, int width,
int height, int tile_size, bool is_loaded,
bool scrollbar, int canvas_id) {
auto draw_canvas = [](gui::Canvas &canvas, const gfx::Bitmap &bitmap,
int width, int height, int tile_size, bool is_loaded) {
auto draw_canvas = [](gui::Canvas &canvas, gfx::Bitmap &bitmap, int width,
int height, int tile_size, bool is_loaded) {
canvas.DrawBackground(ImVec2(width + 1, height + 1));
canvas.DrawContextMenu();
canvas.DrawBitmap(bitmap, 2, is_loaded);

View File

@@ -1,6 +1,8 @@
#ifndef YAZE_GUI_CANVAS_H
#define YAZE_GUI_CANVAS_H
#define IMGUI_DEFINE_MATH_OPERATORS
#include <cstdint>
#include <string>
@@ -32,7 +34,7 @@ enum class CanvasGridSize { k8x8, k16x16, k32x32, k64x64 };
* handling, tile painting, custom grid, and more.
*/
class Canvas : public SharedRom {
public:
public:
Canvas() = default;
explicit Canvas(const std::string &id) : canvas_id_(id) {
context_id_ = id + "Context";
@@ -47,26 +49,30 @@ public:
context_id_ = id + "Context";
SetCanvasGridSize(grid_size);
}
explicit Canvas(const std::string &id, ImVec2 canvas_size, CanvasGridSize grid_size, float global_scale)
: canvas_id_(id), custom_canvas_size_(true), canvas_sz_(canvas_size), global_scale_(global_scale) {
explicit Canvas(const std::string &id, ImVec2 canvas_size,
CanvasGridSize grid_size, float global_scale)
: canvas_id_(id),
custom_canvas_size_(true),
canvas_sz_(canvas_size),
global_scale_(global_scale) {
context_id_ = id + "Context";
SetCanvasGridSize(grid_size);
}
void SetCanvasGridSize(CanvasGridSize grid_size) {
switch (grid_size) {
case CanvasGridSize::k8x8:
custom_step_ = 8.0f;
break;
case CanvasGridSize::k16x16:
custom_step_ = 16.0f;
break;
case CanvasGridSize::k32x32:
custom_step_ = 32.0f;
break;
case CanvasGridSize::k64x64:
custom_step_ = 64.0f;
break;
case CanvasGridSize::k8x8:
custom_step_ = 8.0f;
break;
case CanvasGridSize::k16x16:
custom_step_ = 16.0f;
break;
case CanvasGridSize::k32x32:
custom_step_ = 32.0f;
break;
case CanvasGridSize::k64x64:
custom_step_ = 64.0f;
break;
}
}
@@ -83,7 +89,7 @@ public:
// Context Menu refers to what happens when the right mouse button is pressed
// This routine also handles the scrolling for the canvas.
void DrawContextMenu(gfx::Bitmap *bitmap = nullptr);
void DrawContextMenu();
// Tile painter shows a preview of the currently selected tile
// and allows the user to left click to paint the tile or right
@@ -103,15 +109,14 @@ public:
float scale = 1.0f);
// Draws the contents of the Bitmap image to the Canvas
void DrawBitmap(const Bitmap &bitmap, int border_offset = 0,
bool ready = true);
void DrawBitmap(const Bitmap &bitmap, int border_offset, float scale);
void DrawBitmap(const Bitmap &bitmap, int x_offset = 0, int y_offset = 0,
void DrawBitmap(Bitmap &bitmap, int border_offset = 0, bool ready = true);
void DrawBitmap(Bitmap &bitmap, int border_offset, float scale);
void DrawBitmap(Bitmap &bitmap, int x_offset = 0, int y_offset = 0,
float scale = 1.0f, int alpha = 255);
void DrawBitmapTable(const BitmapTable &gfx_bin);
void DrawBitmapGroup(std::vector<int> &group,
std::array<gfx::Bitmap, 4096>& tile16_individual_,
std::array<gfx::Bitmap, 4096> &tile16_individual_,
int tile_size, float scale = 1.0f);
void DrawOutline(int x, int y, int w, int h);
@@ -123,7 +128,7 @@ public:
void DrawText(std::string text, int x, int y);
void DrawGridLines(float grid_step);
void DrawGrid(float grid_step = 64.0f, int tile_id_offset = 8);
void DrawOverlay(); // last
void DrawOverlay(); // last
void DrawInfoGrid(float grid_step = 64.0f, int tile_id_offset = 8,
int label_id = 0);
@@ -138,7 +143,7 @@ public:
int tile_id = (x / custom_step_) + (y / custom_step_) * num_columns;
tile_id = tile_id / global_scale_;
if (tile_id >= num_columns * num_rows) {
tile_id = -1; // Invalid tile ID
tile_id = -1; // Invalid tile ID
}
return tile_id;
}
@@ -198,7 +203,7 @@ public:
auto hover_mouse_pos() const { return mouse_pos_in_canvas_; }
private:
private:
bool draggable_ = false;
bool is_hovered_ = false;
bool enable_grid_ = true;
@@ -219,7 +224,9 @@ private:
uint64_t edit_palette_group_name_index_ = 0;
uint64_t edit_palette_sub_index_ = 0;
ImDrawList* draw_list_ = nullptr;
Bitmap *bitmap_ = nullptr;
ImDrawList *draw_list_ = nullptr;
ImVec2 scrolling_;
ImVec2 canvas_sz_;
@@ -242,11 +249,11 @@ void GraphicsBinCanvasPipeline(int width, int height, int tile_size,
int num_sheets_to_load, int canvas_id,
bool is_loaded, BitmapTable &graphics_bin);
void BitmapCanvasPipeline(gui::Canvas &canvas, const gfx::Bitmap &bitmap,
int width, int height, int tile_size, bool is_loaded,
void BitmapCanvasPipeline(gui::Canvas &canvas, gfx::Bitmap &bitmap, int width,
int height, int tile_size, bool is_loaded,
bool scrollbar, int canvas_id);
} // namespace gui
} // namespace yaze
} // namespace gui
} // namespace yaze
#endif