yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
room_graphics_content.cc
Go to the documentation of this file.
2
3#include <algorithm>
4#include <cstdint>
5#include <vector>
6
12#include "imgui/imgui.h"
13
14namespace yaze {
15namespace editor {
16
18 const auto blocks = room.blocks();
19 if (blocks.size() < sheet_previews_.size()) {
21 return;
22 }
23
24 bool needs_refresh =
26 if (!needs_refresh) {
27 for (size_t i = 0; i < preview_block_ids_.size(); ++i) {
28 if (preview_block_ids_[i] != blocks[i]) {
29 needs_refresh = true;
30 break;
31 }
32 }
33 }
34 if (!needs_refresh) {
35 return;
36 }
37
38 std::vector<SDL_Color> palette_colors;
39 if (SDL_Surface* bg_surface = room.bg1_buffer().bitmap().surface()) {
40 if (SDL_Palette* palette = platform::GetSurfacePalette(bg_surface)) {
41 palette_colors.assign(palette->colors,
42 palette->colors + palette->ncolors);
43 }
44 }
45
46 const auto& gfx_buffer = room.get_gfx_buffer();
47 constexpr size_t kSheetBytes = 128 * 32;
48 for (size_t i = 0; i < sheet_previews_.size(); ++i) {
49 preview_block_ids_[i] = blocks[i];
50 const size_t offset = i * kSheetBytes;
51 auto& meta = sheet_preview_metadata_[i];
52 meta = {};
53 meta.block_id = blocks[i];
54 meta.source_offset = offset;
55 if (offset + kSheetBytes > gfx_buffer.size()) {
57 continue;
58 }
59
60 std::vector<uint8_t> sheet_pixels(
61 gfx_buffer.begin() + offset, gfx_buffer.begin() + offset + kSheetBytes);
62 meta.nonzero_pixels = static_cast<int>(
63 std::count_if(sheet_pixels.begin(), sheet_pixels.end(),
64 [](uint8_t value) { return value != 0; }));
65 sheet_previews_[i].Create(128, 32, 8,
66 static_cast<int>(gfx::BitmapFormat::kIndexed),
67 sheet_pixels);
68 if (!palette_colors.empty()) {
69 sheet_previews_[i].SetPalette(palette_colors);
70 }
71 sheet_previews_[i].CreateTexture();
72 meta.width = sheet_previews_[i].width();
73 meta.height = sheet_previews_[i].height();
74 meta.bitmap_active = sheet_previews_[i].is_active();
75 meta.has_surface = sheet_previews_[i].surface() != nullptr;
76 meta.palette_colors = static_cast<int>(palette_colors.size());
77 meta.has_texture = sheet_previews_[i].texture() != nullptr;
78 }
79
80 preview_room_id_ = room.id();
82 palette_dirty_ = false;
83}
84
85void RoomGraphicsContent::Draw(bool* p_open) {
86 (void)p_open;
87 // Resolve the active dungeon editor lazily when this panel is hosted through
88 // the workspace window system instead of the legacy direct constructor.
89 if (current_room_id_ == nullptr || rooms_ == nullptr) {
90 const auto ctx = CurrentDungeonWindowContext();
91 if (ctx) {
92 current_room_id_ = ctx.editor->mutable_current_room_id();
93 rooms_ = &ctx.editor->rooms();
94 renderer_ = ctx.editor->renderer();
95 }
96 }
97
98 if (current_room_id_ == nullptr || rooms_ == nullptr) {
99 ImGui::TextDisabled("No room data available");
100 return;
101 }
102
103 const int active_room_id = *current_room_id_;
104 if (active_room_id < 0 ||
105 active_room_id >= static_cast<int>(rooms_->size())) {
106 ImGui::TextDisabled("Invalid room ID: %d", active_room_id);
107 return;
108 }
109
110 auto& room = (*rooms_)[active_room_id];
111 bool needs_render = false;
112 if (room.blocks().empty()) {
113 room.LoadRoomGraphics(room.blockset());
114 needs_render = true;
115 }
116 if (!room.AreObjectsLoaded()) {
117 room.LoadObjects();
118 needs_render = true;
119 }
120 auto& bg1_bitmap = room.bg1_buffer().bitmap();
121 if (needs_render || !bg1_bitmap.is_active() || bg1_bitmap.width() == 0) {
122 room.RenderRoomGraphics();
123 }
124 // Keep room-sheet assignments in sync with the active room header.
125 room.LoadRoomGraphics(room.blockset());
127
128 if (renderer_ != nullptr) {
130 }
131 auto blocks = room.blocks();
132
133 constexpr float kBlockWidth = 128.0f;
134 constexpr float kBlockHeight = 32.0f;
135 constexpr int kBlocksPerRow = 2;
136 constexpr float kPadding = 4.0f;
137
138 const int block_count = static_cast<int>(blocks.size());
139 const int row_count =
140 std::max(1, (block_count + kBlocksPerRow - 1) / kBlocksPerRow);
141 const ImVec2 canvas_size(
142 std::max(ImGui::GetContentRegionAvail().x,
143 kPadding + (kBlockWidth + kPadding) *
144 static_cast<float>(kBlocksPerRow)),
145 kPadding + (kBlockHeight + kPadding) * static_cast<float>(row_count));
146
147 ImGui::Text("Room %03X Graphics Blocks", active_room_id);
148 ImGui::TextDisabled("Blockset %02X | Spriteset %02X", room.blockset(),
149 room.spriteset());
150 ImGui::SameLine();
151 ImGui::Checkbox("Source Trace", &show_source_trace_);
152 ImGui::Separator();
153
154 gui::CanvasFrameOptions frame_opts;
155 frame_opts.canvas_size = canvas_size;
156 frame_opts.draw_grid = false;
157 frame_opts.draw_overlay = false;
158 frame_opts.draw_context_menu = false;
159 frame_opts.render_popups = false;
160
161 auto rt = gui::BeginCanvas(room_gfx_canvas_, frame_opts);
162
163 const float grid_width =
164 kPadding + (kBlockWidth + kPadding) * static_cast<float>(kBlocksPerRow);
165 const float x_offset = std::max(0.0f, (canvas_size.x - grid_width) * 0.5f);
166 ImDrawList* draw_list = ImGui::GetWindowDrawList();
167 for (int i = 0; i < block_count; ++i) {
168 const uint8_t block_id = blocks[static_cast<size_t>(i)];
169 const int row = i / kBlocksPerRow;
170 const int col = i % kBlocksPerRow;
171 const ImVec2 local_pos(x_offset + kPadding + col * (kBlockWidth + kPadding),
172 kPadding + row * (kBlockHeight + kPadding));
173
174 if (i < static_cast<int>(sheet_previews_.size()) &&
175 sheet_previews_[static_cast<size_t>(i)].texture() != 0) {
176 gui::BitmapPreviewOptions preview_opts;
177 preview_opts.dest_pos = local_pos;
178 preview_opts.dest_size = ImVec2(kBlockWidth, kBlockHeight);
179 preview_opts.draw_context_menu = false;
180 preview_opts.draw_grid = false;
181 preview_opts.draw_overlay = false;
182 preview_opts.render_popups = false;
183 preview_opts.ensure_texture = true;
184 gui::DrawBitmapPreview(rt, sheet_previews_[static_cast<size_t>(i)],
185 preview_opts);
186 } else {
187 const ImVec2 zero = room_gfx_canvas_.zero_point();
188 const float scale = room_gfx_canvas_.global_scale();
189 const ImVec2 screen_pos(zero.x + local_pos.x, zero.y + local_pos.y);
190 const ImVec2 screen_end(screen_pos.x + kBlockWidth * scale,
191 screen_pos.y + kBlockHeight * scale);
192 draw_list->AddRect(screen_pos, screen_end,
193 ImGui::GetColorU32(gui::GetOutlineVec4()));
194 draw_list->AddText(ImVec2(screen_pos.x + 6.0f, screen_pos.y + 6.0f),
195 ImGui::GetColorU32(gui::GetTextSecondaryVec4()),
196 block_id == 0 ? "Empty" : "Missing");
197 }
198 }
199
200 gui::EndCanvas(room_gfx_canvas_, rt, frame_opts);
201
202 if (show_source_trace_ &&
203 ImGui::CollapsingHeader(ICON_MD_BUG_REPORT " Source Trace",
204 ImGuiTreeNodeFlags_DefaultOpen)) {
205 ImGui::TextDisabled(
206 "Source: Room::get_gfx_buffer() -> preview bitmap -> queued texture");
207 ImGui::TextDisabled("Room buffer bytes: %zu", room.get_gfx_buffer().size());
208 ImGui::Separator();
209 for (int i = 0;
210 i < std::min(block_count,
211 static_cast<int>(sheet_preview_metadata_.size()));
212 ++i) {
213 const auto& meta = sheet_preview_metadata_[static_cast<size_t>(i)];
214 const uintptr_t texture_value = reinterpret_cast<uintptr_t>(
215 sheet_previews_[static_cast<size_t>(i)].texture());
216 ImGui::PushID(i);
217 ImGui::Text(
218 "Slot %02d | Block %02X | Buf +0x%04zX | %dx%d | nz=%d | pal=%d | "
219 "active=%d surf=%d tex=%d (0x%zx)",
220 i, meta.block_id, meta.source_offset, meta.width, meta.height,
221 meta.nonzero_pixels, meta.palette_colors, meta.bitmap_active,
222 meta.has_surface, meta.has_texture, texture_value);
223 ImGui::PopID();
224 }
225 }
226}
227
228} // namespace editor
229} // namespace yaze
std::array< uint8_t, 16 > preview_block_ids_
void RefreshSheetPreviews(const zelda3::Room &room)
void Draw(bool *p_open) override
Draw the panel content.
std::array< gfx::Bitmap, 16 > sheet_previews_
std::array< SheetPreviewMetadata, 16 > sheet_preview_metadata_
void ProcessTextureQueue(IRenderer *renderer)
Definition arena.cc:116
static Arena & Get()
Definition arena.cc:21
Represents a bitmap image optimized for SNES ROM hacking.
Definition bitmap.h:67
auto global_scale() const
Definition canvas.h:491
auto zero_point() const
Definition canvas.h:443
const std::array< uint8_t, 0x10000 > & get_gfx_buffer() const
Definition room.h:664
auto & bg1_buffer()
Definition room.h:669
auto blocks() const
Definition room.h:650
int id() const
Definition room.h:599
#define ICON_MD_BUG_REPORT
Definition icons.h:327
DungeonWindowContext CurrentDungeonWindowContext()
@ kIndexed
Definition bitmap.h:36
void EndCanvas(Canvas &canvas)
Definition canvas.cc:1591
void DrawBitmapPreview(const CanvasRuntime &rt, gfx::Bitmap &bitmap, const BitmapPreviewOptions &options)
Definition canvas.cc:2217
void BeginCanvas(Canvas &canvas, ImVec2 child_size)
Definition canvas.cc:1568
ImVec4 GetTextSecondaryVec4()
ImVec4 GetOutlineVec4()
SDL_Palette * GetSurfacePalette(SDL_Surface *surface)
Get the palette attached to a surface.
Definition sdl_compat.h:375
SDL2/SDL3 compatibility layer.