feat: Add layer visibility controls and BG2 layer type selection in DungeonCanvasViewer
- Implemented controls for toggling visibility of background layers BG1 and BG2 in the DungeonCanvasViewer. - Added a dropdown for selecting the type of BG2 layer, allowing for different rendering effects (Normal, Translucent, Addition, Dark, Off). - Updated rendering logic to respect visibility settings and apply the selected alpha values for BG2 layer rendering. - Enhanced debug logging to provide detailed information about bitmap states and rendering processes for both background layers.
This commit is contained in:
@@ -93,6 +93,24 @@ void DungeonCanvasViewer::DrawDungeonCanvas(int room_id) {
|
|||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
gui::InputHexWord("Message ID", &room.message_id_);
|
gui::InputHexWord("Message ID", &room.message_id_);
|
||||||
|
|
||||||
|
// Layer visibility controls
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::Text("Layer Controls:");
|
||||||
|
ImGui::Checkbox("Show BG1", &bg1_visible_);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Checkbox("Show BG2", &bg2_visible_);
|
||||||
|
|
||||||
|
// BG2 layer type dropdown
|
||||||
|
const char* bg2_layer_types[] = {
|
||||||
|
"Normal (100%)", "Translucent (75%)", "Addition (50%)", "Dark (25%)", "Off (0%)"
|
||||||
|
};
|
||||||
|
const int bg2_alpha_values[] = {255, 191, 127, 64, 0};
|
||||||
|
|
||||||
|
if (ImGui::Combo("BG2 Layer Type", &bg2_layer_type_, bg2_layer_types,
|
||||||
|
sizeof(bg2_layer_types) / sizeof(bg2_layer_types[0]))) {
|
||||||
|
// BG2 layer type changed, no need to reload graphics
|
||||||
|
}
|
||||||
|
|
||||||
// Check if critical properties changed and trigger reload
|
// Check if critical properties changed and trigger reload
|
||||||
if (prev_blockset != room.blockset || prev_palette != room.palette ||
|
if (prev_blockset != room.blockset || prev_palette != room.palette ||
|
||||||
prev_layout != room.layout || prev_spriteset != room.spriteset) {
|
prev_layout != room.layout || prev_spriteset != room.spriteset) {
|
||||||
@@ -444,7 +462,8 @@ void DungeonCanvasViewer::RenderRoomBackgroundLayers(int room_id) {
|
|||||||
auto& bg1_bitmap = room.bg1_buffer().bitmap();
|
auto& bg1_bitmap = room.bg1_buffer().bitmap();
|
||||||
auto& bg2_bitmap = room.bg2_buffer().bitmap();
|
auto& bg2_bitmap = room.bg2_buffer().bitmap();
|
||||||
|
|
||||||
if (bg1_bitmap.is_active() && bg1_bitmap.width() > 0 && bg1_bitmap.height() > 0) {
|
// Draw BG1 layer if visible and active
|
||||||
|
if (bg1_visible_ && bg1_bitmap.is_active() && bg1_bitmap.width() > 0 && bg1_bitmap.height() > 0) {
|
||||||
if (!bg1_bitmap.texture()) {
|
if (!bg1_bitmap.texture()) {
|
||||||
// Queue texture creation for background layer 1 via Arena's deferred system
|
// Queue texture creation for background layer 1 via Arena's deferred system
|
||||||
gfx::Arena::Get().QueueTextureCommand(
|
gfx::Arena::Get().QueueTextureCommand(
|
||||||
@@ -456,11 +475,15 @@ void DungeonCanvasViewer::RenderRoomBackgroundLayers(int room_id) {
|
|||||||
|
|
||||||
// Only draw if texture was successfully created
|
// Only draw if texture was successfully created
|
||||||
if (bg1_bitmap.texture()) {
|
if (bg1_bitmap.texture()) {
|
||||||
|
printf("[RenderRoomBackgroundLayers] Drawing BG1 bitmap to canvas with texture %p\n", bg1_bitmap.texture());
|
||||||
canvas_.DrawBitmap(bg1_bitmap, 0, 0, 1.0f, 255);
|
canvas_.DrawBitmap(bg1_bitmap, 0, 0, 1.0f, 255);
|
||||||
|
} else {
|
||||||
|
printf("[RenderRoomBackgroundLayers] ERROR: BG1 bitmap has no texture!\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bg2_bitmap.is_active() && bg2_bitmap.width() > 0 && bg2_bitmap.height() > 0) {
|
// Draw BG2 layer if visible and active
|
||||||
|
if (bg2_visible_ && bg2_bitmap.is_active() && bg2_bitmap.width() > 0 && bg2_bitmap.height() > 0) {
|
||||||
if (!bg2_bitmap.texture()) {
|
if (!bg2_bitmap.texture()) {
|
||||||
// Queue texture creation for background layer 2 via Arena's deferred system
|
// Queue texture creation for background layer 2 via Arena's deferred system
|
||||||
gfx::Arena::Get().QueueTextureCommand(
|
gfx::Arena::Get().QueueTextureCommand(
|
||||||
@@ -472,18 +495,42 @@ void DungeonCanvasViewer::RenderRoomBackgroundLayers(int room_id) {
|
|||||||
|
|
||||||
// Only draw if texture was successfully created
|
// Only draw if texture was successfully created
|
||||||
if (bg2_bitmap.texture()) {
|
if (bg2_bitmap.texture()) {
|
||||||
canvas_.DrawBitmap(bg2_bitmap, 0, 0, 1.0f, 200);
|
// Use the selected BG2 layer type alpha value
|
||||||
|
const int bg2_alpha_values[] = {255, 191, 127, 64, 0};
|
||||||
|
int alpha_value = bg2_alpha_values[std::min(bg2_layer_type_, 4)];
|
||||||
|
printf("[RenderRoomBackgroundLayers] Drawing BG2 bitmap to canvas with texture %p, alpha=%d\n", bg2_bitmap.texture(), alpha_value);
|
||||||
|
canvas_.DrawBitmap(bg2_bitmap, 0, 0, 1.0f, alpha_value);
|
||||||
|
} else {
|
||||||
|
printf("[RenderRoomBackgroundLayers] ERROR: BG2 bitmap has no texture!\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DEBUG: Check if background buffers have content
|
// DEBUG: Check if background buffers have content
|
||||||
if (bg1_bitmap.is_active() && bg1_bitmap.width() > 0) {
|
if (bg1_bitmap.is_active() && bg1_bitmap.width() > 0) {
|
||||||
printf("[RenderRoomBackgroundLayers] BG1 bitmap: %dx%d, active=%d\n",
|
printf("[RenderRoomBackgroundLayers] BG1 bitmap: %dx%d, active=%d, visible=%d, texture=%p\n",
|
||||||
bg1_bitmap.width(), bg1_bitmap.height(), bg1_bitmap.is_active());
|
bg1_bitmap.width(), bg1_bitmap.height(), bg1_bitmap.is_active(), bg1_visible_, bg1_bitmap.texture());
|
||||||
|
|
||||||
|
// Check bitmap data content
|
||||||
|
auto& bg1_data = bg1_bitmap.mutable_data();
|
||||||
|
int non_zero_pixels = 0;
|
||||||
|
for (size_t i = 0; i < bg1_data.size(); i += 100) { // Sample every 100th pixel
|
||||||
|
if (bg1_data[i] != 0) non_zero_pixels++;
|
||||||
|
}
|
||||||
|
printf("[RenderRoomBackgroundLayers] BG1 bitmap data: %zu pixels, ~%d non-zero samples\n",
|
||||||
|
bg1_data.size(), non_zero_pixels);
|
||||||
}
|
}
|
||||||
if (bg2_bitmap.is_active() && bg2_bitmap.width() > 0) {
|
if (bg2_bitmap.is_active() && bg2_bitmap.width() > 0) {
|
||||||
printf("[RenderRoomBackgroundLayers] BG2 bitmap: %dx%d, active=%d\n",
|
printf("[RenderRoomBackgroundLayers] BG2 bitmap: %dx%d, active=%d, visible=%d, layer_type=%d, texture=%p\n",
|
||||||
bg2_bitmap.width(), bg2_bitmap.height(), bg2_bitmap.is_active());
|
bg2_bitmap.width(), bg2_bitmap.height(), bg2_bitmap.is_active(), bg2_visible_, bg2_layer_type_, bg2_bitmap.texture());
|
||||||
|
|
||||||
|
// Check bitmap data content
|
||||||
|
auto& bg2_data = bg2_bitmap.mutable_data();
|
||||||
|
int non_zero_pixels = 0;
|
||||||
|
for (size_t i = 0; i < bg2_data.size(); i += 100) { // Sample every 100th pixel
|
||||||
|
if (bg2_data[i] != 0) non_zero_pixels++;
|
||||||
|
}
|
||||||
|
printf("[RenderRoomBackgroundLayers] BG2 bitmap data: %zu pixels, ~%d non-zero samples\n",
|
||||||
|
bg2_data.size(), non_zero_pixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TEST: Draw a bright red rectangle to verify canvas drawing works
|
// TEST: Draw a bright red rectangle to verify canvas drawing works
|
||||||
@@ -493,6 +540,12 @@ void DungeonCanvasViewer::RenderRoomBackgroundLayers(int room_id) {
|
|||||||
ImVec2(canvas_pos.x + 50, canvas_pos.y + 50),
|
ImVec2(canvas_pos.x + 50, canvas_pos.y + 50),
|
||||||
ImVec2(canvas_pos.x + 150, canvas_pos.y + 150),
|
ImVec2(canvas_pos.x + 150, canvas_pos.y + 150),
|
||||||
IM_COL32(255, 0, 0, 255)); // Bright red
|
IM_COL32(255, 0, 0, 255)); // Bright red
|
||||||
|
|
||||||
|
// DEBUG: Show canvas and bitmap info
|
||||||
|
printf("[RenderRoomBackgroundLayers] Canvas pos: (%.1f, %.1f), Canvas size: (%.1f, %.1f)\n",
|
||||||
|
canvas_pos.x, canvas_pos.y, canvas_.canvas_size().x, canvas_.canvas_size().y);
|
||||||
|
printf("[RenderRoomBackgroundLayers] BG1 bitmap size: %dx%d, BG2 bitmap size: %dx%d\n",
|
||||||
|
bg1_bitmap.width(), bg1_bitmap.height(), bg2_bitmap.width(), bg2_bitmap.height());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace yaze::editor
|
} // namespace yaze::editor
|
||||||
|
|||||||
@@ -56,6 +56,16 @@ class DungeonCanvasViewer {
|
|||||||
void SetObjectInteractionEnabled(bool enabled) { object_interaction_enabled_ = enabled; }
|
void SetObjectInteractionEnabled(bool enabled) { object_interaction_enabled_ = enabled; }
|
||||||
bool IsObjectInteractionEnabled() const { return object_interaction_enabled_; }
|
bool IsObjectInteractionEnabled() const { return object_interaction_enabled_; }
|
||||||
|
|
||||||
|
// Layer visibility controls
|
||||||
|
void SetBG1Visible(bool visible) { bg1_visible_ = visible; }
|
||||||
|
void SetBG2Visible(bool visible) { bg2_visible_ = visible; }
|
||||||
|
bool IsBG1Visible() const { return bg1_visible_; }
|
||||||
|
bool IsBG2Visible() const { return bg2_visible_; }
|
||||||
|
|
||||||
|
// BG2 layer type controls
|
||||||
|
void SetBG2LayerType(int type) { bg2_layer_type_ = type; }
|
||||||
|
int GetBG2LayerType() const { return bg2_layer_type_; }
|
||||||
|
|
||||||
// Set the object to be placed
|
// Set the object to be placed
|
||||||
void SetPreviewObject(const zelda3::RoomObject& object) {
|
void SetPreviewObject(const zelda3::RoomObject& object) {
|
||||||
object_interaction_.SetPreviewObject(object, true);
|
object_interaction_.SetPreviewObject(object, true);
|
||||||
@@ -95,6 +105,11 @@ class DungeonCanvasViewer {
|
|||||||
// Object interaction state
|
// Object interaction state
|
||||||
bool object_interaction_enabled_ = true;
|
bool object_interaction_enabled_ = true;
|
||||||
|
|
||||||
|
// Layer visibility controls
|
||||||
|
bool bg1_visible_ = true;
|
||||||
|
bool bg2_visible_ = true;
|
||||||
|
int bg2_layer_type_ = 0; // 0=Normal, 1=Translucent, 2=Addition, etc.
|
||||||
|
|
||||||
// Palette data
|
// Palette data
|
||||||
uint64_t current_palette_group_id_ = 0;
|
uint64_t current_palette_group_id_ = 0;
|
||||||
uint64_t current_palette_id_ = 0;
|
uint64_t current_palette_id_ = 0;
|
||||||
|
|||||||
@@ -146,7 +146,14 @@ void BackgroundBuffer::DrawFloor(const std::vector<uint8_t>& rom_data,
|
|||||||
uint8_t floor_graphics) {
|
uint8_t floor_graphics) {
|
||||||
// Create bitmap ONCE at the start if it doesn't exist
|
// Create bitmap ONCE at the start if it doesn't exist
|
||||||
if (!bitmap_.is_active() || bitmap_.width() == 0) {
|
if (!bitmap_.is_active() || bitmap_.width() == 0) {
|
||||||
|
printf("[DrawFloor] Creating bitmap: %dx%d, active=%d, width=%d\n",
|
||||||
|
width_, height_, bitmap_.is_active(), bitmap_.width());
|
||||||
bitmap_.Create(width_, height_, 8, std::vector<uint8_t>(width_ * height_, 0));
|
bitmap_.Create(width_, height_, 8, std::vector<uint8_t>(width_ * height_, 0));
|
||||||
|
printf("[DrawFloor] After Create: active=%d, width=%d, height=%d\n",
|
||||||
|
bitmap_.is_active(), bitmap_.width(), bitmap_.height());
|
||||||
|
} else {
|
||||||
|
printf("[DrawFloor] Bitmap already exists: active=%d, width=%d, height=%d\n",
|
||||||
|
bitmap_.is_active(), bitmap_.width(), bitmap_.height());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto f = (uint8_t)(floor_graphics << 4);
|
auto f = (uint8_t)(floor_graphics << 4);
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ absl::Status ObjectDrawer::DrawObject(const RoomObject& object,
|
|||||||
|
|
||||||
// Select buffer based on layer
|
// Select buffer based on layer
|
||||||
auto& target_bg = (object.layer_ == RoomObject::LayerType::BG2) ? bg2 : bg1;
|
auto& target_bg = (object.layer_ == RoomObject::LayerType::BG2) ? bg2 : bg1;
|
||||||
|
printf("[DrawObject] Object ID=0x%02X using %s buffer (layer=%d)\n",
|
||||||
|
object.id_, (object.layer_ == RoomObject::LayerType::BG2) ? "BG2" : "BG1", object.layer_);
|
||||||
|
|
||||||
// Skip objects that don't have tiles loaded - check mutable object
|
// Skip objects that don't have tiles loaded - check mutable object
|
||||||
if (mutable_obj.tiles().empty()) {
|
if (mutable_obj.tiles().empty()) {
|
||||||
@@ -577,6 +579,8 @@ void ObjectDrawer::WriteTile16(gfx::BackgroundBuffer& bg, int tile_x, int tile_y
|
|||||||
|
|
||||||
// Draw directly to bitmap instead of tile buffer to avoid being overwritten
|
// Draw directly to bitmap instead of tile buffer to avoid being overwritten
|
||||||
auto& bitmap = bg.bitmap();
|
auto& bitmap = bg.bitmap();
|
||||||
|
printf("[WriteTile16] Bitmap status: active=%d, width=%d, height=%d, surface=%p\n",
|
||||||
|
bitmap.is_active(), bitmap.width(), bitmap.height(), bitmap.surface());
|
||||||
if (!bitmap.is_active() || bitmap.width() == 0) {
|
if (!bitmap.is_active() || bitmap.width() == 0) {
|
||||||
printf("[WriteTile16] Bitmap not ready: active=%d, width=%d\n", bitmap.is_active(), bitmap.width());
|
printf("[WriteTile16] Bitmap not ready: active=%d, width=%d\n", bitmap.is_active(), bitmap.width());
|
||||||
return; // Bitmap not ready
|
return; // Bitmap not ready
|
||||||
@@ -609,8 +613,12 @@ void ObjectDrawer::DrawTileToBitmap(gfx::Bitmap& bitmap, const gfx::TileInfo& ti
|
|||||||
// Draw an 8x8 tile directly to bitmap at pixel coordinates
|
// Draw an 8x8 tile directly to bitmap at pixel coordinates
|
||||||
if (!tiledata) return;
|
if (!tiledata) return;
|
||||||
|
|
||||||
printf("[DrawTileToBitmap] Drawing tile ID=0x%02X at (%d,%d) with palette=%d\n",
|
// DEBUG: Check if bitmap is valid
|
||||||
tile_info.id_, pixel_x, pixel_y, tile_info.palette_);
|
if (!bitmap.is_active() || bitmap.width() == 0 || bitmap.height() == 0) {
|
||||||
|
printf("[DrawTileToBitmap] ERROR: Invalid bitmap - active=%d, size=%dx%d\n",
|
||||||
|
bitmap.is_active(), bitmap.width(), bitmap.height());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate tile position in graphics sheet (128 pixels wide)
|
// Calculate tile position in graphics sheet (128 pixels wide)
|
||||||
int tile_sheet_x = (tile_info.id_ % 16) * 8; // 16 tiles per row
|
int tile_sheet_x = (tile_info.id_ % 16) * 8; // 16 tiles per row
|
||||||
@@ -621,6 +629,12 @@ void ObjectDrawer::DrawTileToBitmap(gfx::Bitmap& bitmap, const gfx::TileInfo& ti
|
|||||||
if (palette_id > 10) palette_id = palette_id % 11;
|
if (palette_id > 10) palette_id = palette_id % 11;
|
||||||
uint8_t palette_offset = palette_id * 8; // 3BPP: 8 colors per palette
|
uint8_t palette_offset = palette_id * 8; // 3BPP: 8 colors per palette
|
||||||
|
|
||||||
|
// Force a visible palette for debugging
|
||||||
|
if (palette_id == 0) {
|
||||||
|
palette_id = 1; // Use palette 1 instead of 0
|
||||||
|
palette_offset = palette_id * 8;
|
||||||
|
}
|
||||||
|
|
||||||
// Draw 8x8 pixels
|
// Draw 8x8 pixels
|
||||||
for (int py = 0; py < 8; py++) {
|
for (int py = 0; py < 8; py++) {
|
||||||
for (int px = 0; px < 8; px++) {
|
for (int px = 0; px < 8; px++) {
|
||||||
@@ -641,6 +655,12 @@ void ObjectDrawer::DrawTileToBitmap(gfx::Bitmap& bitmap, const gfx::TileInfo& ti
|
|||||||
int dest_index = dest_y * bitmap.width() + dest_x;
|
int dest_index = dest_y * bitmap.width() + dest_x;
|
||||||
if (dest_index >= 0 && dest_index < static_cast<int>(bitmap.mutable_data().size())) {
|
if (dest_index >= 0 && dest_index < static_cast<int>(bitmap.mutable_data().size())) {
|
||||||
bitmap.mutable_data()[dest_index] = final_color;
|
bitmap.mutable_data()[dest_index] = final_color;
|
||||||
|
|
||||||
|
// Debug first pixel of each tile
|
||||||
|
if (py == 0 && px == 0) {
|
||||||
|
printf("[DrawTileToBitmap] Tile ID=0x%02X at (%d,%d): palette=%d, pixel_index=%d, final_color=%d\n",
|
||||||
|
tile_info.id_, pixel_x, pixel_y, palette_id, pixel_index, final_color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -312,9 +312,9 @@ void Room::RenderRoomGraphics() {
|
|||||||
int palette_id = palette;
|
int palette_id = palette;
|
||||||
|
|
||||||
if (palette_id < 0 || palette_id >= num_palettes) {
|
if (palette_id < 0 || palette_id >= num_palettes) {
|
||||||
std::printf("5. WARNING: palette_id %d is out of bounds [0, %d), using palette 0\n",
|
std::printf("5. WARNING: palette_id %d is out of bounds [0, %d), using palette %d\n",
|
||||||
palette_id, num_palettes);
|
palette_id, num_palettes, palette_id % num_palettes);
|
||||||
palette_id = 0;
|
palette_id = palette_id % num_palettes; // Use modulo to wrap around instead of defaulting to 0
|
||||||
}
|
}
|
||||||
|
|
||||||
auto bg1_palette = dungeon_pal_group[palette_id];
|
auto bg1_palette = dungeon_pal_group[palette_id];
|
||||||
|
|||||||
Reference in New Issue
Block a user