yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
overworld_entity_renderer.cc
Go to the documentation of this file.
2
3#include <string>
4
5#include "absl/strings/str_format.h"
9#include "core/features.h"
10#include "imgui/imgui.h"
11#include "util/hex.h"
12#include "zelda3/common.h"
14
15namespace yaze {
16namespace editor {
17
18using namespace ImGui;
19
20// Entity colors - using unified theme colors
21namespace {
25ImVec4 GetExitColor() {
27}
28ImVec4 GetItemColor() {
30}
33}
35 const auto& theme = AgentUI::GetTheme();
36 return ImVec4{theme.status_active.x, theme.status_active.y, theme.status_active.z, 0.5f};
37}
38} // namespace
39
40// =============================================================================
41// Modern CanvasRuntime-based rendering methods (Phase 2)
42// =============================================================================
43
45 int current_world) {
46 // Don't reset hovered_entity_ here - DrawExits resets it (called first)
47 for (auto& each : overworld_->entrances()) {
48 if (each.map_id_ < 0x40 + (current_world * 0x40) &&
49 each.map_id_ >= (current_world * 0x40) && !each.deleted) {
50 ImVec4 entrance_color = GetEntranceColor();
51 if (each.is_hole_) {
52 entrance_color.w = 0.78f;
53 }
54 gui::DrawRect(rt, each.x_, each.y_, 16, 16, entrance_color);
55 if (IsMouseHoveringOverEntity(each, rt)) {
56 hovered_entity_ = &each;
57 }
58 std::string str = util::HexByte(each.entrance_id_);
59 gui::DrawText(rt, str, each.x_, each.y_);
60 }
61 }
62}
63
65 int current_world) {
66 // Reset hover state at the start of entity rendering (DrawExits is called first)
67 hovered_entity_ = nullptr;
68
69 int i = 0;
70 for (auto& each : *overworld_->mutable_exits()) {
71 if (each.map_id_ < 0x40 + (current_world * 0x40) &&
72 each.map_id_ >= (current_world * 0x40) && !each.deleted_) {
73 gui::DrawRect(rt, each.x_, each.y_, 16, 16, GetExitColor());
74 if (IsMouseHoveringOverEntity(each, rt)) {
75 hovered_entity_ = &each;
76 }
77 each.entity_id_ = i;
78 std::string str = util::HexByte(i);
79 gui::DrawText(rt, str, each.x_, each.y_);
80 }
81 i++;
82 }
83}
84
86 int current_world) {
87 for (auto& item : *overworld_->mutable_all_items()) {
88 if (item.room_map_id_ < 0x40 + (current_world * 0x40) &&
89 item.room_map_id_ >= (current_world * 0x40) && !item.deleted) {
90 gui::DrawRect(rt, item.x_, item.y_, 16, 16, GetItemColor());
91 if (IsMouseHoveringOverEntity(item, rt)) {
92 hovered_entity_ = &item;
93 }
94 std::string item_name = "";
95 if (item.id_ < zelda3::kSecretItemNames.size()) {
96 item_name = zelda3::kSecretItemNames[item.id_];
97 } else {
98 item_name = absl::StrFormat("0x%02X", item.id_);
99 }
100 gui::DrawText(rt, item_name, item.x_, item.y_);
101 }
102 }
103}
104
106 int current_world, int game_state) {
107 for (auto& sprite : *overworld_->mutable_sprites(game_state)) {
108 if (!sprite.deleted() && sprite.map_id() < 0x40 + (current_world * 0x40) &&
109 sprite.map_id() >= (current_world * 0x40)) {
110 int sprite_x = sprite.x_;
111 int sprite_y = sprite.y_;
112
113 gui::DrawRect(rt, sprite_x, sprite_y, 16, 16, GetSpriteColor());
114 if (IsMouseHoveringOverEntity(sprite, rt)) {
115 hovered_entity_ = &sprite;
116 }
117
118 if (core::FeatureFlags::get().overworld.kDrawOverworldSprites) {
119 if ((*sprite_previews_)[sprite.id()].is_active()) {
120 // For bitmap drawing, we still use the canvas pointer for now
121 // as runtime-based bitmap drawing needs the texture
122 canvas_->DrawBitmap((*sprite_previews_)[sprite.id()], sprite_x,
123 sprite_y, 2.0f);
124 }
125 }
126
127 gui::DrawText(rt, absl::StrFormat("%s", sprite.name()), sprite_x,
128 sprite_y);
129 }
130 }
131}
132
133// =============================================================================
134// Legacy rendering methods (kept for backward compatibility)
135// =============================================================================
136
137void OverworldEntityRenderer::DrawEntrances(ImVec2 canvas_p0, ImVec2 scrolling,
138 int current_world,
139 int current_mode) {
140 // Don't reset hovered_entity_ here - DrawExits resets it (called first)
141 float scale = canvas_->global_scale();
142 int i = 0;
143 for (auto& each : overworld_->entrances()) {
144 if (each.map_id_ < 0x40 + (current_world * 0x40) &&
145 each.map_id_ >= (current_world * 0x40) && !each.deleted) {
146 // Use theme-aware color with proper transparency
147 ImVec4 entrance_color = GetEntranceColor();
148 if (each.is_hole_) {
149 // Holes are more opaque for visibility
150 entrance_color.w = 0.78f; // 200/255 alpha
151 }
152 canvas_->DrawRect(each.x_, each.y_, 16, 16, entrance_color);
153 if (IsMouseHoveringOverEntity(each, canvas_p0, scrolling, scale)) {
154 hovered_entity_ = &each;
155 }
156 std::string str = util::HexByte(each.entrance_id_);
157
158 canvas_->DrawText(str, each.x_, each.y_);
159 }
160 i++;
161 }
162}
163
164void OverworldEntityRenderer::DrawExits(ImVec2 canvas_p0, ImVec2 scrolling,
165 int current_world, int current_mode) {
166 // Reset hover state at the start of entity rendering (DrawExits is called
167 // first)
168 hovered_entity_ = nullptr;
169 float scale = canvas_->global_scale();
170
171 int i = 0;
172 for (auto& each : *overworld_->mutable_exits()) {
173 if (each.map_id_ < 0x40 + (current_world * 0x40) &&
174 each.map_id_ >= (current_world * 0x40) && !each.deleted_) {
175 canvas_->DrawRect(each.x_, each.y_, 16, 16, GetExitColor());
176
177 if (IsMouseHoveringOverEntity(each, canvas_p0, scrolling, scale)) {
178 hovered_entity_ = &each;
179 }
180 each.entity_id_ = i;
181
182 std::string str = util::HexByte(i);
183 canvas_->DrawText(str, each.x_, each.y_);
184 }
185 i++;
186 }
187}
188
189void OverworldEntityRenderer::DrawItems(int current_world, int current_mode) {
190 float scale = canvas_->global_scale();
191 int i = 0;
192 for (auto& item : *overworld_->mutable_all_items()) {
193 // Get the item's bitmap and real X and Y positions
194 if (item.room_map_id_ < 0x40 + (current_world * 0x40) &&
195 item.room_map_id_ >= (current_world * 0x40) && !item.deleted) {
196 canvas_->DrawRect(item.x_, item.y_, 16, 16, GetItemColor());
197
199 canvas_->scrolling(), scale)) {
200 hovered_entity_ = &item;
201 }
202
203 std::string item_name = "";
204 if (item.id_ < zelda3::kSecretItemNames.size()) {
205 item_name = zelda3::kSecretItemNames[item.id_];
206 } else {
207 item_name = absl::StrFormat("0x%02X", item.id_);
208 }
209 canvas_->DrawText(item_name, item.x_, item.y_);
210 }
211 i++;
212 }
213}
214
215void OverworldEntityRenderer::DrawSprites(int current_world, int game_state,
216 int current_mode) {
217 float scale = canvas_->global_scale();
218 int i = 0;
219 for (auto& sprite : *overworld_->mutable_sprites(game_state)) {
220 // Filter sprites by current world - only show sprites for the current world
221 if (!sprite.deleted() && sprite.map_id() < 0x40 + (current_world * 0x40) &&
222 sprite.map_id() >= (current_world * 0x40)) {
223 // Sprites are already stored with global coordinates (realX, realY from
224 // ROM loading) So we can use sprite.x_ and sprite.y_ directly
225 int sprite_x = sprite.x_;
226 int sprite_y = sprite.y_;
227
228 // Temporarily update sprite coordinates for entity interaction
229 int original_x = sprite.x_;
230 int original_y = sprite.y_;
231
232 canvas_->DrawRect(sprite_x, sprite_y, 16, 16, GetSpriteColor());
234 canvas_->scrolling(), scale)) {
235 hovered_entity_ = &sprite;
236 }
237
239 if ((*sprite_previews_)[sprite.id()].is_active()) {
240 canvas_->DrawBitmap((*sprite_previews_)[sprite.id()], sprite_x,
241 sprite_y, 2.0f);
242 }
243 }
244
245 canvas_->DrawText(absl::StrFormat("%s", sprite.name()), sprite_x,
246 sprite_y);
247
248 // Restore original coordinates
249 sprite.x_ = original_x;
250 sprite.y_ = original_y;
251 }
252 i++;
253 }
254}
255
257 int current_map) {
259 return;
260 }
261
262 const auto& diggable_tiles = overworld_->diggable_tiles();
263 const auto& map_tiles = overworld_->GetMapTiles(current_world);
264
265 // Calculate map bounds based on current_map
266 // Each map is 32x32 tiles (512x512 pixels)
267 // Maps are arranged in an 8x8 grid per world
268 int map_x = (current_map % 8) * 32; // Tile position in world
269 int map_y = (current_map / 8) * 32;
270
271 // Iterate through the 32x32 tiles in this map
272 for (int ty = 0; ty < 32; ++ty) {
273 for (int tx = 0; tx < 32; ++tx) {
274 int world_tx = map_x + tx;
275 int world_ty = map_y + ty;
276
277 // Get the Map16 tile ID at this position
278 // Map tiles are stored [y][x]
279 if (world_ty >= 256 || world_tx >= 256) {
280 continue; // Out of bounds
281 }
282
283 uint16_t tile_id = map_tiles[world_ty][world_tx];
284
285 // Check if this tile is marked as diggable
286 if (diggable_tiles.IsDiggable(tile_id)) {
287 // Calculate pixel position (each tile is 16x16 pixels)
288 int pixel_x = world_tx * 16;
289 int pixel_y = world_ty * 16;
290
291 // Draw a semi-transparent highlight
292 canvas_->DrawRect(pixel_x, pixel_y, 16, 16, GetDiggableTileColor());
293 }
294 }
295 }
296}
297
298} // namespace editor
299} // namespace yaze
static Flags & get()
Definition features.h:118
void DrawDiggableTileHighlights(int current_world, int current_map)
Draw highlights for all diggable tiles on the current map.
void DrawItems(const gui::CanvasRuntime &rt, int current_world)
void DrawExits(const gui::CanvasRuntime &rt, int current_world)
void DrawSprites(const gui::CanvasRuntime &rt, int current_world, int game_state)
void DrawEntrances(const gui::CanvasRuntime &rt, int current_world)
void DrawBitmap(Bitmap &bitmap, int border_offset, float scale)
Definition canvas.cc:1157
auto global_scale() const
Definition canvas.h:491
void DrawRect(int x, int y, int w, int h, ImVec4 color)
Definition canvas.cc:1423
auto zero_point() const
Definition canvas.h:443
auto scrolling() const
Definition canvas.h:445
void DrawText(const std::string &text, int x, int y)
Definition canvas.cc:1428
auto mutable_sprites(int state)
Definition overworld.h:549
const DiggableTiles & diggable_tiles() const
Definition overworld.h:618
const std::vector< OverworldEntrance > & entrances() const
Definition overworld.h:557
OverworldBlockset & GetMapTiles(int world_type)
Definition overworld.h:514
Definition input.cc:22
const AgentUITheme & GetTheme()
bool IsMouseHoveringOverEntity(const zelda3::GameEntity &entity, ImVec2 canvas_p0, ImVec2 scrolling, float scale)
Check if mouse is hovering over an entity.
Definition entity.cc:26
void DrawRect(const CanvasRuntime &rt, int x, int y, int w, int h, ImVec4 color)
Definition canvas.cc:2264
ImVec4 GetEntranceColor()
Definition ui_helpers.cc:78
ImVec4 GetSpriteColor()
Definition ui_helpers.cc:93
void DrawText(const CanvasRuntime &rt, const std::string &text, int x, int y)
Definition canvas.cc:2271
ImVec4 GetItemColor()
Definition ui_helpers.cc:88
ImVec4 GetExitColor()
Definition ui_helpers.cc:83
std::string HexByte(uint8_t byte, HexStringParams params)
Definition hex.cc:30
const std::vector< std::string > kSecretItemNames
struct yaze::core::FeatureFlags::Flags::Overworld overworld