diff --git a/src/app/editor/graphics/graphics_editor.cc b/src/app/editor/graphics/graphics_editor.cc index 6a9ce72e..0c18e0e9 100644 --- a/src/app/editor/graphics/graphics_editor.cc +++ b/src/app/editor/graphics/graphics_editor.cc @@ -104,54 +104,22 @@ absl::Status GraphicsEditor::Load() { LOG_INFO("GraphicsEditor", "Initializing textures for %d graphics sheets", kNumGfxSheets); - int sheets_initialized = 0; + int sheets_queued = 0; for (int i = 0; i < kNumGfxSheets; i++) { if (!sheets[i].is_active() || !sheets[i].surface()) { continue; // Skip inactive or surface-less sheets } - // Determine which palette group to use based on sheet index - gfx::SnesPalette sheet_palette; - - if (i < 113) { - // Overworld/Dungeon graphics - use dungeon main palette - auto palette_group = rom()->palette_group().dungeon_main; - if (palette_group.size() > 0) { - sheet_palette = palette_group[0]; - } - } else if (i < 128) { - // Sprite graphics - use sprite palettes - auto palette_group = rom()->palette_group().sprites_aux1; - if (palette_group.size() > 0) { - sheet_palette = palette_group[0]; - } - } else { - // Auxiliary graphics - use HUD/menu palettes - auto palette_group = rom()->palette_group().hud; - if (palette_group.size() > 0) { - sheet_palette = palette_group.palette(0); - } - } - - // CRITICAL: Apply palette BEFORE queueing texture creation - // The palette must be set on the surface before creating the texture - if (!sheet_palette.empty()) { - sheets[i].SetPalette(sheet_palette); - sheets_initialized++; - } else { - LOG_WARN("GraphicsEditor", "Sheet %d: Empty palette, skipping", i); - continue; - } - - // Queue texture creation if not already created + // Palettes are now applied during ROM loading in LoadAllGraphicsData() + // Just queue texture creation for sheets that don't have textures yet if (!sheets[i].texture()) { gfx::Arena::Get().QueueTextureCommand( gfx::Arena::TextureCommandType::CREATE, &sheets[i]); + sheets_queued++; } } - LOG_INFO("GraphicsEditor", "Initialized %d sheets with palettes, queued for texture creation", - sheets_initialized); + LOG_INFO("GraphicsEditor", "Queued texture creation for %d graphics sheets", sheets_queued); } return absl::OkStatus(); @@ -478,19 +446,16 @@ absl::Status GraphicsEditor::UpdateGfxTabView() { auto draw_tile_event = [&]() { current_sheet_canvas_.DrawTileOnBitmap(tile_size_, ¤t_bitmap, current_color_); - // Use batch operations for texture updates - // current_bitmap.QueueTextureUpdate(core::Renderer::Get().renderer()); - gfx::Arena::Get().QueueTextureCommand( - gfx::Arena::TextureCommandType::UPDATE, ¤t_bitmap); + // Notify Arena that this sheet has been modified for cross-editor synchronization + gfx::Arena::Get().NotifySheetModified(sheet_id); }; current_sheet_canvas_.UpdateColorPainter( nullptr, gfx::Arena::Get().mutable_gfx_sheets()->at(sheet_id), current_color_, draw_tile_event, tile_size_, current_scale_); - gfx::Arena::Get().QueueTextureCommand( - gfx::Arena::TextureCommandType::UPDATE, - &gfx::Arena::Get().mutable_gfx_sheets()->at(sheet_id)); + // Notify Arena that this sheet has been modified for cross-editor synchronization + gfx::Arena::Get().NotifySheetModified(sheet_id); ImGui::EndChild(); ImGui::EndTabItem(); @@ -580,10 +545,8 @@ absl::Status GraphicsEditor::UpdatePaletteColumn() { auto& sheet = gfx::Arena::Get().mutable_gfx_sheets()->data()[i]; if (sheet.is_active() && sheet.surface()) { sheet.SetPaletteWithTransparent(palette, edit_palette_sub_index_); - if (sheet.texture()) { - gfx::Arena::Get().QueueTextureCommand( - gfx::Arena::TextureCommandType::UPDATE, &sheet); - } + // Notify Arena that this sheet has been modified + gfx::Arena::Get().NotifySheetModified(i); } } } @@ -605,13 +568,8 @@ absl::Status GraphicsEditor::UpdatePaletteColumn() { auto& current = gfx::Arena::Get().mutable_gfx_sheets()->data()[current_sheet_]; if (current.is_active() && current.surface()) { current.SetPaletteWithTransparent(palette, edit_palette_sub_index_); - if (current.texture()) { - gfx::Arena::Get().QueueTextureCommand( - gfx::Arena::TextureCommandType::UPDATE, ¤t); - } else { - gfx::Arena::Get().QueueTextureCommand( - gfx::Arena::TextureCommandType::CREATE, ¤t); - } + // Notify Arena that this sheet has been modified + gfx::Arena::Get().NotifySheetModified(current_sheet_); } refresh_graphics_ = false; } diff --git a/src/app/editor/message/message_editor.cc b/src/app/editor/message/message_editor.cc index bbc91209..242d679a 100644 --- a/src/app/editor/message/message_editor.cc +++ b/src/app/editor/message/message_editor.cc @@ -19,6 +19,7 @@ #include "imgui.h" #include "imgui/misc/cpp/imgui_stdlib.h" #include "util/hex.h" +#include "util/log.h" namespace yaze { namespace editor { @@ -124,7 +125,7 @@ void MessageEditor::Initialize() { gfx::Arena::Get().QueueTextureCommand( gfx::Arena::TextureCommandType::CREATE, &font_gfx_bitmap_); - printf("[MessageEditor] Font bitmap created and texture queued\n"); + LOG_INFO("MessageEditor", "Font bitmap created and texture queued"); *current_font_gfx16_bitmap_.mutable_palette() = font_preview_colors_; auto load_font = LoadFontGraphics(*rom()); @@ -372,13 +373,32 @@ void MessageEditor::DrawDictionary() { } void MessageEditor::DrawMessagePreview() { + // Render the message to the preview bitmap message_preview_.DrawMessagePreview(current_message_); + + // Validate preview data before updating + if (message_preview_.current_preview_data_.empty()) { + LOG_WARN("MessageEditor", "Preview data is empty, skipping bitmap update"); + return; + } + if (current_font_gfx16_bitmap_.is_active()) { - current_font_gfx16_bitmap_.mutable_data() = - message_preview_.current_preview_data_; - // Queue texture update via Arena's deferred system + // CRITICAL: Use set_data() to properly update both data_ AND surface_ + // mutable_data() returns a reference but doesn't update the surface! + current_font_gfx16_bitmap_.set_data(message_preview_.current_preview_data_); + + // Validate surface was updated + if (!current_font_gfx16_bitmap_.surface()) { + LOG_ERROR("MessageEditor", "Bitmap surface is null after set_data()"); + return; + } + + // Queue texture update so changes are visible immediately gfx::Arena::Get().QueueTextureCommand( gfx::Arena::TextureCommandType::UPDATE, ¤t_font_gfx16_bitmap_); + + LOG_DEBUG("MessageEditor", "Updated message preview bitmap (size: %zu) and queued texture update", + message_preview_.current_preview_data_.size()); } else { // Create bitmap and queue texture creation current_font_gfx16_bitmap_.Create(kCurrentMessageWidth, kCurrentMessageHeight, @@ -386,6 +406,9 @@ void MessageEditor::DrawMessagePreview() { current_font_gfx16_bitmap_.SetPalette(font_preview_colors_); gfx::Arena::Get().QueueTextureCommand( gfx::Arena::TextureCommandType::CREATE, ¤t_font_gfx16_bitmap_); + + LOG_INFO("MessageEditor", "Created message preview bitmap (%dx%d) and queued texture creation", + kCurrentMessageWidth, kCurrentMessageHeight); } } diff --git a/src/app/gfx/arena.cc b/src/app/gfx/arena.cc index 3da1d25f..6e988e2b 100644 --- a/src/app/gfx/arena.cc +++ b/src/app/gfx/arena.cc @@ -4,6 +4,7 @@ #include #include "app/gfx/backend/irenderer.h" +#include "util/log.h" #include "util/sdl_deleter.h" namespace yaze { @@ -79,7 +80,7 @@ void Arena::ProcessTextureQueue(IRenderer* renderer) { should_remove = false; // Retry next frame } } catch (...) { - printf("[Arena] ERROR: Exception during texture creation\n"); + LOG_ERROR("Arena", "Exception during texture creation"); should_remove = true; // Remove bad command } } @@ -94,7 +95,7 @@ void Arena::ProcessTextureQueue(IRenderer* renderer) { active_renderer->UpdateTexture(command.bitmap->texture(), *command.bitmap); processed++; } catch (...) { - printf("[Arena] ERROR: Exception during texture update\n"); + LOG_ERROR("Arena", "Exception during texture update"); } } break; @@ -106,7 +107,7 @@ void Arena::ProcessTextureQueue(IRenderer* renderer) { command.bitmap->set_texture(nullptr); processed++; } catch (...) { - printf("[Arena] ERROR: Exception during texture destruction\n"); + LOG_ERROR("Arena", "Exception during texture destruction"); } } break; @@ -179,6 +180,29 @@ void Arena::Shutdown() { texture_command_queue_.clear(); } +void Arena::NotifySheetModified(int sheet_index) { + if (sheet_index < 0 || sheet_index >= 223) { + LOG_WARN("Arena", "Invalid sheet index %d, ignoring notification", sheet_index); + return; + } + + auto& sheet = gfx_sheets_[sheet_index]; + if (!sheet.is_active() || !sheet.surface()) { + LOG_DEBUG("Arena", "Sheet %d not active or no surface, skipping notification", sheet_index); + return; + } + + // Queue texture update so changes are visible in all editors + if (sheet.texture()) { + QueueTextureCommand(TextureCommandType::UPDATE, &sheet); + LOG_DEBUG("Arena", "Queued texture update for modified sheet %d", sheet_index); + } else { + // Create texture if it doesn't exist + QueueTextureCommand(TextureCommandType::CREATE, &sheet); + LOG_DEBUG("Arena", "Queued texture creation for modified sheet %d", sheet_index); + } +} + } // namespace gfx } // namespace yaze \ No newline at end of file diff --git a/src/app/gfx/arena.h b/src/app/gfx/arena.h index bdc2901a..3124ff54 100644 --- a/src/app/gfx/arena.h +++ b/src/app/gfx/arena.h @@ -96,6 +96,13 @@ class Arena { * @return Pointer to mutable array of 223 Bitmap objects */ auto mutable_gfx_sheets() { return &gfx_sheets_; } + + /** + * @brief Notify Arena that a graphics sheet has been modified + * @param sheet_index Index of the modified sheet (0-222) + * @details This ensures textures are updated across all editors + */ + void NotifySheetModified(int sheet_index); // Background buffer access for SNES layer rendering /** diff --git a/src/app/rom.cc b/src/app/rom.cc index 656cec26..ab7f891e 100644 --- a/src/app/rom.cc +++ b/src/app/rom.cc @@ -206,6 +206,36 @@ absl::StatusOr> LoadAllGraphicsData( graphics_sheets[i].Create(gfx::kTilesheetWidth, gfx::kTilesheetHeight, gfx::kTilesheetDepth, converted_sheet); + // Apply default palette based on sheet index to prevent white sheets + // This ensures graphics are visible immediately after loading + if (!rom.palette_group().empty()) { + gfx::SnesPalette default_palette; + + if (i < 113) { + // Overworld/Dungeon graphics - use dungeon main palette + auto palette_group = rom.palette_group().dungeon_main; + if (palette_group.size() > 0) { + default_palette = palette_group[0]; + } + } else if (i < 128) { + // Sprite graphics - use sprite palettes + auto palette_group = rom.palette_group().sprites_aux1; + if (palette_group.size() > 0) { + default_palette = palette_group[0]; + } + } else { + // Auxiliary graphics - use HUD/menu palettes + auto palette_group = rom.palette_group().hud; + if (palette_group.size() > 0) { + default_palette = palette_group.palette(0); + } + } + + // Apply palette if we have one + if (!default_palette.empty()) { + graphics_sheets[i].SetPalette(default_palette); + } + } for (int j = 0; j < graphics_sheets[i].size(); ++j) { rom.mutable_graphics_buffer()->push_back(graphics_sheets[i].at(j));