12#include "imgui/imgui.h"
19using ImGui::BeginMenu;
21using ImGui::GetContentRegionAvail;
22using ImGui::GetCursorScreenPos;
24using ImGui::GetMouseDragDelta;
25using ImGui::GetWindowDrawList;
26using ImGui::IsItemActive;
27using ImGui::IsItemHovered;
28using ImGui::IsMouseClicked;
29using ImGui::IsMouseDragging;
31using ImGui::OpenPopupOnItemClick;
32using ImGui::Selectable;
41 ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight;
44 const std::function<
void()> &event,
45 int tile_size,
float scale) {
58 float grid_size,
int label_id) {
77 ImGui::InvisibleButton(
83 const ImGuiIO &io = GetIO();
84 const bool is_active = IsItemActive();
87 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
90 if (
const float mouse_threshold_for_pan =
93 IsMouseDragging(ImGuiMouseButton_Right, mouse_threshold_for_pan)) {
101 const ImGuiIO &io = GetIO();
106 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
109 if (ImVec2 drag_delta = GetMouseDragDelta(ImGuiMouseButton_Right);
111 OpenPopupOnItemClick(
context_id_.c_str(), ImGuiPopupFlags_MouseButtonRight);
115 if (MenuItem(
"Reset Position",
nullptr,
false)) {
121 if (BeginMenu(
"Canvas Properties")) {
124 Text(
"Mouse Position: %.0f x %.0f", mouse_pos.x, mouse_pos.y);
127 if (bitmap !=
nullptr) {
128 if (BeginMenu(
"Bitmap Properties")) {
129 Text(
"Size: %.0f x %.0f", scaled_sz.x, scaled_sz.y);
130 Text(
"Pitch: %d", bitmap->
surface()->pitch);
131 Text(
"BitsPerPixel: %d", bitmap->
surface()->format->BitsPerPixel);
132 Text(
"BytesPerPixel: %d", bitmap->
surface()->format->BytesPerPixel);
135 if (BeginMenu(
"Bitmap Format")) {
136 if (MenuItem(
"Indexed")) {
140 if (MenuItem(
"2BPP")) {
144 if (MenuItem(
"4BPP")) {
148 if (MenuItem(
"8BPP")) {
154 if (BeginMenu(
"Bitmap Palette")) {
155 if (
rom()->is_loaded()) {
157 ImGui::SetNextItemWidth(100.f);
161 ImGui::SetNextItemWidth(100.f);
164 auto palette_group =
rom()->mutable_palette_group()->get_group(
168 if (ImGui::BeginChild(
"Palette", ImVec2(0, 300),
true)) {
185 if (BeginMenu(
"Grid Tile Size")) {
189 if (MenuItem(
"16x16",
nullptr,
custom_step_ == 16.0f)) {
192 if (MenuItem(
"32x32",
nullptr,
custom_step_ == 32.0f)) {
195 if (MenuItem(
"64x64",
nullptr,
custom_step_ == 64.0f)) {
206 const ImGuiIO &io = GetIO();
207 const bool is_hovered = IsItemHovered();
211 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
222 std::floor((
double)mouse_pos.x / (size * scale)) * (size * scale);
224 std::floor((
double)mouse_pos.y / (size * scale)) * (size * scale);
228 auto painter_pos_end =
229 ImVec2(painter_pos.x + (size * scale), painter_pos.y + (size * scale));
230 points_.push_back(painter_pos);
231 points_.push_back(painter_pos_end);
235 (ImTextureID)(intptr_t)bitmap.
texture(),
236 ImVec2(origin.x + painter_pos.x, origin.y + painter_pos.y),
237 ImVec2(origin.x + painter_pos.x + (size)*scale,
238 origin.y + painter_pos.y + size * scale));
241 if (IsMouseClicked(ImGuiMouseButton_Left)) {
246 }
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
260 const ImGuiIO &io = GetIO();
261 const bool is_hovered = IsItemHovered();
265 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
268 static bool is_dragging =
false;
269 static ImVec2 start_drag_pos;
280 std::floor((
double)mouse_pos.x / scaled_tile_size) * scaled_tile_size;
282 std::floor((
double)mouse_pos.y / scaled_tile_size) * scaled_tile_size;
290 points_.push_back(painter_pos);
291 points_.push_back(ImVec2(painter_pos.x + scaled_tile_size,
292 painter_pos.y + scaled_tile_size));
295 ImVec2(origin.x + painter_pos.x + 1, origin.y + painter_pos.y + 1),
296 ImVec2(origin.x + painter_pos.x + scaled_tile_size,
297 origin.y + painter_pos.y + scaled_tile_size),
298 IM_COL32(color.x * 255, color.y * 255, color.z * 255, 255));
300 if (IsMouseClicked(ImGuiMouseButton_Left)) {
302 start_drag_pos = painter_pos;
305 if (is_dragging && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
321 int tile_index_x =
static_cast<int>(position.x /
global_scale_) / tile_size;
322 int tile_index_y =
static_cast<int>(position.y /
global_scale_) / tile_size;
324 ImVec2 start_position(tile_index_x * tile_size, tile_index_y * tile_size);
327 for (
int y = 0; y < tile_size; ++y) {
328 for (
int x = 0; x < tile_size; ++x) {
331 (start_position.y + y) * bitmap->
width() + (start_position.x + x);
340 const ImGuiIO &io = GetIO();
341 const bool is_hovered = IsItemHovered();
343 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
345 if (is_hovered && IsMouseClicked(ImGuiMouseButton_Left)) {
350 painter_pos.x = std::floor((
double)mouse_pos.x / size) * size;
351 painter_pos.y = std::floor((
double)mouse_pos.y / size) * size;
353 points_.push_back(painter_pos);
354 points_.push_back(ImVec2(painter_pos.x + size, painter_pos.y + size));
358 if (is_hovered && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
367 return ImVec2(std::floor((
double)pos.x / scale) * scale,
368 std::floor((
double)pos.y / scale) * scale);
373 const ImGuiIO &io = GetIO();
375 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
376 static ImVec2 drag_start_pos;
377 const float scaled_size = tile_size * scale;
378 static bool dragging =
false;
379 constexpr int small_map_size = 0x200;
380 int superY = current_map / 8;
381 int superX = current_map % 8;
384 if (IsMouseClicked(ImGuiMouseButton_Right)) {
385 ImVec2 painter_pos = AlignPosToGrid(mouse_pos, scaled_size);
386 int painter_x = painter_pos.x;
387 int painter_y = painter_pos.y;
389 auto tile16_x = (painter_x % small_map_size) / (small_map_size / 0x20);
390 auto tile16_y = (painter_y % small_map_size) / (small_map_size / 0x20);
392 int index_x = superX * 0x20 + tile16_x;
393 int index_y = superY * 0x20 + tile16_y;
399 drag_start_pos = AlignPosToGrid(mouse_pos, scaled_size);
403 ImVec2 drag_end_pos = AlignPosToGrid(mouse_pos, scaled_size);
404 if (ImGui::IsMouseDragging(ImGuiMouseButton_Right)) {
405 auto start = ImVec2(
canvas_p0_.x + drag_start_pos.x,
407 auto end = ImVec2(
canvas_p0_.x + drag_end_pos.x + tile_size,
415 if (!ImGui::IsMouseDown(ImGuiMouseButton_Right)) {
419 constexpr int tile16_size = 16;
420 int start_x = std::floor(drag_start_pos.x / scaled_size) * tile16_size;
421 int start_y = std::floor(drag_start_pos.y / scaled_size) * tile16_size;
422 int end_x = std::floor(drag_end_pos.x / scaled_size) * tile16_size;
423 int end_y = std::floor(drag_end_pos.y / scaled_size) * tile16_size;
426 if (start_x > end_x) std::swap(start_x, end_x);
427 if (start_y > end_y) std::swap(start_y, end_y);
431 constexpr int tiles_per_local_map = small_map_size / 16;
434 for (
int y = start_y; y <= end_y; y += tile16_size) {
435 for (
int x = start_x; x <= end_x; x += tile16_size) {
437 int local_map_x = x / small_map_size;
438 int local_map_y = y / small_map_size;
441 int tile16_x = (x % small_map_size) / tile16_size;
442 int tile16_y = (y % small_map_size) / tile16_size;
445 int index_x = local_map_x * tiles_per_local_map + tile16_x;
446 int index_y = local_map_y * tiles_per_local_map + tile16_y;
463 (ImTextureID)(intptr_t)bitmap.
texture(),
482 float scale,
int alpha) {
487 (ImTextureID)(intptr_t)bitmap.
texture(),
493 ImVec2(0, 0), ImVec2(1, 1), IM_COL32(255, 255, 255, alpha));
498 for (
const auto &[key, value] : gfx_bin) {
499 int offset = 0x40 * (key + 1);
504 draw_list_->AddImage((ImTextureID)(intptr_t)value.texture(),
524 IM_COL32(color.x, color.y, color.z, color.w));
536 std::array<gfx::Bitmap, 4096> &tile16_individual_,
537 int tile_size,
float scale) {
553 static_cast<int>(std::floor(rect_top_left.x / (tile_size * scale)));
555 static_cast<int>(std::floor(rect_top_left.y / (tile_size * scale)));
557 static_cast<int>(std::floor(rect_bottom_right.x / (tile_size * scale)));
559 static_cast<int>(std::floor(rect_bottom_right.y / (tile_size * scale)));
561 if (start_tile_x > end_tile_x) std::swap(start_tile_x, end_tile_x);
562 if (start_tile_y > end_tile_y) std::swap(start_tile_y, end_tile_y);
565 int rect_width = (end_tile_x - start_tile_x) * tile_size;
566 int rect_height = (end_tile_y - start_tile_y) * tile_size;
568 int tiles_per_row = rect_width / tile_size;
569 int tiles_per_col = rect_height / tile_size;
572 for (
int y = 0; y < tiles_per_col + 1; ++y) {
573 for (
int x = 0; x < tiles_per_row + 1; ++x) {
574 int tile_id = group[i];
577 if (tile_id >= 0 && tile_id < tile16_individual_.size()) {
579 int tile_pos_x = (x + start_tile_x) * tile_size * scale;
580 int tile_pos_y = (y + start_tile_y) * tile_size * scale;
583 DrawBitmap(tile16_individual_[tile_id], tile_pos_x, tile_pos_y, scale,
590 const ImGuiIO &io = GetIO();
592 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
593 auto new_start_pos = AlignPosToGrid(mouse_pos, tile_size * scale);
597 ImVec2(new_start_pos.x + rect_width, new_start_pos.y + rect_height));
607 IM_COL32(color.x, color.y, color.z, color.w));
609 ImVec2 outline_origin(origin.x - 1, origin.y - 1);
610 ImVec2 outline_size(size.x + 1, size.y + 1);
624 const uint32_t grid_color = IM_COL32(200, 200, 200, 50);
625 const float grid_thickness = 0.5f;
626 for (
float x = fmodf(
scrolling_.x, grid_step);
631 for (
float y = fmodf(
scrolling_.y, grid_step);
650 for (
float x = fmodf(
scrolling_.x, grid_step);
652 for (
float y = fmodf(
scrolling_.y, grid_step);
656 int tile_id = tile_x + (tile_y * tile_id_offset);
658 if (tile_id >=
labels_[label_id].size()) {
661 std::string label =
labels_[label_id][tile_id];
663 ImVec2(
canvas_p0_.x + x + (grid_step / 2) - tile_id_offset,
664 canvas_p0_.y + y + (grid_step / 2) - tile_id_offset),
678 ImVec2 tile_pos_end(tile_pos.x + grid_step, tile_pos.y + grid_step);
680 draw_list_->AddRectFilled(tile_pos, tile_pos_end,
681 IM_COL32(255, 0, 255, 255));
697 for (
float x = fmodf(
scrolling_.x, grid_step);
699 for (
float y = fmodf(
scrolling_.y, grid_step);
703 int tile_id = tile_x + (tile_y * 16);
704 std::string hex_id = absl::StrFormat(
"%02X", tile_id);
714 for (
float x = fmodf(
scrolling_.x, grid_step);
716 for (
float y = fmodf(
scrolling_.y, grid_step);
720 int tile_id = tile_x + (tile_y * tile_id_offset);
727 ImVec2(
canvas_p0_.x + x + (grid_step / 2) - tile_id_offset,
728 canvas_p0_.y + y + (grid_step / 2) - tile_id_offset),
739 for (
int n = 0; n <
points_.Size; n += 2) {
761 ImDrawList *
draw_list = ImGui::GetWindowDrawList();
763 Text(
"Blue shape is drawn first: appears in back");
764 Text(
"Red shape is drawn after: appears in front");
765 ImVec2 p0 = ImGui::GetCursorScreenPos();
766 draw_list->AddRectFilled(ImVec2(p0.x, p0.y), ImVec2(p0.x + 50, p0.y + 50),
767 IM_COL32(0, 0, 255, 255));
768 draw_list->AddRectFilled(ImVec2(p0.x + 25, p0.y + 25),
769 ImVec2(p0.x + 75, p0.y + 75),
770 IM_COL32(255, 0, 0, 255));
771 ImGui::Dummy(ImVec2(75, 75));
775 Text(
"Blue shape is drawn first, into channel 1: appears in front");
776 Text(
"Red shape is drawn after, into channel 0: appears in back");
777 ImVec2 p1 = ImGui::GetCursorScreenPos();
784 draw_list->AddRectFilled(ImVec2(p1.x, p1.y), ImVec2(p1.x + 50, p1.y + 50),
785 IM_COL32(0, 0, 255, 255));
787 draw_list->AddRectFilled(ImVec2(p1.x + 25, p1.y + 25),
788 ImVec2(p1.x + 75, p1.y + 75),
789 IM_COL32(255, 0, 0, 255));
795 ImGui::Dummy(ImVec2(75, 75));
796 Text(
"After reordering, contents of channel 0 appears below channel 1.");
801 int num_sheets_to_load,
int canvas_id,
804 if (ImGuiID child_id =
805 ImGui::GetID((ImTextureID)(intptr_t)(intptr_t)canvas_id);
806 ImGui::BeginChild(child_id, ImGui::GetContentRegionAvail(),
true,
807 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
808 canvas.
DrawBackground(ImVec2(width + 1, num_sheets_to_load * height + 1));
811 for (
const auto &[key, value] : graphics_bin) {
812 int offset = height * (key + 1);
815 top_left_y = canvas.
zero_point().y + height * key;
818 (ImTextureID)(intptr_t)value.texture(),
819 ImVec2(canvas.
zero_point().x + 2, top_left_y),
832 int width,
int height,
int tile_size,
bool is_loaded,
833 bool scrollbar,
int canvas_id) {
835 int width,
int height,
int tile_size,
bool is_loaded) {
845 if (ImGuiID child_id =
846 ImGui::GetID((ImTextureID)(intptr_t)(intptr_t)canvas_id);
847 ImGui::BeginChild(child_id, ImGui::GetContentRegionAvail(),
true,
848 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
849 draw_canvas(canvas, bitmap, width, height, tile_size, is_loaded);
853 draw_canvas(canvas, bitmap, width, height, tile_size, is_loaded);
The Renderer class represents the renderer for the Yaze application.
void UpdateBitmap(gfx::Bitmap *bitmap)
Used to update a bitmap on the screen.
Represents a bitmap image.
void Reformat(int format)
absl::Status ApplyPaletteWithTransparent(const SnesPalette &palette, size_t index, int length=7)
void WriteColor(int position, const ImVec4 &color)
Represents a canvas for drawing and manipulating graphics.
ImVector< ImVec2 > points_
ImVec2 selected_tile_pos_
void DrawOutlineWithColor(int x, int y, int w, int h, ImVec4 color)
uint64_t edit_palette_group_name_index_
ImVec2 mouse_pos_in_canvas_
bool DrawSolidTilePainter(const ImVec4 &color, int size)
bool enable_context_menu_
void DrawLayeredElements()
void DrawBitmap(const Bitmap &bitmap, int border_offset=0, bool ready=true)
bool enable_custom_labels_
void UpdateColorPainter(gfx::Bitmap &bitmap, const ImVec4 &color, const std::function< void()> &event, int tile_size, float scale=1.0f)
void DrawGridLines(float grid_step)
uint64_t edit_palette_sub_index_
void DrawRect(int x, int y, int w, int h, ImVec4 color)
bool DrawTilePainter(const Bitmap &bitmap, int size, float scale=1.0f)
ImVector< ImVec2 > selected_points_
void DrawTileOnBitmap(int tile_size, gfx::Bitmap *bitmap, ImVec4 color)
void DrawCustomHighlight(float grid_step)
uint16_t edit_palette_index_
ImVector< ImVector< std::string > > labels_
void DrawText(std::string text, int x, int y)
void DrawSelectRect(int current_map, int tile_size=0x10, float scale=1.0f)
void DrawBackground(ImVec2 canvas_size=ImVec2(0, 0), bool drag=false)
void UpdateInfoGrid(ImVec2 bg_size, int tile_size, float scale=1.0f, float grid_size=64.0f, int label_id=0)
void DrawOutline(int x, int y, int w, int h)
void DrawInfoGrid(float grid_step=64.0f, int tile_id_offset=8, int label_id=0)
bool enable_hex_tile_labels_
void DrawBitmapGroup(std::vector< int > &group, std::array< gfx::Bitmap, 4096 > &tile16_individual_, int tile_size, float scale=1.0f)
void DrawContextMenu(gfx::Bitmap *bitmap=nullptr)
void DrawBitmapTable(const BitmapTable &gfx_bin)
bool DrawTileSelector(int size)
void DrawGrid(float grid_step=64.0f, int tile_id_offset=8)
std::vector< ImVec2 > selected_tiles_
static Renderer & GetInstance()
constexpr const char * kPaletteGroupAddressesKeys[]
std::unordered_map< int, gfx::Bitmap > BitmapTable
ImVec2 AlignPosToGrid(ImVec2 pos, float scale)
Graphical User Interface (GUI) components for the application.
constexpr uint32_t kWhiteColor
constexpr uint32_t kRectangleColor
void BitmapCanvasPipeline(gui::Canvas &canvas, const gfx::Bitmap &bitmap, int width, int height, int tile_size, bool is_loaded, bool scrollbar, int canvas_id)
bool InputHexWord(const char *label, uint16_t *data, float input_width, bool no_step)
void GraphicsBinCanvasPipeline(int width, int height, int tile_size, int num_sheets_to_load, int canvas_id, bool is_loaded, gfx::BitmapTable &graphics_bin)
constexpr uint32_t kOutlineRect
void SelectablePalettePipeline(uint64_t &palette_id, bool &refresh_graphics, gfx::SnesPalette &palette)
constexpr uint32_t kBlackColor
constexpr ImGuiButtonFlags kMouseFlags
void TextWithSeparators(const absl::string_view &text)
Main namespace for the application.