#include "gtest/gtest.h" #include "zelda3/dungeon/object_drawer.h" #include "zelda3/dungeon/editor_dungeon_state.h" #include "zelda3/dungeon/room_object.h" #include "app/gfx/render/background_buffer.h" #include "app/gfx/types/snes_palette.h" #include "app/gfx/types/snes_tile.h" #include "rom/rom.h" #include "zelda3/game_data.h" namespace yaze { namespace zelda3 { namespace { class ObjectDrawerTest : public ::testing::Test { protected: void SetUp() override { // Initialize minimal dependencies state_ = std::make_unique(nullptr, nullptr); // Initialize ObjectDrawer drawer_ = std::make_unique(nullptr, 0); // Room ID 0 } std::unique_ptr state_; std::unique_ptr drawer_; }; TEST_F(ObjectDrawerTest, ChestStateHandling) { // Setup a chest object (ID 0x140 maps to DrawChest) RoomObject chest_obj(0x140, 10, 10, 0); // Setup background buffer (dummy) gfx::BackgroundBuffer bg(256, 256); // Setup tiles // 4 tiles for closed state, 4 tiles for open state (total 8) std::vector tiles; for (int i = 0; i < 8; ++i) { tiles.emplace_back(i, 0, false, false, false); } // Setup PaletteGroup (dummy) gfx::PaletteGroup palette_group; // Test Closed State (Default) // Set chest closed state_->SetChestOpen(0, 0, false); // Draw // Should use first 4 tiles // We rely on DrawObject calling DrawChest internally // We need to inject the tiles into the object for DrawObject to use them // But DrawObject calls mutable_obj.tiles() which decodes tiles from ROM... // Wait, DrawObject decodes tiles using RoomObject::tiles() which might require ROM access if not cached. // BUT, RoomObject has a `tiles_` member. We can set it? // RoomObject::tiles() returns a span. // We need to populate the tiles in the object. // RoomObject doesn't have a setter for tiles, it usually decodes them. // However, for testing, we might need to subclass or mock. // Actually, ObjectDrawer::DrawObject calls `mutable_obj.tiles()`. // If `tiles_` is empty, it might try to decode. // We need to ensure `tiles_` is populated. // Let's check RoomObject definition. // If we can't easily populate tiles, we might need to call DrawChest directly. // But DrawChest is private. // We can make a derived class of ObjectDrawer that exposes DrawChest for testing. } class TestableObjectDrawer : public ObjectDrawer { public: using ObjectDrawer::ObjectDrawer; void PublicDrawChest(const RoomObject& obj, gfx::BackgroundBuffer& bg, std::span tiles, const DungeonState* state) { DrawChest(obj, bg, tiles, state); } void ResetIndex() { ResetChestIndex(); } }; TEST_F(ObjectDrawerTest, ChestStateHandlingDirect) { // Use TestableObjectDrawer TestableObjectDrawer test_drawer(nullptr, 0); RoomObject chest_obj(0x140, 10, 10, 0); gfx::BackgroundBuffer bg(256, 256); std::vector tiles; for (int i = 0; i < 8; ++i) { tiles.emplace_back(i, 0, false, false, false); } // Test Closed State state_->SetChestOpen(0, 0, false); test_drawer.PublicDrawChest(chest_obj, bg, tiles, state_.get()); // Reset index test_drawer.ResetIndex(); // Test Open State state_->SetChestOpen(0, 0, true); test_drawer.PublicDrawChest(chest_obj, bg, tiles, state_.get()); // Verify no crash. // To verify logic, we'd need to inspect bg pixels or mock WriteTile8. // For now, this ensures the code path is executed and state is queried. } } // namespace } // namespace zelda3 } // namespace yaze