#include "canvas.h" #include #include #include #include "app/gfx/bitmap.h" #include "app/rom.h" namespace yaze { namespace gui { 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); // Draw border and background color draw_list_ = ImGui::GetWindowDrawList(); draw_list_->AddRectFilled(canvas_p0_, canvas_p1_, IM_COL32(32, 32, 32, 255)); draw_list_->AddRect(canvas_p0_, canvas_p1_, IM_COL32(255, 255, 255, 255)); } void Canvas::DrawContextMenu() { // This will catch our interactions const ImGuiIO &io = ImGui::GetIO(); ImGui::InvisibleButton( "canvas", canvas_sz_, ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight); const bool is_hovered = ImGui::IsItemHovered(); // Hovered const bool is_active = ImGui::IsItemActive(); // Held const ImVec2 origin(canvas_p0_.x + scrolling_.x, canvas_p0_.y + scrolling_.y); // Lock scrolled origin const ImVec2 mouse_pos_in_canvas(io.MousePos.x - origin.x, io.MousePos.y - origin.y); // Pan (we use a zero mouse threshold when there's no context menu) const float mouse_threshold_for_pan = enable_context_menu_ ? -1.0f : 0.0f; if (is_active && ImGui::IsMouseDragging(ImGuiMouseButton_Right, mouse_threshold_for_pan)) { scrolling_.x += io.MouseDelta.x; scrolling_.y += io.MouseDelta.y; } // Context menu (under default mouse threshold) ImVec2 drag_delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right); if (enable_context_menu_ && drag_delta.x == 0.0f && drag_delta.y == 0.0f) ImGui::OpenPopupOnItemClick("context", ImGuiPopupFlags_MouseButtonRight); if (ImGui::BeginPopup("context")) { ImGui::MenuItem("Show Grid", nullptr, &enable_grid_); if (ImGui::MenuItem("Reset Position", nullptr, false)) { scrolling_.x = 0; scrolling_.y = 0; } if (ImGui::MenuItem("Remove all", nullptr, false, points_.Size > 0)) { points_.clear(); } ImGui::EndPopup(); } } void Canvas::DrawTilePainter(const Bitmap& bitmap, int size) { const ImGuiIO &io = ImGui::GetIO(); const bool is_hovered = ImGui::IsItemHovered(); // Hovered const ImVec2 origin(canvas_p0_.x + scrolling_.x, canvas_p0_.y + scrolling_.y); // Lock scrolled origin const ImVec2 mouse_pos_in_canvas(io.MousePos.x - origin.x, io.MousePos.y - origin.y); if (is_hovered) { if (!points_.empty()) { points_.clear(); } ImVec2 draw_tile_outline_pos; draw_tile_outline_pos.x = std::floor((double)mouse_pos_in_canvas.x / size) * size; draw_tile_outline_pos.y = std::floor((double)mouse_pos_in_canvas.y / size) * size; points_.push_back(draw_tile_outline_pos); points_.push_back( ImVec2(draw_tile_outline_pos.x + size, draw_tile_outline_pos.y + size)); draw_list_->AddImage((void *)bitmap.GetTexture(), ImVec2(draw_tile_outline_pos.x, draw_tile_outline_pos.y), ImVec2(draw_tile_outline_pos.x + (bitmap.GetWidth() * 2), draw_tile_outline_pos.y + (bitmap.GetHeight() * 2))); } else { points_.clear(); } } void Canvas::DrawTileSelector(int size) { const ImGuiIO &io = ImGui::GetIO(); const bool is_hovered = ImGui::IsItemHovered(); // Hovered const ImVec2 origin(canvas_p0_.x + scrolling_.x, canvas_p0_.y + scrolling_.y); // Lock scrolled origin const ImVec2 mouse_pos_in_canvas(io.MousePos.x - origin.x, io.MousePos.y - origin.y); if (is_hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) { if (!points_.empty()) { points_.clear(); } ImVec2 draw_tile_outline_pos; draw_tile_outline_pos.x = std::floor((double)mouse_pos_in_canvas.x / size) * size; draw_tile_outline_pos.y = std::floor((double)mouse_pos_in_canvas.y / size) * size; points_.push_back(draw_tile_outline_pos); points_.push_back( ImVec2(draw_tile_outline_pos.x + size, draw_tile_outline_pos.y + size)); } } void Canvas::DrawBitmap(const Bitmap &bitmap, int border_offset, bool ready) { if (ready) { draw_list_->AddImage( (void *)bitmap.GetTexture(), ImVec2(canvas_p0_.x + border_offset, canvas_p0_.y + border_offset), ImVec2(canvas_p0_.x + (bitmap.GetWidth() * 2), canvas_p0_.y + (bitmap.GetHeight() * 2))); } } void Canvas::DrawBitmap(const Bitmap &bitmap, int x_offset, int y_offset) { draw_list_->AddImage( (void *)bitmap.GetTexture(), ImVec2(canvas_p0_.x + x_offset + scrolling_.x, canvas_p0_.y + y_offset + scrolling_.y), ImVec2(canvas_p0_.x + x_offset + scrolling_.x + (bitmap.GetWidth()), canvas_p0_.y + y_offset + scrolling_.y + (bitmap.GetHeight()))); } void Canvas::DrawOutline(int x, int y, int w, int h) { ImVec2 origin(canvas_p0_.x + scrolling_.x + x, canvas_p0_.y + scrolling_.y + y); ImVec2 size(canvas_p0_.x + scrolling_.x + x + w, canvas_p0_.y + scrolling_.y + y + h); draw_list_->AddRect(origin, size, IM_COL32(255, 255, 255, 255)); } void Canvas::DrawRect(int x, int y, int w, int h, ImVec4 color) { ImVec2 origin(canvas_p0_.x + scrolling_.x + x, canvas_p0_.y + scrolling_.y + y); ImVec2 size(canvas_p0_.x + scrolling_.x + x + w, canvas_p0_.y + scrolling_.y + y + h); draw_list_->AddRectFilled(origin, size, IM_COL32(color.x, color.y, color.z, color.w)); } void Canvas::DrawText(std::string text, int x, int y) { draw_list_->AddText( ImVec2(canvas_p0_.x + scrolling_.x + x, canvas_p0_.y + scrolling_.y + y), IM_COL32(255, 255, 255, 255), text.data()); } void Canvas::DrawGrid(float grid_step) { // Draw grid + all lines in the canvas draw_list_->PushClipRect(canvas_p0_, canvas_p1_, true); if (enable_grid_) { for (float x = fmodf(scrolling_.x, grid_step); x < canvas_sz_.x; 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, 40)); for (float y = fmodf(scrolling_.y, grid_step); y < canvas_sz_.y; 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, 40)); } } void Canvas::DrawOverlay() { const ImVec2 origin(canvas_p0_.x + scrolling_.x, canvas_p0_.y + scrolling_.y); // Lock scrolled origin for (int n = 0; n < points_.Size; n += 2) { draw_list_->AddRect( ImVec2(origin.x + points_[n].x, origin.y + points_[n].y), ImVec2(origin.x + points_[n + 1].x, origin.y + points_[n + 1].y), IM_COL32(255, 255, 255, 255), 1.0f); } draw_list_->PopClipRect(); } } // namespace gui } // namespace yaze