- Moved the declaration of `AgentControlServer` to a forward declaration in the header file for better clarity and organization. - Updated the `EditorManager` constructor to initialize the version string and popup manager context. - Added conditional compilation for gRPC-related includes and commented out the agent control server initialization for future reference. - Ensured consistent definition of `IMGUI_DEFINE_MATH_OPERATORS` across multiple files to prevent potential issues with ImGui usage. Benefits: - Improved code organization and readability. - Enhanced maintainability by clarifying the initialization process and managing includes effectively.
217 lines
6.5 KiB
C++
217 lines
6.5 KiB
C++
// Integration tests for dungeon object rendering using ObjectDrawer
|
|
// Updated for DungeonEditorV2 architecture - uses ObjectDrawer (production system)
|
|
// instead of the obsolete ObjectRenderer
|
|
|
|
#ifndef IMGUI_DEFINE_MATH_OPERATORS
|
|
#define IMGUI_DEFINE_MATH_OPERATORS
|
|
#endif
|
|
|
|
#include "app/zelda3/dungeon/object_drawer.h"
|
|
#include "app/zelda3/dungeon/room.h"
|
|
#include "app/zelda3/dungeon/room_object.h"
|
|
|
|
#include <gtest/gtest.h>
|
|
#include <memory>
|
|
#include <vector>
|
|
#include <chrono>
|
|
|
|
#include "app/rom.h"
|
|
#include "app/gfx/snes_palette.h"
|
|
#include "app/gfx/background_buffer.h"
|
|
#include "testing.h"
|
|
#include "test_utils.h"
|
|
|
|
namespace yaze {
|
|
namespace test {
|
|
|
|
/**
|
|
* @brief Tests for ObjectDrawer with realistic dungeon scenarios
|
|
*
|
|
* These tests validate that ObjectDrawer correctly renders dungeon objects
|
|
* to BackgroundBuffers using pattern-based drawing routines.
|
|
*/
|
|
class DungeonObjectRenderingTests : public TestRomManager::BoundRomTest {
|
|
protected:
|
|
void SetUp() override {
|
|
BoundRomTest::SetUp();
|
|
|
|
// Create drawer
|
|
drawer_ = std::make_unique<zelda3::ObjectDrawer>(rom());
|
|
|
|
// Create background buffers
|
|
bg1_ = std::make_unique<gfx::BackgroundBuffer>(512, 512);
|
|
bg2_ = std::make_unique<gfx::BackgroundBuffer>(512, 512);
|
|
|
|
// Setup test palette
|
|
palette_group_ = CreateTestPaletteGroup();
|
|
}
|
|
|
|
void TearDown() override {
|
|
bg2_.reset();
|
|
bg1_.reset();
|
|
drawer_.reset();
|
|
BoundRomTest::TearDown();
|
|
}
|
|
|
|
gfx::PaletteGroup CreateTestPaletteGroup() {
|
|
gfx::PaletteGroup group;
|
|
gfx::SnesPalette palette;
|
|
|
|
// Create standard dungeon palette
|
|
for (int i = 0; i < 16; i++) {
|
|
int intensity = i * 16;
|
|
palette.AddColor(gfx::SnesColor(intensity, intensity, intensity));
|
|
}
|
|
|
|
group.AddPalette(palette);
|
|
return group;
|
|
}
|
|
|
|
zelda3::RoomObject CreateTestObject(int id, int x, int y, int size = 0x12, int layer = 0) {
|
|
zelda3::RoomObject obj(id, x, y, size, layer);
|
|
obj.set_rom(rom());
|
|
obj.EnsureTilesLoaded();
|
|
return obj;
|
|
}
|
|
|
|
std::unique_ptr<zelda3::ObjectDrawer> drawer_;
|
|
std::unique_ptr<gfx::BackgroundBuffer> bg1_;
|
|
std::unique_ptr<gfx::BackgroundBuffer> bg2_;
|
|
gfx::PaletteGroup palette_group_;
|
|
};
|
|
|
|
// Test basic object drawing
|
|
TEST_F(DungeonObjectRenderingTests, BasicObjectDrawing) {
|
|
std::vector<zelda3::RoomObject> objects;
|
|
objects.push_back(CreateTestObject(0x10, 5, 5, 0x12, 0)); // Wall
|
|
objects.push_back(CreateTestObject(0x20, 10, 10, 0x22, 0)); // Floor
|
|
|
|
bg1_->ClearBuffer();
|
|
bg2_->ClearBuffer();
|
|
|
|
auto status = drawer_->DrawObjectList(objects, *bg1_, *bg2_, palette_group_);
|
|
ASSERT_TRUE(status.ok()) << "Drawing failed: " << status.message();
|
|
|
|
// Verify buffers have content
|
|
auto& bg1_bitmap = bg1_->bitmap();
|
|
EXPECT_TRUE(bg1_bitmap.is_active());
|
|
EXPECT_GT(bg1_bitmap.width(), 0);
|
|
}
|
|
|
|
// Test objects on different layers
|
|
TEST_F(DungeonObjectRenderingTests, MultiLayerRendering) {
|
|
std::vector<zelda3::RoomObject> objects;
|
|
objects.push_back(CreateTestObject(0x10, 5, 5, 0x12, 0)); // BG1
|
|
objects.push_back(CreateTestObject(0x20, 10, 10, 0x22, 1)); // BG2
|
|
objects.push_back(CreateTestObject(0x30, 15, 15, 0x12, 2)); // BG3
|
|
|
|
bg1_->ClearBuffer();
|
|
bg2_->ClearBuffer();
|
|
|
|
auto status = drawer_->DrawObjectList(objects, *bg1_, *bg2_, palette_group_);
|
|
ASSERT_TRUE(status.ok());
|
|
|
|
// Both buffers should be active
|
|
EXPECT_TRUE(bg1_->bitmap().is_active());
|
|
EXPECT_TRUE(bg2_->bitmap().is_active());
|
|
}
|
|
|
|
// Test empty object list
|
|
TEST_F(DungeonObjectRenderingTests, EmptyObjectList) {
|
|
std::vector<zelda3::RoomObject> objects; // Empty
|
|
|
|
bg1_->ClearBuffer();
|
|
bg2_->ClearBuffer();
|
|
|
|
auto status = drawer_->DrawObjectList(objects, *bg1_, *bg2_, palette_group_);
|
|
// Should succeed (drawing nothing is valid)
|
|
EXPECT_TRUE(status.ok());
|
|
}
|
|
|
|
// Test large object set
|
|
TEST_F(DungeonObjectRenderingTests, LargeObjectSet) {
|
|
std::vector<zelda3::RoomObject> objects;
|
|
|
|
// Create 100 test objects
|
|
for (int i = 0; i < 100; i++) {
|
|
int x = (i % 10) * 5;
|
|
int y = (i / 10) * 5;
|
|
objects.push_back(CreateTestObject(0x10 + (i % 20), x, y, 0x12, i % 2));
|
|
}
|
|
|
|
bg1_->ClearBuffer();
|
|
bg2_->ClearBuffer();
|
|
|
|
auto start = std::chrono::high_resolution_clock::now();
|
|
auto status = drawer_->DrawObjectList(objects, *bg1_, *bg2_, palette_group_);
|
|
auto end = std::chrono::high_resolution_clock::now();
|
|
|
|
ASSERT_TRUE(status.ok());
|
|
|
|
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
|
|
// Should complete in reasonable time
|
|
EXPECT_LT(duration.count(), 1000) << "Rendered 100 objects in " << duration.count() << "ms";
|
|
}
|
|
|
|
// Test boundary conditions
|
|
TEST_F(DungeonObjectRenderingTests, BoundaryObjects) {
|
|
std::vector<zelda3::RoomObject> objects;
|
|
|
|
// Objects at boundaries
|
|
objects.push_back(CreateTestObject(0x10, 0, 0, 0x12, 0)); // Origin
|
|
objects.push_back(CreateTestObject(0x10, 63, 63, 0x12, 0)); // Max valid
|
|
objects.push_back(CreateTestObject(0x10, 32, 32, 0x12, 0)); // Center
|
|
|
|
bg1_->ClearBuffer();
|
|
bg2_->ClearBuffer();
|
|
|
|
auto status = drawer_->DrawObjectList(objects, *bg1_, *bg2_, palette_group_);
|
|
EXPECT_TRUE(status.ok());
|
|
}
|
|
|
|
// Test various object types
|
|
TEST_F(DungeonObjectRenderingTests, VariousObjectTypes) {
|
|
// Test common object types
|
|
std::vector<int> object_types = {
|
|
0x00, 0x01, 0x02, 0x03, // Floor/wall objects
|
|
0x09, 0x0A, // Diagonal objects
|
|
0x10, 0x11, 0x12, // Standard objects
|
|
0x20, 0x21, // Decorative objects
|
|
0x34, // Solid block
|
|
};
|
|
|
|
for (int obj_type : object_types) {
|
|
std::vector<zelda3::RoomObject> objects;
|
|
objects.push_back(CreateTestObject(obj_type, 10, 10, 0x12, 0));
|
|
|
|
bg1_->ClearBuffer();
|
|
bg2_->ClearBuffer();
|
|
|
|
auto status = drawer_->DrawObjectList(objects, *bg1_, *bg2_, palette_group_);
|
|
// Some object types might not be valid, that's okay
|
|
if (!status.ok()) {
|
|
std::cout << "Object type 0x" << std::hex << obj_type << std::dec
|
|
<< " not renderable: " << status.message() << std::endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Test error handling
|
|
TEST_F(DungeonObjectRenderingTests, ErrorHandling) {
|
|
// Test with null ROM
|
|
zelda3::ObjectDrawer null_drawer(nullptr);
|
|
std::vector<zelda3::RoomObject> objects;
|
|
objects.push_back(CreateTestObject(0x10, 5, 5));
|
|
|
|
bg1_->ClearBuffer();
|
|
bg2_->ClearBuffer();
|
|
|
|
auto status = null_drawer.DrawObjectList(objects, *bg1_, *bg2_, palette_group_);
|
|
EXPECT_FALSE(status.ok());
|
|
EXPECT_EQ(status.code(), absl::StatusCode::kFailedPrecondition);
|
|
}
|
|
|
|
} // namespace test
|
|
} // namespace yaze
|
|
|