78 title = absl::StrFormat(
83 title = absl::StrFormat(
89 ImGui::SetNextWindowSize(ImVec2(550, 500), ImGuiCond_FirstUseEver);
90 if (!ImGui::Begin(title.c_str(), &
is_open_)) {
102 if (ImGui::BeginTable(
"##TileEditorLayout", 2,
103 ImGuiTableFlags_Resizable |
104 ImGuiTableFlags_BordersInnerV)) {
105 ImGui::TableSetupColumn(
"Tile Grid", ImGuiTableColumnFlags_WidthFixed,
107 ImGui::TableSetupColumn(
"Source Sheet", ImGuiTableColumnFlags_WidthStretch);
109 ImGui::TableNextRow();
110 ImGui::TableNextColumn();
113 ImGui::TableNextColumn();
128 ImGui::OpenPopup(
"Shared Tile Data");
131 if (ImGui::BeginPopupModal(
"Shared Tile Data",
nullptr,
132 ImGuiWindowFlags_AlwaysAutoResize)) {
134 ImGui::Text(
"Changes will affect all of them.");
136 if (ImGui::Button(
"Apply Anyway", ImVec2(120, 0))) {
138 ImGui::CloseCurrentPopup();
141 if (ImGui::Button(
"Cancel", ImVec2(120, 0))) {
142 ImGui::CloseCurrentPopup();
184 constexpr float kScale = 4.0f;
188 ImVec2 canvas_pos = ImGui::GetCursorScreenPos();
189 ImVec2 canvas_size(grid_width, grid_height);
197 ImGui::Dummy(canvas_size);
200 ImDrawList* draw_list = ImGui::GetWindowDrawList();
204 float line_x = canvas_pos.x + gx * 8 *
kScale;
205 draw_list->AddLine(ImVec2(line_x, canvas_pos.y),
206 ImVec2(line_x, canvas_pos.y + grid_height),
207 IM_COL32(128, 128, 128, 80));
210 float line_y = canvas_pos.y + gy * 8 *
kScale;
211 draw_list->AddLine(ImVec2(canvas_pos.x, line_y),
212 ImVec2(canvas_pos.x + grid_width, line_y),
213 IM_COL32(128, 128, 128, 80));
220 ImVec2 cell_min(canvas_pos.x + cell.rel_x * 8 *
kScale,
221 canvas_pos.y + cell.rel_y * 8 *
kScale);
222 ImVec2 cell_max(cell_min.x + 8 *
kScale, cell_min.y + 8 *
kScale);
223 draw_list->AddRect(cell_min, cell_max, IM_COL32(255, 255, 0, 255), 0, 0,
228 if (ImGui::IsItemHovered() && ImGui::IsMouseClicked(0)) {
229 ImVec2 mouse = ImGui::GetMousePos();
230 int click_tile_x =
static_cast<int>((mouse.x - canvas_pos.x) / (8 *
kScale));
231 int click_tile_y =
static_cast<int>((mouse.y - canvas_pos.y) / (8 *
kScale));
245 int modified_count = 0;
247 if (cell.modified) ++modified_count;
262 ImGui::SetNextItemWidth(80);
267 constexpr float kAtlasScale = 2.0f;
269 float display_height =
272 ImVec2 atlas_pos = ImGui::GetCursorScreenPos();
273 ImVec2 atlas_size(display_width, display_height);
276 ImGui::BeginChild(
"##AtlasScroll", ImVec2(display_width + 16, 300),
true,
277 ImGuiWindowFlags_HorizontalScrollbar);
279 atlas_pos = ImGui::GetCursorScreenPos();
286 ImGui::Dummy(atlas_size);
289 ImDrawList* draw_list = ImGui::GetWindowDrawList();
293 float line_x = atlas_pos.x + gx * 8 * kAtlasScale;
294 draw_list->AddLine(ImVec2(line_x, atlas_pos.y),
295 ImVec2(line_x, atlas_pos.y + display_height),
296 IM_COL32(64, 64, 64, 60));
299 float line_y = atlas_pos.y + gy * 8 * kAtlasScale;
300 draw_list->AddLine(ImVec2(atlas_pos.x, line_y),
301 ImVec2(atlas_pos.x + display_width, line_y),
302 IM_COL32(64, 64, 64, 60));
311 ImVec2 sel_min(atlas_pos.x + src_col * 8 * kAtlasScale,
312 atlas_pos.y + src_row * 8 * kAtlasScale);
313 ImVec2 sel_max(sel_min.x + 8 * kAtlasScale, sel_min.y + 8 * kAtlasScale);
314 draw_list->AddRect(sel_min, sel_max, IM_COL32(0, 255, 255, 255), 0, 0,
319 if (ImGui::IsItemHovered() && ImGui::IsMouseClicked(0)) {
320 ImVec2 mouse = ImGui::GetMousePos();
322 static_cast<int>((mouse.x - atlas_pos.x) / (8 * kAtlasScale));
324 static_cast<int>((mouse.y - atlas_pos.y) / (8 * kAtlasScale));
326 if (click_col >= 0 &&
339 cell.tile_info.id_ =
static_cast<uint16_t
>(tile_id);
341 cell.modified =
true;
357 ImGui::TextDisabled(
"Select a tile cell to edit properties");
362 ImGui::Text(
"Cell (%d, %d)", cell.rel_x, cell.rel_y);
366 int tile_id = cell.tile_info.id_;
367 ImGui::SetNextItemWidth(80);
368 if (ImGui::InputInt(
"ID", &tile_id, 1, 16)) {
369 cell.tile_info.id_ =
static_cast<uint16_t
>(tile_id & 0x3FF);
370 cell.modified =
true;
376 int pal = cell.tile_info.palette_;
377 ImGui::SetNextItemWidth(60);
378 if (ImGui::SliderInt(
"Pal", &pal, 0, 7)) {
379 cell.tile_info.palette_ =
static_cast<uint8_t
>(pal);
380 cell.modified =
true;
386 if (ImGui::Checkbox(
"H", &cell.tile_info.horizontal_mirror_)) {
387 cell.modified =
true;
391 if (ImGui::Checkbox(
"V", &cell.tile_info.vertical_mirror_)) {
392 cell.modified =
true;
396 if (ImGui::Checkbox(
"Pri", &cell.tile_info.over_)) {
397 cell.modified =
true;
442 int modified_count = 0;
444 if (cell.modified) ++modified_count;
447 bool has_mods = modified_count > 0;
450 ImGui::Text(
"%d tile(s) modified", modified_count);
458 if (shared_count > 1) {
459 ImGui::TextColored(ImVec4(1.0f, 0.6f, 0.2f, 1.0f),
466 if (!has_mods) ImGui::BeginDisabled();
470 if (!has_mods) ImGui::EndDisabled();
475 if (!has_mods) ImGui::BeginDisabled();
480 if (!has_mods) ImGui::EndDisabled();
491 if (!ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows))
return;
497 auto find_neighbor = [&](
int dx,
int dy) ->
int {
500 int target_x = cur.rel_x + dx;
501 int target_y = cur.rel_y + dy;
502 for (
int i = 0; i < cell_count; ++i) {
511 if (ImGui::IsKeyPressed(ImGuiKey_LeftArrow,
false)) {
514 if (ImGui::IsKeyPressed(ImGuiKey_RightArrow,
false)) {
517 if (ImGui::IsKeyPressed(ImGuiKey_UpArrow,
false)) {
520 if (ImGui::IsKeyPressed(ImGuiKey_DownArrow,
false)) {
527 for (
int key = 0; key <= 7; ++key) {
528 if (ImGui::IsKeyPressed(
529 static_cast<ImGuiKey
>(ImGuiKey_0 + key),
false)) {
530 cell.tile_info.palette_ =
static_cast<uint8_t
>(key);
531 cell.modified =
true;
537 if (ImGui::IsKeyPressed(ImGuiKey_H,
false)) {
538 cell.tile_info.horizontal_mirror_ = !cell.tile_info.horizontal_mirror_;
539 cell.modified =
true;
544 if (ImGui::IsKeyPressed(ImGuiKey_V,
false)) {
545 cell.tile_info.vertical_mirror_ = !cell.tile_info.vertical_mirror_;
546 cell.modified =
true;
551 if (ImGui::IsKeyPressed(ImGuiKey_P,
false)) {
552 cell.tile_info.over_ = !cell.tile_info.over_;
553 cell.modified =
true;
559 if (ImGui::IsKeyPressed(ImGuiKey_Escape,
false)) {
568 if (ImGui::IsKeyPressed(ImGuiKey_Tab,
false)) {
569 if (cell_count > 0) {