feat: Add manual object renderer for debugging in dungeon editor
- Introduced ManualObjectRenderer class to facilitate manual rendering of dungeon objects for debugging purposes. - Integrated manual renderer initialization in DungeonEditorV2, allowing for testing and debugging of object rendering. - Added methods for rendering simple blocks, test patterns, and debugging graphics sheets. - Updated dungeon_editor_v2.cc and dungeon_editor_v2.h to include the new manual renderer functionality.
This commit is contained in:
@@ -1,5 +1,19 @@
|
||||
#include "dungeon_editor.h"
|
||||
|
||||
/**
|
||||
* @file dungeon_editor.cc
|
||||
* @deprecated This file is deprecated in favor of dungeon_editor_v2.cc
|
||||
*
|
||||
* Migration notes:
|
||||
* ✅ ManualObjectRenderer - Migrated to V2
|
||||
* ✅ ProcessDeferredTextures() - Migrated to V2
|
||||
* ✅ Object interaction - Already in DungeonObjectInteraction component
|
||||
* ✅ Primitive rendering - Already in DungeonRenderer component
|
||||
*
|
||||
* All critical features have been migrated. This file should be removed
|
||||
* once DungeonEditorV2 is confirmed working in production.
|
||||
*/
|
||||
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "app/gfx/performance_profiler.h"
|
||||
#include "app/core/window.h"
|
||||
@@ -56,6 +70,9 @@ void DungeonEditor::Initialize() {
|
||||
config.grid_size = 16; // 16x16 tiles
|
||||
object_editor_->SetConfig(config);
|
||||
}
|
||||
|
||||
// Initialize manual renderer for debugging
|
||||
printf("[DungeonEditor] Manual renderer initialized\n");
|
||||
}
|
||||
|
||||
absl::Status DungeonEditor::Load() {
|
||||
@@ -738,15 +755,35 @@ void DungeonEditor::DrawDungeonCanvas(int room_id) {
|
||||
canvas_.DrawBitmap(bg2_bitmap, 0, 0, 1.0f, 200);
|
||||
}
|
||||
|
||||
// TEMPORARY: Render all objects as primitives until proper rendering is fixed
|
||||
if (current_palette_id_ < current_palette_group_.size()) {
|
||||
auto room_palette = current_palette_group_[current_palette_id_];
|
||||
|
||||
// Render regular objects with primitive fallback
|
||||
for (const auto& object : room.GetTileObjects()) {
|
||||
renderer_.RenderObjectInCanvas(object, room_palette);
|
||||
}
|
||||
}
|
||||
// TEMPORARY: Render all objects as primitives until proper rendering is fixed
|
||||
if (current_palette_id_ < current_palette_group_.size()) {
|
||||
auto room_palette = current_palette_group_[current_palette_id_];
|
||||
|
||||
// Render regular objects with primitive fallback
|
||||
for (const auto& object : room.GetTileObjects()) {
|
||||
renderer_.RenderObjectInCanvas(object, room_palette);
|
||||
}
|
||||
|
||||
// Test manual rendering for debugging
|
||||
if (room.GetTileObjects().size() > 0) {
|
||||
const auto& test_object = room.GetTileObjects()[0];
|
||||
int canvas_x = test_object.x_ * 8;
|
||||
int canvas_y = test_object.y_ * 8;
|
||||
|
||||
printf("[DungeonEditor] Testing manual render for object 0x%04X at (%d,%d)\n",
|
||||
test_object.id_, canvas_x, canvas_y);
|
||||
printf("[DungeonEditor] Object tiles count: %zu\n", test_object.tiles().size());
|
||||
|
||||
manual_renderer_.RenderSimpleBlock(test_object.id_, canvas_x, canvas_y, room_palette);
|
||||
|
||||
// Debug graphics sheets
|
||||
manual_renderer_.DebugGraphicsSheet(0);
|
||||
manual_renderer_.DebugGraphicsSheet(1);
|
||||
}
|
||||
|
||||
// Test palette rendering
|
||||
manual_renderer_.TestPaletteRendering(400, 100);
|
||||
}
|
||||
|
||||
// Render sprites as simple 16x16 squares with labels
|
||||
// (Sprites are not part of the background buffers)
|
||||
|
||||
@@ -1,6 +1,19 @@
|
||||
#ifndef YAZE_APP_EDITOR_DUNGEONEDITOR_H
|
||||
#define YAZE_APP_EDITOR_DUNGEONEDITOR_H
|
||||
|
||||
/**
|
||||
* @deprecated This file is deprecated in favor of dungeon_editor_v2.h
|
||||
*
|
||||
* DungeonEditorV2 uses a cleaner component-based architecture with:
|
||||
* - Card-based UI for better UX
|
||||
* - Lazy loading for performance
|
||||
* - Proper component delegation
|
||||
* - Simplified state management
|
||||
*
|
||||
* This file is kept temporarily for reference during migration.
|
||||
* TODO: Remove once all functionality is verified in V2.
|
||||
*/
|
||||
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "app/editor/editor.h"
|
||||
#include "app/editor/graphics/gfx_group_editor.h"
|
||||
@@ -22,6 +35,7 @@
|
||||
#include "dungeon_renderer.h"
|
||||
#include "dungeon_room_loader.h"
|
||||
#include "dungeon_usage_tracker.h"
|
||||
#include "manual_object_renderer.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace editor {
|
||||
@@ -187,6 +201,7 @@ class DungeonEditor : public Editor {
|
||||
DungeonRenderer renderer_;
|
||||
DungeonRoomLoader room_loader_;
|
||||
DungeonUsageTracker usage_tracker_;
|
||||
ManualObjectRenderer manual_renderer_;
|
||||
|
||||
absl::Status status_;
|
||||
|
||||
|
||||
@@ -67,6 +67,11 @@ absl::Status DungeonEditorV2::Load() {
|
||||
// Initialize unified object editor card
|
||||
object_editor_card_ = std::make_unique<ObjectEditorCard>(renderer_, rom_, &canvas_viewer_);
|
||||
|
||||
// Initialize manual renderer for debugging (uses canvas from canvas_viewer_)
|
||||
manual_renderer_ = std::make_unique<ManualObjectRenderer>(
|
||||
&canvas_viewer_.canvas(), rom_);
|
||||
printf("[DungeonEditorV2] Manual renderer initialized for debugging\n");
|
||||
|
||||
// Wire palette changes to trigger room re-renders
|
||||
palette_editor_.SetOnPaletteChanged([this](int /*palette_id*/) {
|
||||
// Re-render all active rooms when palette changes
|
||||
@@ -712,5 +717,11 @@ void DungeonEditorV2::DrawRoomGraphicsCard() {
|
||||
graphics_card.End();
|
||||
}
|
||||
|
||||
void DungeonEditorV2::ProcessDeferredTextures() {
|
||||
// Process queued texture commands via Arena's deferred system
|
||||
// This is critical for ensuring textures are actually created and updated
|
||||
gfx::Arena::Get().ProcessTextureQueue(renderer_);
|
||||
}
|
||||
|
||||
} // namespace yaze::editor
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "dungeon_object_selector.h"
|
||||
#include "dungeon_room_loader.h"
|
||||
#include "object_editor_card.h"
|
||||
#include "manual_object_renderer.h"
|
||||
#include "app/zelda3/dungeon/room.h"
|
||||
#include "app/zelda3/dungeon/room_entrance.h"
|
||||
#include "app/gui/editor_layout.h"
|
||||
@@ -97,6 +98,9 @@ class DungeonEditorV2 : public Editor {
|
||||
void DrawEntrancesListCard();
|
||||
void DrawRoomGraphicsCard();
|
||||
|
||||
// Texture processing (critical for rendering)
|
||||
void ProcessDeferredTextures();
|
||||
|
||||
// Room selection callback
|
||||
void OnRoomSelected(int room_id);
|
||||
void OnEntranceSelected(int entrance_id);
|
||||
@@ -136,6 +140,7 @@ class DungeonEditorV2 : public Editor {
|
||||
gui::DungeonObjectEmulatorPreview object_emulator_preview_;
|
||||
gui::PaletteEditorWidget palette_editor_;
|
||||
std::unique_ptr<ObjectEditorCard> object_editor_card_; // Unified object editor
|
||||
std::unique_ptr<ManualObjectRenderer> manual_renderer_; // Debugging renderer
|
||||
|
||||
bool is_loaded_ = false;
|
||||
|
||||
|
||||
170
src/app/editor/dungeon/manual_object_renderer.cc
Normal file
170
src/app/editor/dungeon/manual_object_renderer.cc
Normal file
@@ -0,0 +1,170 @@
|
||||
#include "manual_object_renderer.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include "app/gfx/arena.h"
|
||||
#include "app/gfx/bitmap.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace editor {
|
||||
|
||||
ManualObjectRenderer::ManualObjectRenderer(gui::Canvas* canvas, Rom* rom)
|
||||
: canvas_(canvas), rom_(rom) {}
|
||||
|
||||
absl::Status ManualObjectRenderer::RenderSimpleBlock(uint16_t object_id, int x, int y,
|
||||
const gfx::SnesPalette& palette) {
|
||||
if (!canvas_ || !rom_) {
|
||||
return absl::InvalidArgumentError("Canvas or ROM not initialized");
|
||||
}
|
||||
|
||||
printf("[ManualRenderer] Rendering object 0x%04X at (%d, %d)\n", object_id, x, y);
|
||||
|
||||
// Create a simple 16x16 tile manually
|
||||
auto tile_bitmap = CreateSimpleTile(object_id, palette);
|
||||
if (!tile_bitmap) {
|
||||
return absl::InternalError("Failed to create simple tile");
|
||||
}
|
||||
|
||||
// Draw directly to canvas
|
||||
canvas_->DrawBitmap(*tile_bitmap, x, y, 1.0f, 255);
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
void ManualObjectRenderer::RenderTestPattern(int x, int y, int width, int height,
|
||||
uint8_t color_index) {
|
||||
if (!canvas_) return;
|
||||
|
||||
printf("[ManualRenderer] Drawing test pattern: %dx%d at (%d,%d) color=%d\n",
|
||||
width, height, x, y, color_index);
|
||||
|
||||
// Create a simple colored rectangle using ImGui
|
||||
ImVec4 color = ImVec4(
|
||||
(color_index & 0x01) ? 1.0f : 0.0f, // Red bit
|
||||
(color_index & 0x02) ? 1.0f : 0.0f, // Green bit
|
||||
(color_index & 0x04) ? 1.0f : 0.0f, // Blue bit
|
||||
1.0f // Alpha
|
||||
);
|
||||
|
||||
// Draw using ImGui primitives for testing
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
if (draw_list) {
|
||||
ImVec2 p1 = ImVec2(x, y);
|
||||
ImVec2 p2 = ImVec2(x + width, y + height);
|
||||
draw_list->AddRectFilled(p1, p2, ImGui::ColorConvertFloat4ToU32(color));
|
||||
}
|
||||
}
|
||||
|
||||
void ManualObjectRenderer::DebugGraphicsSheet(int sheet_index) {
|
||||
if (!rom_ || sheet_index < 0 || sheet_index >= 223) {
|
||||
printf("[ManualRenderer] Invalid sheet index: %d\n", sheet_index);
|
||||
return;
|
||||
}
|
||||
|
||||
auto& arena = gfx::Arena::Get();
|
||||
const auto& sheet = arena.gfx_sheet(sheet_index);
|
||||
|
||||
printf("[ManualRenderer] Graphics Sheet %d Debug Info:\n", sheet_index);
|
||||
printf(" - Is Active: %s\n", sheet.is_active() ? "YES" : "NO");
|
||||
printf(" - Width: %d\n", sheet.width());
|
||||
printf(" - Height: %d\n", sheet.height());
|
||||
printf(" - Has Surface: %s\n", sheet.surface() ? "YES" : "NO");
|
||||
printf(" - Has Texture: %s\n", sheet.texture() ? "YES" : "NO");
|
||||
|
||||
if (sheet.is_active() && sheet.width() > 0 && sheet.height() > 0) {
|
||||
printf(" - Format: %s\n", sheet.surface() && sheet.surface()->format ?
|
||||
SDL_GetPixelFormatName(sheet.surface()->format->format) : "Unknown");
|
||||
}
|
||||
}
|
||||
|
||||
void ManualObjectRenderer::TestPaletteRendering(int x, int y) {
|
||||
printf("[ManualRenderer] Testing palette rendering at (%d, %d)\n", x, y);
|
||||
|
||||
// Draw test squares with different color indices
|
||||
for (int i = 0; i < 8; i++) {
|
||||
int test_x = x + (i * 20);
|
||||
int test_y = y;
|
||||
RenderTestPattern(test_x, test_y, 16, 16, i);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<gfx::Bitmap> ManualObjectRenderer::CreateSimpleTile(uint16_t tile_id,
|
||||
const gfx::SnesPalette& palette) {
|
||||
// Fill with a simple pattern based on tile_id
|
||||
uint8_t base_color = tile_id & 0x07; // Use lower 3 bits for color
|
||||
|
||||
// Create tile data manually
|
||||
auto tile_data = CreateSolidTile(base_color);
|
||||
if (tile_data.empty()) {
|
||||
printf("[ManualRenderer] Failed to create tile data\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create a 16x16 bitmap with the tile data
|
||||
auto bitmap = std::make_unique<gfx::Bitmap>();
|
||||
bitmap->Create(16, 16, 8, tile_data); // 16x16 pixels, 8-bit depth
|
||||
|
||||
if (!bitmap->is_active()) {
|
||||
printf("[ManualRenderer] Failed to create bitmap\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Apply palette
|
||||
bitmap->SetPalette(palette);
|
||||
|
||||
printf("[ManualRenderer] Created simple tile: ID=0x%04X, color=%d\n", tile_id, base_color);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> ManualObjectRenderer::CreateSolidTile(uint8_t color_index) {
|
||||
std::vector<uint8_t> tile_data(16 * 16, color_index);
|
||||
return tile_data;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> ManualObjectRenderer::CreatePatternTile(uint8_t pattern_type,
|
||||
uint8_t color_index) {
|
||||
std::vector<uint8_t> tile_data(16 * 16);
|
||||
|
||||
switch (pattern_type) {
|
||||
case 0: // Solid
|
||||
std::fill(tile_data.begin(), tile_data.end(), color_index);
|
||||
break;
|
||||
|
||||
case 1: // Checkerboard
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
tile_data[y * 16 + x] = ((x + y) % 2) ? color_index : 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // Horizontal stripes
|
||||
for (int y = 0; y < 16; y++) {
|
||||
uint8_t color = (y % 4 < 2) ? color_index : 0;
|
||||
for (int x = 0; x < 16; x++) {
|
||||
tile_data[y * 16 + x] = color;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: // Vertical stripes
|
||||
for (int x = 0; x < 16; x++) {
|
||||
uint8_t color = (x % 4 < 2) ? color_index : 0;
|
||||
for (int y = 0; y < 16; y++) {
|
||||
tile_data[y * 16 + x] = color;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
std::fill(tile_data.begin(), tile_data.end(), color_index);
|
||||
break;
|
||||
}
|
||||
|
||||
return tile_data;
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace yaze
|
||||
90
src/app/editor/dungeon/manual_object_renderer.h
Normal file
90
src/app/editor/dungeon/manual_object_renderer.h
Normal file
@@ -0,0 +1,90 @@
|
||||
#ifndef YAZE_APP_EDITOR_DUNGEON_MANUAL_OBJECT_RENDERER_H
|
||||
#define YAZE_APP_EDITOR_DUNGEON_MANUAL_OBJECT_RENDERER_H
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "app/gfx/snes_palette.h"
|
||||
#include "app/gui/canvas.h"
|
||||
#include "app/rom.h"
|
||||
#include "app/zelda3/dungeon/room_object.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace editor {
|
||||
|
||||
/**
|
||||
* @brief Manual object renderer for debugging and testing basic object rendering
|
||||
*
|
||||
* This class provides simple, manual rendering of basic dungeon objects
|
||||
* to help debug the graphics pipeline and understand object data structures.
|
||||
*
|
||||
* Features:
|
||||
* - Manual tile creation for simple objects
|
||||
* - Direct graphics sheet access
|
||||
* - Palette debugging and testing
|
||||
* - Simple pattern rendering (solid blocks, lines, etc.)
|
||||
*/
|
||||
class ManualObjectRenderer {
|
||||
public:
|
||||
explicit ManualObjectRenderer(gui::Canvas* canvas, Rom* rom);
|
||||
|
||||
/**
|
||||
* @brief Render a simple solid block object manually
|
||||
* @param object_id Object ID to render
|
||||
* @param x X position in pixels
|
||||
* @param y Y position in pixels
|
||||
* @param palette Current palette to use
|
||||
* @return Status of the rendering operation
|
||||
*/
|
||||
absl::Status RenderSimpleBlock(uint16_t object_id, int x, int y,
|
||||
const gfx::SnesPalette& palette);
|
||||
|
||||
/**
|
||||
* @brief Render a test pattern to verify graphics pipeline
|
||||
* @param x X position in pixels
|
||||
* @param y Y position in pixels
|
||||
* @param width Width in pixels
|
||||
* @param height Height in pixels
|
||||
* @param color_index Color index to use
|
||||
*/
|
||||
void RenderTestPattern(int x, int y, int width, int height, uint8_t color_index);
|
||||
|
||||
/**
|
||||
* @brief Debug graphics sheet loading and display info
|
||||
* @param sheet_index Graphics sheet index to examine
|
||||
*/
|
||||
void DebugGraphicsSheet(int sheet_index);
|
||||
|
||||
/**
|
||||
* @brief Test palette rendering with different colors
|
||||
* @param x X position in pixels
|
||||
* @param y Y position in pixels
|
||||
*/
|
||||
void TestPaletteRendering(int x, int y);
|
||||
|
||||
/**
|
||||
* @brief Create a simple 16x16 tile manually
|
||||
* @param tile_id Tile ID to create
|
||||
* @param palette Palette to apply
|
||||
* @return Created bitmap
|
||||
*/
|
||||
std::unique_ptr<gfx::Bitmap> CreateSimpleTile(uint16_t tile_id,
|
||||
const gfx::SnesPalette& palette);
|
||||
|
||||
private:
|
||||
gui::Canvas* canvas_;
|
||||
Rom* rom_;
|
||||
|
||||
// Simple tile creation helpers
|
||||
std::vector<uint8_t> CreateSolidTile(uint8_t color_index);
|
||||
std::vector<uint8_t> CreatePatternTile(uint8_t pattern_type, uint8_t color_index);
|
||||
|
||||
// Graphics debugging
|
||||
void LogGraphicsInfo(int sheet_index);
|
||||
void LogPaletteInfo(const gfx::SnesPalette& palette);
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EDITOR_DUNGEON_MANUAL_OBJECT_RENDERER_H
|
||||
Reference in New Issue
Block a user