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