epic: refactor SDL2_Renderer usage to IRenderer and queued texture rendering
- Updated the testing guide to clarify the testing framework's organization and execution methods, improving user understanding. - Refactored CMakeLists to include new platform-specific files, ensuring proper integration of the rendering backend. - Modified main application files to utilize the new IRenderer interface, enhancing flexibility in rendering operations. - Implemented deferred texture management in various components, allowing for more efficient graphics handling and improved performance. - Introduced new methods for texture creation and updates, streamlining the rendering process across the application. - Enhanced logging and error handling in the rendering pipeline to facilitate better debugging and diagnostics.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
#include "absl/strings/match.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/time/clock.h"
|
||||
#include "app/core/platform/asset_loader.h"
|
||||
#include "app/platform/asset_loader.h"
|
||||
#include "app/editor/agent/agent_chat_widget.h"
|
||||
#include "app/editor/agent/agent_collaboration_coordinator.h"
|
||||
#include "app/editor/system/proposal_drawer.h"
|
||||
@@ -638,7 +638,7 @@ void AgentEditor::DrawPromptEditorPanel() {
|
||||
// Load prompt file if not initialized
|
||||
if (!prompt_editor_initialized_ && prompt_editor_) {
|
||||
std::string asset_path = "agent/" + active_prompt_file_;
|
||||
auto content_result = core::AssetLoader::LoadTextFile(asset_path);
|
||||
auto content_result = AssetLoader::LoadTextFile(asset_path);
|
||||
|
||||
if (content_result.ok()) {
|
||||
prompt_editor_->SetText(*content_result);
|
||||
@@ -923,7 +923,7 @@ void AgentEditor::DrawCommonTilesEditor() {
|
||||
|
||||
// Load/Save buttons
|
||||
if (ImGui::Button(ICON_MD_FOLDER_OPEN " Load", ImVec2(100, 0))) {
|
||||
auto content = core::AssetLoader::LoadTextFile("agent/common_tiles.txt");
|
||||
auto content = AssetLoader::LoadTextFile("agent/common_tiles.txt");
|
||||
if (content.ok()) {
|
||||
common_tiles_editor_->SetText(*content);
|
||||
common_tiles_initialized_ = true;
|
||||
@@ -954,7 +954,7 @@ void AgentEditor::DrawCommonTilesEditor() {
|
||||
|
||||
// Load if not initialized
|
||||
if (!common_tiles_initialized_ && common_tiles_editor_) {
|
||||
auto content = core::AssetLoader::LoadTextFile("agent/common_tiles.txt");
|
||||
auto content = AssetLoader::LoadTextFile("agent/common_tiles.txt");
|
||||
if (content.ok()) {
|
||||
common_tiles_editor_->SetText(*content);
|
||||
} else {
|
||||
@@ -1010,7 +1010,7 @@ void AgentEditor::DrawNewPromptCreator() {
|
||||
ImGui::Text("Start from template:");
|
||||
|
||||
if (ImGui::Button(ICON_MD_FILE_COPY " v1 (Basic)", ImVec2(-1, 0))) {
|
||||
auto content = core::AssetLoader::LoadTextFile("agent/system_prompt.txt");
|
||||
auto content = AssetLoader::LoadTextFile("agent/system_prompt.txt");
|
||||
if (content.ok() && prompt_editor_) {
|
||||
prompt_editor_->SetText(*content);
|
||||
if (toast_manager_) {
|
||||
@@ -1021,7 +1021,7 @@ void AgentEditor::DrawNewPromptCreator() {
|
||||
|
||||
if (ImGui::Button(ICON_MD_FILE_COPY " v2 (Enhanced)", ImVec2(-1, 0))) {
|
||||
auto content =
|
||||
core::AssetLoader::LoadTextFile("agent/system_prompt_v2.txt");
|
||||
AssetLoader::LoadTextFile("agent/system_prompt_v2.txt");
|
||||
if (content.ok() && prompt_editor_) {
|
||||
prompt_editor_->SetText(*content);
|
||||
if (toast_manager_) {
|
||||
@@ -1032,7 +1032,7 @@ void AgentEditor::DrawNewPromptCreator() {
|
||||
|
||||
if (ImGui::Button(ICON_MD_FILE_COPY " v3 (Proactive)", ImVec2(-1, 0))) {
|
||||
auto content =
|
||||
core::AssetLoader::LoadTextFile("agent/system_prompt_v3.txt");
|
||||
AssetLoader::LoadTextFile("agent/system_prompt_v3.txt");
|
||||
if (content.ok() && prompt_editor_) {
|
||||
prompt_editor_->SetText(*content);
|
||||
if (toast_manager_) {
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
#include "dungeon_canvas_viewer.h"
|
||||
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "app/core/window.h"
|
||||
#include "app/gfx/arena.h"
|
||||
#include "app/gfx/snes_palette.h"
|
||||
#include "app/gui/canvas.h"
|
||||
#include "app/gui/input.h"
|
||||
#include "app/rom.h"
|
||||
#include "util/log.h"
|
||||
#include "app/zelda3/dungeon/object_drawer.h"
|
||||
#include "app/zelda3/dungeon/object_renderer.h"
|
||||
#include "app/zelda3/dungeon/room.h"
|
||||
#include "app/zelda3/sprite/sprite.h"
|
||||
@@ -148,6 +144,7 @@ void DungeonCanvasViewer::DrawDungeonCanvas(int room_id) {
|
||||
object_interaction_.HandleCanvasMouseInput();
|
||||
object_interaction_.CheckForObjectSelection();
|
||||
object_interaction_.DrawSelectBox();
|
||||
object_interaction_.DrawSelectionHighlights(); // Draw selection highlights on top
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,7 +192,9 @@ void DungeonCanvasViewer::RenderObjectInCanvas(const zelda3::RoomObject &object,
|
||||
// Ensure the bitmap is valid and has content
|
||||
if (object_bitmap.width() > 0 && object_bitmap.height() > 0) {
|
||||
object_bitmap.SetPalette(palette);
|
||||
core::Renderer::Get().RenderBitmap(&object_bitmap);
|
||||
// Queue texture creation for the object bitmap via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, &object_bitmap);
|
||||
canvas_.DrawBitmap(object_bitmap, canvas_x, canvas_y, 1.0f, 255);
|
||||
return;
|
||||
}
|
||||
@@ -656,7 +655,10 @@ absl::Status DungeonCanvasViewer::UpdateRoomBackgroundLayers(int room_id) {
|
||||
if (current_palette_id_ < current_palette_group_.size()) {
|
||||
gfx::Arena::Get().gfx_sheets()[block].SetPaletteWithTransparent(
|
||||
current_palette_group_[current_palette_id_], 0);
|
||||
core::Renderer::Get().UpdateBitmap(&gfx::Arena::Get().gfx_sheets()[block]);
|
||||
// Queue texture update via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE,
|
||||
&gfx::Arena::Get().gfx_sheets()[block]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -671,7 +673,10 @@ absl::Status DungeonCanvasViewer::UpdateRoomBackgroundLayers(int room_id) {
|
||||
if (block >= 0 && block < gfx::Arena::Get().gfx_sheets().size()) {
|
||||
gfx::Arena::Get().gfx_sheets()[block].SetPaletteWithTransparent(
|
||||
sprites_aux1_pal_group[current_palette_id_], 0);
|
||||
core::Renderer::Get().UpdateBitmap(&gfx::Arena::Get().gfx_sheets()[block]);
|
||||
// Queue texture update via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE,
|
||||
&gfx::Arena::Get().gfx_sheets()[block]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -691,14 +696,9 @@ void DungeonCanvasViewer::RenderRoomBackgroundLayers(int room_id) {
|
||||
|
||||
if (bg1_bitmap.is_active() && bg1_bitmap.width() > 0 && bg1_bitmap.height() > 0) {
|
||||
if (!bg1_bitmap.texture()) {
|
||||
core::Renderer::Get().RenderBitmap(&bg1_bitmap);
|
||||
}
|
||||
|
||||
// DEBUG: Check SDL texture format
|
||||
Uint32 format;
|
||||
int access, w, h;
|
||||
if (SDL_QueryTexture(bg1_bitmap.texture(), &format, &access, &w, &h) == 0) {
|
||||
const char* format_name_cstr = SDL_GetPixelFormatName(format);
|
||||
// Queue texture creation for background layer 1 via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, &bg1_bitmap);
|
||||
}
|
||||
|
||||
canvas_.DrawBitmap(bg1_bitmap, 0, 0, 1.0f, 255);
|
||||
@@ -706,7 +706,9 @@ void DungeonCanvasViewer::RenderRoomBackgroundLayers(int room_id) {
|
||||
|
||||
if (bg2_bitmap.is_active() && bg2_bitmap.width() > 0 && bg2_bitmap.height() > 0) {
|
||||
if (!bg2_bitmap.texture()) {
|
||||
core::Renderer::Get().RenderBitmap(&bg2_bitmap);
|
||||
// Queue texture creation for background layer 2 via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, &bg2_bitmap);
|
||||
}
|
||||
canvas_.DrawBitmap(bg2_bitmap, 0, 0, 1.0f, 200);
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ class DungeonCanvasViewer {
|
||||
int current_active_room_tab_ = 0;
|
||||
|
||||
// Object interaction state
|
||||
bool object_interaction_enabled_ = false;
|
||||
bool object_interaction_enabled_ = true;
|
||||
|
||||
// Palette data
|
||||
uint64_t current_palette_group_id_ = 0;
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
|
||||
namespace yaze::editor {
|
||||
|
||||
using core::Renderer;
|
||||
|
||||
using ImGui::BeginTabBar;
|
||||
using ImGui::BeginTabItem;
|
||||
using ImGui::BeginTable;
|
||||
@@ -185,11 +183,15 @@ absl::Status DungeonEditor::Save() {
|
||||
}
|
||||
|
||||
absl::Status DungeonEditor::RefreshGraphics() {
|
||||
// Update graphics sheet textures via Arena's deferred texture queue
|
||||
std::for_each_n(
|
||||
rooms_[current_room_id_].blocks().begin(), 8, [this](int block) {
|
||||
gfx::Arena::Get().gfx_sheets()[block].SetPaletteWithTransparent(
|
||||
current_palette_group_[current_palette_id_], 0);
|
||||
Renderer::Get().UpdateBitmap(&gfx::Arena::Get().gfx_sheets()[block]);
|
||||
// Queue texture update for the modified graphics sheet
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE,
|
||||
&gfx::Arena::Get().gfx_sheets()[block]);
|
||||
});
|
||||
|
||||
auto sprites_aux1_pal_group = rom()->palette_group().sprites_aux1;
|
||||
@@ -198,7 +200,10 @@ absl::Status DungeonEditor::RefreshGraphics() {
|
||||
[this, &sprites_aux1_pal_group](int block) {
|
||||
gfx::Arena::Get().gfx_sheets()[block].SetPaletteWithTransparent(
|
||||
sprites_aux1_pal_group[current_palette_id_], 0);
|
||||
Renderer::Get().UpdateBitmap(&gfx::Arena::Get().gfx_sheets()[block]);
|
||||
// Queue texture update for the modified graphics sheet
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE,
|
||||
&gfx::Arena::Get().gfx_sheets()[block]);
|
||||
});
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
@@ -15,7 +15,9 @@ namespace yaze::editor {
|
||||
|
||||
// No table layout needed - all cards are independent
|
||||
|
||||
void DungeonEditorV2::Initialize() {
|
||||
void DungeonEditorV2::Initialize(gfx::IRenderer* renderer, Rom* rom) {
|
||||
renderer_ = renderer;
|
||||
rom_ = rom;
|
||||
// Don't initialize emulator preview yet - ROM might not be loaded
|
||||
// Will be initialized in Load() instead
|
||||
|
||||
@@ -24,6 +26,8 @@ void DungeonEditorV2::Initialize() {
|
||||
room_window_class_.DockingAllowUnclassed = false; // Room windows dock together
|
||||
}
|
||||
|
||||
void DungeonEditorV2::Initialize() {}
|
||||
|
||||
absl::Status DungeonEditorV2::Load() {
|
||||
if (!rom_ || !rom_->is_loaded()) {
|
||||
return absl::FailedPreconditionError("ROM not loaded");
|
||||
@@ -55,13 +59,13 @@ absl::Status DungeonEditorV2::Load() {
|
||||
object_selector_.set_rooms(&rooms_);
|
||||
|
||||
// NOW initialize emulator preview with loaded ROM
|
||||
object_emulator_preview_.Initialize(rom_);
|
||||
object_emulator_preview_.Initialize(renderer_, rom_);
|
||||
|
||||
// Initialize palette editor with loaded ROM
|
||||
palette_editor_.Initialize(rom_);
|
||||
|
||||
// Initialize unified object editor card
|
||||
object_editor_card_ = std::make_unique<ObjectEditorCard>(rom_, &canvas_viewer_);
|
||||
object_editor_card_ = std::make_unique<ObjectEditorCard>(renderer_, rom_, &canvas_viewer_);
|
||||
|
||||
// Wire palette changes to trigger room re-renders
|
||||
palette_editor_.SetOnPaletteChanged([this](int /*palette_id*/) {
|
||||
@@ -97,7 +101,8 @@ absl::Status DungeonEditorV2::Update() {
|
||||
"This parent window can be minimized or closed.");
|
||||
|
||||
// Render all independent cards (these create their own top-level windows)
|
||||
object_emulator_preview_.Render();
|
||||
// NOTE: Emulator preview is now integrated into ObjectEditorCard
|
||||
// object_emulator_preview_.Render(); // Removed - causing performance issues
|
||||
DrawLayout();
|
||||
|
||||
return absl::OkStatus();
|
||||
@@ -148,11 +153,7 @@ void DungeonEditorV2::DrawToolset() {
|
||||
|
||||
toolbar.AddSeparator();
|
||||
|
||||
if (toolbar.AddToggle(ICON_MD_CATEGORY, &show_object_selector_, "Toggle Object Selector (Legacy)")) {
|
||||
// Toggled
|
||||
}
|
||||
|
||||
if (toolbar.AddToggle(ICON_MD_CONSTRUCTION, &show_object_editor_, "Toggle Object Editor (Unified)")) {
|
||||
if (toolbar.AddToggle(ICON_MD_CONSTRUCTION, &show_object_editor_, "Toggle Object Editor")) {
|
||||
// Toggled
|
||||
}
|
||||
|
||||
@@ -186,18 +187,7 @@ void DungeonEditorV2::DrawLayout() {
|
||||
DrawRoomGraphicsCard();
|
||||
}
|
||||
|
||||
// 4. Legacy Object Selector Card (independent, dockable)
|
||||
if (show_object_selector_) {
|
||||
gui::EditorCard object_card(
|
||||
MakeCardTitle("Object Selector").c_str(),
|
||||
ICON_MD_CATEGORY, &show_object_selector_);
|
||||
if (object_card.Begin()) {
|
||||
object_selector_.Draw();
|
||||
}
|
||||
object_card.End();
|
||||
}
|
||||
|
||||
// 4b. Unified Object Editor Card (new, combines selector + preview + interaction)
|
||||
// 4. Unified Object Editor Card
|
||||
if (show_object_editor_ && object_editor_card_) {
|
||||
object_editor_card_->Draw(&show_object_editor_);
|
||||
}
|
||||
@@ -234,11 +224,16 @@ void DungeonEditorV2::DrawLayout() {
|
||||
room_cards_[room_id] = std::make_shared<gui::EditorCard>(
|
||||
card_name_str.c_str(), ICON_MD_GRID_ON, &open);
|
||||
room_cards_[room_id]->SetDefaultSize(700, 600);
|
||||
|
||||
// Set default position for first room to be docked with main window
|
||||
if (active_rooms_.Size == 1) {
|
||||
room_cards_[room_id]->SetPosition(gui::EditorCard::Position::Floating);
|
||||
}
|
||||
}
|
||||
|
||||
auto& room_card = room_cards_[room_id];
|
||||
|
||||
// Use docking class to make room cards dock together
|
||||
// CRITICAL: Use docking class BEFORE Begin() to make rooms tab together
|
||||
ImGui::SetNextWindowClass(&room_window_class_);
|
||||
|
||||
if (room_card->Begin(&open)) {
|
||||
@@ -500,15 +495,15 @@ void DungeonEditorV2::DrawRoomMatrixCard() {
|
||||
MakeCardTitle("Room Matrix").c_str(),
|
||||
ICON_MD_GRID_VIEW, &show_room_matrix_);
|
||||
|
||||
matrix_card.SetDefaultSize(520, 620);
|
||||
matrix_card.SetDefaultSize(440, 520);
|
||||
|
||||
if (matrix_card.Begin()) {
|
||||
// 16 wide x 19 tall = 304 cells (295 rooms + 9 empty)
|
||||
// 16 wide x 19 tall = 304 cells (296 rooms + 8 empty)
|
||||
constexpr int kRoomsPerRow = 16;
|
||||
constexpr int kRoomsPerCol = 19;
|
||||
constexpr int kTotalRooms = 0x128; // 296 rooms (0x00-0x127)
|
||||
constexpr float kRoomCellSize = 28.0f; // Compact cells
|
||||
constexpr float kCellSpacing = 2.0f;
|
||||
constexpr float kRoomCellSize = 24.0f; // Smaller cells like ZScream
|
||||
constexpr float kCellSpacing = 1.0f; // Tighter spacing
|
||||
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
ImVec2 canvas_pos = ImGui::GetCursorScreenPos();
|
||||
@@ -527,30 +522,34 @@ void DungeonEditorV2::DrawRoomMatrixCard() {
|
||||
cell_min.y + kRoomCellSize);
|
||||
|
||||
if (is_valid_room) {
|
||||
// ALWAYS use palette-based color (lazy load if needed)
|
||||
ImU32 bg_color = IM_COL32(60, 60, 70, 255); // Fallback
|
||||
// Use simple deterministic color based on room ID (no loading needed)
|
||||
ImU32 bg_color;
|
||||
|
||||
// Try to get palette color
|
||||
uint8_t palette = 0;
|
||||
if (room_id < static_cast<int>(rooms_.size())) {
|
||||
// Lazy load room if needed to get palette
|
||||
if (!rooms_[room_id].IsLoaded()) {
|
||||
auto status = room_loader_.LoadRoom(room_id, rooms_[room_id]);
|
||||
if (status.ok()) {
|
||||
palette = rooms_[room_id].palette;
|
||||
}
|
||||
} else {
|
||||
palette = rooms_[room_id].palette;
|
||||
}
|
||||
|
||||
// Create a color variation based on palette ID
|
||||
float r = 0.3f + (palette % 4) * 0.15f;
|
||||
float g = 0.3f + ((palette / 4) % 4) * 0.15f;
|
||||
float b = 0.4f + ((palette / 16) % 2) * 0.2f;
|
||||
bg_color = IM_COL32(
|
||||
static_cast<int>(r * 255),
|
||||
static_cast<int>(g * 255),
|
||||
static_cast<int>(b * 255), 255);
|
||||
// Generate color from room ID - much faster than loading
|
||||
int hue = (room_id * 37) % 360; // Distribute colors across spectrum
|
||||
int saturation = 40 + (room_id % 3) * 15;
|
||||
int brightness = 50 + (room_id % 5) * 10;
|
||||
|
||||
// Convert HSV to RGB
|
||||
float h = hue / 60.0f;
|
||||
float s = saturation / 100.0f;
|
||||
float v = brightness / 100.0f;
|
||||
|
||||
int i = static_cast<int>(h);
|
||||
float f = h - i;
|
||||
int p = static_cast<int>(v * (1 - s) * 255);
|
||||
int q = static_cast<int>(v * (1 - s * f) * 255);
|
||||
int t = static_cast<int>(v * (1 - s * (1 - f)) * 255);
|
||||
int val = static_cast<int>(v * 255);
|
||||
|
||||
switch (i % 6) {
|
||||
case 0: bg_color = IM_COL32(val, t, p, 255); break;
|
||||
case 1: bg_color = IM_COL32(q, val, p, 255); break;
|
||||
case 2: bg_color = IM_COL32(p, val, t, 255); break;
|
||||
case 3: bg_color = IM_COL32(p, q, val, 255); break;
|
||||
case 4: bg_color = IM_COL32(t, p, val, 255); break;
|
||||
case 5: bg_color = IM_COL32(val, p, q, 255); break;
|
||||
default: bg_color = IM_COL32(60, 60, 70, 255); break;
|
||||
}
|
||||
|
||||
// Check if room is currently selected
|
||||
@@ -604,7 +603,7 @@ void DungeonEditorV2::DrawRoomMatrixCard() {
|
||||
OnRoomSelected(room_id);
|
||||
}
|
||||
|
||||
// Hover tooltip with room name
|
||||
// Hover tooltip with room name and status
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
if (room_id < static_cast<int>(std::size(zelda3::kRoomNames))) {
|
||||
@@ -612,9 +611,8 @@ void DungeonEditorV2::DrawRoomMatrixCard() {
|
||||
} else {
|
||||
ImGui::Text("Room %03X", room_id);
|
||||
}
|
||||
ImGui::Text("Palette: %02X",
|
||||
room_id < static_cast<int>(rooms_.size()) ?
|
||||
rooms_[room_id].palette : 0);
|
||||
ImGui::Text("Status: %s", is_open ? "Open" : is_current ? "Current" : "Closed");
|
||||
ImGui::Text("Click to %s", is_open ? "focus" : "open");
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -51,8 +51,9 @@ class DungeonEditorV2 : public Editor {
|
||||
}
|
||||
|
||||
// Editor interface
|
||||
void Initialize(gfx::IRenderer* renderer, Rom* rom);
|
||||
void Initialize() override;
|
||||
absl::Status Load() override;
|
||||
absl::Status Load();
|
||||
absl::Status Update() override;
|
||||
absl::Status Undo() override { return absl::UnimplementedError("Undo"); }
|
||||
absl::Status Redo() override { return absl::UnimplementedError("Redo"); }
|
||||
@@ -69,7 +70,7 @@ class DungeonEditorV2 : public Editor {
|
||||
room_selector_.set_rom(rom);
|
||||
canvas_viewer_.SetRom(rom);
|
||||
object_selector_.SetRom(rom);
|
||||
object_emulator_preview_.Initialize(rom);
|
||||
object_emulator_preview_.Initialize(renderer_, rom);
|
||||
}
|
||||
Rom* rom() const { return rom_; }
|
||||
|
||||
@@ -86,6 +87,7 @@ class DungeonEditorV2 : public Editor {
|
||||
}
|
||||
|
||||
private:
|
||||
gfx::IRenderer* renderer_ = nullptr;
|
||||
// Simple UI layout
|
||||
void DrawLayout();
|
||||
void DrawRoomTab(int room_id);
|
||||
@@ -117,8 +119,7 @@ class DungeonEditorV2 : public Editor {
|
||||
bool show_room_matrix_ = false;
|
||||
bool show_entrances_list_ = false;
|
||||
bool show_room_graphics_ = false; // Room graphics card
|
||||
bool show_object_selector_ = true; // Legacy object selector
|
||||
bool show_object_editor_ = true; // New unified object editor card
|
||||
bool show_object_editor_ = true; // Unified object editor card
|
||||
bool show_palette_editor_ = true;
|
||||
|
||||
// Palette management
|
||||
|
||||
@@ -150,25 +150,59 @@ void DungeonObjectInteraction::SelectObjectsInRect() {
|
||||
selected_object_indices_.push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonObjectInteraction::DrawSelectionHighlights() {
|
||||
if (!rooms_ || current_room_id_ < 0 || current_room_id_ >= 296) return;
|
||||
|
||||
// Highlight selected objects
|
||||
if (!selected_object_indices_.empty()) {
|
||||
for (size_t index : selected_object_indices_) {
|
||||
if (index < objects.size()) {
|
||||
const auto& object = objects[index];
|
||||
auto [canvas_x, canvas_y] =
|
||||
RoomToCanvasCoordinates(object.x_, object.y_);
|
||||
|
||||
// Draw selection highlight
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
ImVec2 canvas_pos = canvas_->zero_point();
|
||||
ImVec2 obj_start(canvas_pos.x + canvas_x - 2,
|
||||
canvas_pos.y + canvas_y - 2);
|
||||
ImVec2 obj_end(canvas_pos.x + canvas_x + 18,
|
||||
canvas_pos.y + canvas_y + 18);
|
||||
draw_list->AddRect(obj_start, obj_end, IM_COL32(0, 255, 255, 255), 0.0f,
|
||||
0, 2.0f);
|
||||
}
|
||||
auto& room = (*rooms_)[current_room_id_];
|
||||
const auto& objects = room.GetTileObjects();
|
||||
|
||||
// Draw highlights for all selected objects
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
ImVec2 canvas_pos = canvas_->zero_point();
|
||||
|
||||
for (size_t index : selected_object_indices_) {
|
||||
if (index < objects.size()) {
|
||||
const auto& object = objects[index];
|
||||
auto [canvas_x, canvas_y] = RoomToCanvasCoordinates(object.x_, object.y_);
|
||||
|
||||
// Calculate object size for highlight
|
||||
int obj_width = 8 + (object.size_ & 0x0F) * 4;
|
||||
int obj_height = 8 + ((object.size_ >> 4) & 0x0F) * 4;
|
||||
obj_width = std::min(obj_width, 64);
|
||||
obj_height = std::min(obj_height, 64);
|
||||
|
||||
// Draw cyan selection highlight
|
||||
ImVec2 obj_start(canvas_pos.x + canvas_x - 2,
|
||||
canvas_pos.y + canvas_y - 2);
|
||||
ImVec2 obj_end(canvas_pos.x + canvas_x + obj_width + 2,
|
||||
canvas_pos.y + canvas_y + obj_height + 2);
|
||||
|
||||
// Animated selection (pulsing effect)
|
||||
float pulse = 0.7f + 0.3f * std::sin(static_cast<float>(ImGui::GetTime()) * 4.0f);
|
||||
draw_list->AddRect(obj_start, obj_end,
|
||||
IM_COL32(0, static_cast<int>(255 * pulse), 255, 255),
|
||||
0.0f, 0, 2.5f);
|
||||
|
||||
// Draw corner handles for selected objects
|
||||
constexpr float handle_size = 4.0f;
|
||||
draw_list->AddRectFilled(
|
||||
ImVec2(obj_start.x - handle_size/2, obj_start.y - handle_size/2),
|
||||
ImVec2(obj_start.x + handle_size/2, obj_start.y + handle_size/2),
|
||||
IM_COL32(0, 255, 255, 255));
|
||||
draw_list->AddRectFilled(
|
||||
ImVec2(obj_end.x - handle_size/2, obj_start.y - handle_size/2),
|
||||
ImVec2(obj_end.x + handle_size/2, obj_start.y + handle_size/2),
|
||||
IM_COL32(0, 255, 255, 255));
|
||||
draw_list->AddRectFilled(
|
||||
ImVec2(obj_start.x - handle_size/2, obj_end.y - handle_size/2),
|
||||
ImVec2(obj_start.x + handle_size/2, obj_end.y + handle_size/2),
|
||||
IM_COL32(0, 255, 255, 255));
|
||||
draw_list->AddRectFilled(
|
||||
ImVec2(obj_end.x - handle_size/2, obj_end.y - handle_size/2),
|
||||
ImVec2(obj_end.x + handle_size/2, obj_end.y + handle_size/2),
|
||||
IM_COL32(0, 255, 255, 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ class DungeonObjectInteraction {
|
||||
// Selection rectangle (like OverworldEditor)
|
||||
void DrawObjectSelectRect();
|
||||
void SelectObjectsInRect();
|
||||
void DrawSelectionHighlights(); // Draw highlights for selected objects
|
||||
|
||||
// Drag and select box functionality
|
||||
void DrawSelectBox();
|
||||
|
||||
@@ -90,7 +90,9 @@ void DungeonObjectSelector::DrawObjectRenderer() {
|
||||
auto preview_bitmap = std::move(preview_result.value());
|
||||
if (preview_bitmap.width() > 0 && preview_bitmap.height() > 0) {
|
||||
preview_bitmap.SetPalette(preview_palette_);
|
||||
core::Renderer::Get().RenderBitmap(&preview_bitmap);
|
||||
// Queue texture creation via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, &preview_bitmap);
|
||||
object_canvas_.DrawBitmap(preview_bitmap, preview_x, preview_y, 1.0f, 255);
|
||||
} else {
|
||||
// Fallback: Draw primitive shape
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
#include "dungeon_renderer.h"
|
||||
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "app/core/window.h"
|
||||
#include "app/gfx/arena.h"
|
||||
#include "app/gui/color.h"
|
||||
|
||||
namespace yaze::editor {
|
||||
|
||||
using core::Renderer;
|
||||
|
||||
void DungeonRenderer::RenderObjectInCanvas(const zelda3::RoomObject& object,
|
||||
const gfx::SnesPalette& palette) {
|
||||
// Validate ROM is loaded
|
||||
@@ -55,7 +51,9 @@ void DungeonRenderer::RenderObjectInCanvas(const zelda3::RoomObject& object,
|
||||
if (object_bitmap.width() > 0 && object_bitmap.height() > 0 &&
|
||||
object_bitmap.data() != nullptr) {
|
||||
object_bitmap.SetPalette(palette);
|
||||
core::Renderer::Get().RenderBitmap(&object_bitmap);
|
||||
// Queue texture creation for the object bitmap via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, &object_bitmap);
|
||||
canvas_->DrawBitmap(object_bitmap, canvas_x, canvas_y, 1.0f, 255);
|
||||
// Cache the successfully rendered bitmap
|
||||
ObjectRenderCache cache_entry;
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
#include "object_editor_card.h"
|
||||
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "app/gfx/backend/irenderer.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/gui/ui_helpers.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze::editor {
|
||||
|
||||
ObjectEditorCard::ObjectEditorCard(Rom* rom, DungeonCanvasViewer* canvas_viewer)
|
||||
: rom_(rom), canvas_viewer_(canvas_viewer), object_selector_(rom) {
|
||||
emulator_preview_.Initialize(rom);
|
||||
ObjectEditorCard::ObjectEditorCard(gfx::IRenderer* renderer, Rom* rom, DungeonCanvasViewer* canvas_viewer)
|
||||
: renderer_(renderer), rom_(rom), canvas_viewer_(canvas_viewer), object_selector_(rom) {
|
||||
emulator_preview_.Initialize(renderer, rom);
|
||||
}
|
||||
|
||||
void ObjectEditorCard::Draw(bool* p_open) {
|
||||
@@ -93,7 +94,7 @@ void ObjectEditorCard::DrawObjectSelector() {
|
||||
ImGui::Separator();
|
||||
|
||||
// Object list with categories
|
||||
if (ImGui::BeginChild("##ObjectList", ImVec2(0, -100), true)) {
|
||||
if (ImGui::BeginChild("##ObjectList", ImVec2(0, 0), true)) {
|
||||
// Floor objects
|
||||
if (ImGui::CollapsingHeader(ICON_MD_GRID_ON " Floor Objects",
|
||||
ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
@@ -268,8 +269,10 @@ void ObjectEditorCard::DrawObjectPreviewIcon(int object_id, const ImVec2& size)
|
||||
|
||||
void ObjectEditorCard::DrawSelectedObjectInfo() {
|
||||
ImGui::BeginGroup();
|
||||
|
||||
// Show current object for placement
|
||||
ImGui::TextColored(ImVec4(0.4f, 0.8f, 1.0f, 1.0f),
|
||||
ICON_MD_INFO " Current Object:");
|
||||
ICON_MD_INFO " Current:");
|
||||
|
||||
if (has_preview_object_) {
|
||||
ImGui::SameLine();
|
||||
@@ -278,14 +281,35 @@ void ObjectEditorCard::DrawSelectedObjectInfo() {
|
||||
ImGui::Text("Layer: %s",
|
||||
preview_object_.layer_ == zelda3::RoomObject::BG1 ? "BG1" :
|
||||
preview_object_.layer_ == zelda3::RoomObject::BG2 ? "BG2" : "BG3");
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("Mode: %s",
|
||||
interaction_mode_ == InteractionMode::Place ? "Place" :
|
||||
interaction_mode_ == InteractionMode::Select ? "Select" :
|
||||
interaction_mode_ == InteractionMode::Delete ? "Delete" : "None");
|
||||
} else {
|
||||
ImGui::SameLine();
|
||||
ImGui::TextDisabled("None selected");
|
||||
ImGui::TextDisabled("None");
|
||||
}
|
||||
|
||||
// Show selection count
|
||||
auto& interaction = canvas_viewer_->object_interaction();
|
||||
const auto& selected = interaction.GetSelectedObjectIndices();
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("|");
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.4f, 1.0f),
|
||||
ICON_MD_CHECKLIST " Selected: %zu", selected.size());
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("|");
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("Mode: %s",
|
||||
interaction_mode_ == InteractionMode::Place ? ICON_MD_ADD_BOX " Place" :
|
||||
interaction_mode_ == InteractionMode::Select ? ICON_MD_CHECK_BOX " Select" :
|
||||
interaction_mode_ == InteractionMode::Delete ? ICON_MD_DELETE " Delete" : "None");
|
||||
|
||||
// Show quick actions for selections
|
||||
if (!selected.empty()) {
|
||||
ImGui::SameLine();
|
||||
if (ImGui::SmallButton(ICON_MD_CLEAR " Clear")) {
|
||||
interaction.ClearSelection();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndGroup();
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <unordered_map>
|
||||
|
||||
#include "app/editor/dungeon/dungeon_canvas_viewer.h"
|
||||
#include "app/gfx/backend/irenderer.h"
|
||||
#include "app/gui/canvas.h"
|
||||
#include "app/editor/dungeon/dungeon_object_selector.h"
|
||||
#include "app/gui/editor_layout.h"
|
||||
@@ -27,7 +28,7 @@ namespace editor {
|
||||
*/
|
||||
class ObjectEditorCard {
|
||||
public:
|
||||
ObjectEditorCard(Rom* rom, DungeonCanvasViewer* canvas_viewer);
|
||||
ObjectEditorCard(gfx::IRenderer* renderer, Rom* rom, DungeonCanvasViewer* canvas_viewer);
|
||||
|
||||
// Main update function
|
||||
void Draw(bool* p_open);
|
||||
@@ -59,7 +60,7 @@ class ObjectEditorCard {
|
||||
|
||||
// UI state
|
||||
int selected_tab_ = 0;
|
||||
bool show_emulator_preview_ = true;
|
||||
bool show_emulator_preview_ = false; // Disabled by default for performance
|
||||
bool show_object_list_ = true;
|
||||
bool show_interaction_controls_ = true;
|
||||
|
||||
@@ -75,6 +76,7 @@ class ObjectEditorCard {
|
||||
// Selected object for placement
|
||||
zelda3::RoomObject preview_object_{0, 0, 0, 0, 0};
|
||||
bool has_preview_object_ = false;
|
||||
gfx::IRenderer* renderer_;
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
|
||||
@@ -230,7 +230,9 @@ constexpr const char* kAssemblyEditorName = ICON_MD_CODE " Assembly Editor";
|
||||
constexpr const char* kDungeonEditorName = ICON_MD_CASTLE " Dungeon Editor";
|
||||
constexpr const char* kMusicEditorName = ICON_MD_MUSIC_NOTE " Music Editor";
|
||||
|
||||
void EditorManager::Initialize(const std::string& filename) {
|
||||
void EditorManager::Initialize(gfx::IRenderer* renderer, const std::string& filename) {
|
||||
renderer_ = renderer;
|
||||
|
||||
// Point to a blank editor set when no ROM is loaded
|
||||
current_editor_set_ = &blank_editor_set_;
|
||||
|
||||
@@ -2097,6 +2099,8 @@ absl::Status EditorManager::LoadAssets() {
|
||||
|
||||
current_editor_set_->overworld_editor_.Initialize();
|
||||
current_editor_set_->message_editor_.Initialize();
|
||||
// Initialize the dungeon editor with the renderer
|
||||
current_editor_set_->dungeon_editor_.Initialize(renderer_, current_rom_);
|
||||
ASSIGN_OR_RETURN(*gfx::Arena::Get().mutable_gfx_sheets(),
|
||||
LoadAllGraphicsData(*current_rom_));
|
||||
RETURN_IF_ERROR(current_editor_set_->overworld_editor_.Load());
|
||||
|
||||
@@ -105,7 +105,7 @@ class EditorManager {
|
||||
context_.popup_manager = popup_manager_.get();
|
||||
}
|
||||
|
||||
void Initialize(const std::string& filename = "");
|
||||
void Initialize(gfx::IRenderer* renderer, const std::string& filename = "");
|
||||
absl::Status Update();
|
||||
void DrawMenuBar();
|
||||
|
||||
@@ -262,6 +262,8 @@ class EditorManager {
|
||||
EditorSet* current_editor_set_ = nullptr;
|
||||
Editor* current_editor_ = nullptr;
|
||||
EditorSet blank_editor_set_{};
|
||||
|
||||
gfx::IRenderer* renderer_ = nullptr;
|
||||
|
||||
core::YazeProject current_project_;
|
||||
EditorContext context_;
|
||||
|
||||
@@ -29,8 +29,6 @@
|
||||
namespace yaze {
|
||||
namespace editor {
|
||||
|
||||
using core::Renderer;
|
||||
|
||||
using gfx::kPaletteGroupAddressesKeys;
|
||||
using ImGui::Button;
|
||||
using ImGui::InputInt;
|
||||
@@ -45,7 +43,50 @@ constexpr ImGuiTableFlags kGfxEditTableFlags =
|
||||
|
||||
void GraphicsEditor::Initialize() {}
|
||||
|
||||
absl::Status GraphicsEditor::Load() { return absl::OkStatus(); }
|
||||
absl::Status GraphicsEditor::Load() {
|
||||
gfx::ScopedTimer timer("GraphicsEditor::Load");
|
||||
|
||||
// Initialize all graphics sheets with appropriate palettes from ROM
|
||||
if (rom()->is_loaded()) {
|
||||
auto& sheets = gfx::Arena::Get().gfx_sheets();
|
||||
|
||||
// Apply default palettes to all sheets based on common SNES ROM structure
|
||||
// Sheets 0-112: Use overworld/dungeon palettes
|
||||
// Sheets 113-127: Use sprite palettes
|
||||
// Sheets 128-222: Use auxiliary/menu palettes
|
||||
|
||||
for (int i = 0; i < kNumGfxSheets; i++) {
|
||||
if (sheets[i].is_active() && sheets[i].surface()) {
|
||||
// Determine which palette group to use based on sheet index
|
||||
gfx::SnesPalette sheet_palette;
|
||||
|
||||
if (i < 113) {
|
||||
// Overworld/Dungeon graphics - use main palette
|
||||
auto palette_group = rom()->palette_group().dungeon_main;
|
||||
sheet_palette = palette_group[0]; // Use first palette as default
|
||||
} else if (i < 128) {
|
||||
// Sprite graphics - use sprite palettes
|
||||
auto palette_group = rom()->palette_group().sprites_aux1;
|
||||
sheet_palette = palette_group[0];
|
||||
} else {
|
||||
// Auxiliary graphics - use HUD/menu palettes
|
||||
sheet_palette = rom()->palette_group().hud.palette(0);
|
||||
}
|
||||
|
||||
// Apply palette and queue texture creation
|
||||
sheets[i].SetPalette(sheet_palette);
|
||||
|
||||
// Queue texture creation if not already created
|
||||
if (!sheets[i].texture()) {
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, &sheets[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status GraphicsEditor::Update() {
|
||||
DrawToolset();
|
||||
@@ -273,36 +314,43 @@ absl::Status GraphicsEditor::UpdateGfxSheetList() {
|
||||
graphics_bin_canvas_.DrawBackground(ImVec2(0x100 + 1, 0x40 + 1));
|
||||
graphics_bin_canvas_.DrawContextMenu();
|
||||
if (value.is_active()) {
|
||||
auto texture = value.texture();
|
||||
graphics_bin_canvas_.draw_list()->AddImage(
|
||||
(ImTextureID)(intptr_t)texture,
|
||||
ImVec2(graphics_bin_canvas_.zero_point().x + 2,
|
||||
graphics_bin_canvas_.zero_point().y + 2),
|
||||
ImVec2(graphics_bin_canvas_.zero_point().x +
|
||||
value.width() * sheet_scale_,
|
||||
graphics_bin_canvas_.zero_point().y +
|
||||
value.height() * sheet_scale_));
|
||||
|
||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
|
||||
current_sheet_ = key;
|
||||
open_sheets_.insert(key);
|
||||
// Ensure texture exists for active sheets
|
||||
if (!value.texture() && value.surface()) {
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, &value);
|
||||
}
|
||||
|
||||
auto texture = value.texture();
|
||||
if (texture) {
|
||||
graphics_bin_canvas_.draw_list()->AddImage(
|
||||
(ImTextureID)(intptr_t)texture,
|
||||
ImVec2(graphics_bin_canvas_.zero_point().x + 2,
|
||||
graphics_bin_canvas_.zero_point().y + 2),
|
||||
ImVec2(graphics_bin_canvas_.zero_point().x +
|
||||
value.width() * sheet_scale_,
|
||||
graphics_bin_canvas_.zero_point().y +
|
||||
value.height() * sheet_scale_));
|
||||
|
||||
// Add a slightly transparent rectangle behind the text
|
||||
ImVec2 text_pos(graphics_bin_canvas_.zero_point().x + 2,
|
||||
graphics_bin_canvas_.zero_point().y + 2);
|
||||
ImVec2 text_size =
|
||||
ImGui::CalcTextSize(absl::StrFormat("%02X", key).c_str());
|
||||
ImVec2 rent_min(text_pos.x, text_pos.y);
|
||||
ImVec2 rent_max(text_pos.x + text_size.x, text_pos.y + text_size.y);
|
||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
|
||||
current_sheet_ = key;
|
||||
open_sheets_.insert(key);
|
||||
}
|
||||
|
||||
graphics_bin_canvas_.draw_list()->AddRectFilled(rent_min, rent_max,
|
||||
IM_COL32(0, 125, 0, 128));
|
||||
// Add a slightly transparent rectangle behind the text
|
||||
ImVec2 text_pos(graphics_bin_canvas_.zero_point().x + 2,
|
||||
graphics_bin_canvas_.zero_point().y + 2);
|
||||
ImVec2 text_size =
|
||||
ImGui::CalcTextSize(absl::StrFormat("%02X", key).c_str());
|
||||
ImVec2 rect_min(text_pos.x, text_pos.y);
|
||||
ImVec2 rect_max(text_pos.x + text_size.x, text_pos.y + text_size.y);
|
||||
|
||||
graphics_bin_canvas_.draw_list()->AddText(
|
||||
text_pos, IM_COL32(125, 255, 125, 255),
|
||||
absl::StrFormat("%02X", key).c_str());
|
||||
graphics_bin_canvas_.draw_list()->AddRectFilled(rect_min, rect_max,
|
||||
IM_COL32(0, 125, 0, 128));
|
||||
|
||||
graphics_bin_canvas_.draw_list()->AddText(
|
||||
text_pos, IM_COL32(125, 255, 125, 255),
|
||||
absl::StrFormat("%02X", key).c_str());
|
||||
}
|
||||
key++;
|
||||
}
|
||||
graphics_bin_canvas_.DrawGrid(16.0f);
|
||||
@@ -362,13 +410,19 @@ absl::Status GraphicsEditor::UpdateGfxTabView() {
|
||||
current_sheet_canvas_.DrawTileOnBitmap(tile_size_, ¤t_bitmap,
|
||||
current_color_);
|
||||
// Use batch operations for texture updates
|
||||
current_bitmap.QueueTextureUpdate(core::Renderer::Get().renderer());
|
||||
// current_bitmap.QueueTextureUpdate(core::Renderer::Get().renderer());
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, ¤t_bitmap);
|
||||
};
|
||||
|
||||
current_sheet_canvas_.UpdateColorPainter(
|
||||
gfx::Arena::Get().mutable_gfx_sheets()->at(sheet_id),
|
||||
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));
|
||||
|
||||
ImGui::EndChild();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
@@ -399,7 +453,7 @@ absl::Status GraphicsEditor::UpdateGfxTabView() {
|
||||
current_sheet_ = id;
|
||||
// ImVec2(0x100, 0x40),
|
||||
current_sheet_canvas_.UpdateColorPainter(
|
||||
gfx::Arena::Get().mutable_gfx_sheets()->at(id), current_color_,
|
||||
nullptr, gfx::Arena::Get().mutable_gfx_sheets()->at(id), current_color_,
|
||||
[&]() {
|
||||
|
||||
},
|
||||
@@ -415,9 +469,6 @@ absl::Status GraphicsEditor::UpdateGfxTabView() {
|
||||
}
|
||||
}
|
||||
|
||||
// Process all queued texture updates at once
|
||||
gfx::Arena::Get().ProcessBatchTextureUpdates();
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
@@ -426,24 +477,73 @@ absl::Status GraphicsEditor::UpdatePaletteColumn() {
|
||||
auto palette_group = *rom()->palette_group().get_group(
|
||||
kPaletteGroupAddressesKeys[edit_palette_group_name_index_]);
|
||||
auto palette = palette_group.palette(edit_palette_index_);
|
||||
gui::TextWithSeparators("ROM Palette");
|
||||
ImGui::SetNextItemWidth(100.f);
|
||||
gui::TextWithSeparators("ROM Palette Management");
|
||||
|
||||
// Quick palette presets for common SNES graphics types
|
||||
ImGui::Text("Quick Presets:");
|
||||
if (ImGui::Button("Overworld")) {
|
||||
edit_palette_group_name_index_ = 0; // Dungeon Main
|
||||
edit_palette_index_ = 0;
|
||||
refresh_graphics_ = true;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Dungeon")) {
|
||||
edit_palette_group_name_index_ = 0; // Dungeon Main
|
||||
edit_palette_index_ = 1;
|
||||
refresh_graphics_ = true;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Sprites")) {
|
||||
edit_palette_group_name_index_ = 4; // Sprites Aux1
|
||||
edit_palette_index_ = 0;
|
||||
refresh_graphics_ = true;
|
||||
}
|
||||
ImGui::Separator();
|
||||
|
||||
// Apply current palette to current sheet
|
||||
if (ImGui::Button("Apply to Current Sheet") && !open_sheets_.empty()) {
|
||||
refresh_graphics_ = true;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Apply to All Sheets")) {
|
||||
// Apply current palette to all active sheets
|
||||
for (int i = 0; i < kNumGfxSheets; i++) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::SetNextItemWidth(150.f);
|
||||
ImGui::Combo("Palette Group", (int*)&edit_palette_group_name_index_,
|
||||
kPaletteGroupAddressesKeys,
|
||||
IM_ARRAYSIZE(kPaletteGroupAddressesKeys));
|
||||
ImGui::SetNextItemWidth(100.f);
|
||||
gui::InputHex("Palette Group Index", &edit_palette_index_);
|
||||
gui::InputHex("Palette Index", &edit_palette_index_);
|
||||
ImGui::SetNextItemWidth(100.f);
|
||||
gui::InputHex("Sub-Palette", &edit_palette_sub_index_);
|
||||
|
||||
gui::SelectablePalettePipeline(edit_palette_sub_index_, refresh_graphics_,
|
||||
palette);
|
||||
|
||||
if (refresh_graphics_ && !open_sheets_.empty()) {
|
||||
gfx::Arena::Get()
|
||||
.mutable_gfx_sheets()
|
||||
->data()[current_sheet_]
|
||||
.SetPaletteWithTransparent(palette, edit_palette_sub_index_);
|
||||
Renderer::Get().UpdateBitmap(
|
||||
&gfx::Arena::Get().mutable_gfx_sheets()->data()[current_sheet_]);
|
||||
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);
|
||||
}
|
||||
}
|
||||
refresh_graphics_ = false;
|
||||
}
|
||||
}
|
||||
@@ -583,7 +683,8 @@ absl::Status GraphicsEditor::DrawCgxImport() {
|
||||
cgx_bitmap_.Create(0x80, 0x200, 8, decoded_cgx_);
|
||||
if (col_file_) {
|
||||
cgx_bitmap_.SetPalette(decoded_col_);
|
||||
Renderer::Get().RenderBitmap(&cgx_bitmap_);
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, &cgx_bitmap_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -613,7 +714,8 @@ absl::Status GraphicsEditor::DrawScrImport() {
|
||||
scr_bitmap_.Create(0x100, 0x100, 8, decoded_scr_data_);
|
||||
if (scr_loaded_) {
|
||||
scr_bitmap_.SetPalette(decoded_col_);
|
||||
Renderer::Get().RenderBitmap(&scr_bitmap_);
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, &scr_bitmap_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -815,7 +917,8 @@ absl::Status GraphicsEditor::DecompressImportData(int size) {
|
||||
}
|
||||
}
|
||||
|
||||
Renderer::Get().RenderBitmap(&bin_bitmap_);
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, &bin_bitmap_);
|
||||
gfx_loaded_ = true;
|
||||
|
||||
return absl::OkStatus();
|
||||
@@ -844,7 +947,8 @@ absl::Status GraphicsEditor::DecompressSuperDonkey() {
|
||||
gfx_sheets_[i].SetPalette(z3_rom_palette_);
|
||||
}
|
||||
|
||||
Renderer::Get().RenderBitmap(&gfx_sheets_[i]);
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, &gfx_sheets_[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
@@ -868,7 +972,8 @@ absl::Status GraphicsEditor::DecompressSuperDonkey() {
|
||||
gfx_sheets_[i].SetPalette(z3_rom_palette_);
|
||||
}
|
||||
|
||||
Renderer::Get().RenderBitmap(&gfx_sheets_[i]);
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, &gfx_sheets_[i]);
|
||||
i++;
|
||||
}
|
||||
super_donkey_ = true;
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
namespace yaze {
|
||||
namespace editor {
|
||||
|
||||
using core::Renderer;
|
||||
|
||||
constexpr uint32_t kRedPen = 0xFF0000FF;
|
||||
|
||||
@@ -56,7 +55,9 @@ absl::Status ScreenEditor::Load() {
|
||||
sheets_[i].Get8x8Tile(tile_index, x, y, tile_data, tile_data_offset);
|
||||
tile8_individual_.emplace_back(gfx::Bitmap(8, 8, 4, tile_data));
|
||||
tile8_individual_.back().SetPalette(*rom()->mutable_dungeon_palette(3));
|
||||
Renderer::Get().RenderBitmap(&tile8_individual_.back());
|
||||
// Queue texture creation via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, &tile8_individual_.back());
|
||||
}
|
||||
tile_data_offset = 0;
|
||||
}
|
||||
@@ -249,15 +250,17 @@ void ScreenEditor::DrawDungeonMapScreen(int i) {
|
||||
int tile16_id = tile_ids_to_render[idx];
|
||||
ImVec2 pos = tile_positions[idx];
|
||||
|
||||
gfx::RenderTile16(tile16_blockset_, tile16_id);
|
||||
gfx::RenderTile16(nullptr, tile16_blockset_, tile16_id);
|
||||
// Get tile from cache after rendering
|
||||
auto* cached_tile = tile16_blockset_.tile_cache.GetTile(tile16_id);
|
||||
if (cached_tile && cached_tile->is_active()) {
|
||||
// Ensure the cached tile has a valid texture
|
||||
if (!cached_tile->texture()) {
|
||||
core::Renderer::Get().RenderBitmap(cached_tile);
|
||||
// Queue texture creation via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, cached_tile);
|
||||
}
|
||||
screen_canvas_.DrawBitmap(*cached_tile, pos.x, pos.y, 4.0F);
|
||||
screen_canvas_.DrawBitmap(*cached_tile, pos.x, pos.y, 4.0F, 255);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,12 +385,12 @@ void ScreenEditor::DrawDungeonMapsRoomGfx() {
|
||||
(tilesheet_canvas_.points().front().y / 32) * 16;
|
||||
|
||||
// Render selected tile16 and cache tile metadata
|
||||
gfx::RenderTile16(tile16_blockset_, selected_tile16_);
|
||||
gfx::RenderTile16(nullptr, tile16_blockset_, selected_tile16_);
|
||||
std::ranges::copy(tile16_blockset_.tile_info[selected_tile16_],
|
||||
current_tile16_info.begin());
|
||||
}
|
||||
// Use direct bitmap rendering for tilesheet
|
||||
tilesheet_canvas_.DrawBitmap(tile16_blockset_.atlas, 1, 1, 2.0F);
|
||||
tilesheet_canvas_.DrawBitmap(tile16_blockset_.atlas, 1, 1, 2.0F, 255);
|
||||
tilesheet_canvas_.DrawGrid(32.f);
|
||||
tilesheet_canvas_.DrawOverlay();
|
||||
|
||||
@@ -408,16 +411,18 @@ void ScreenEditor::DrawDungeonMapsRoomGfx() {
|
||||
current_tile16_info[0], current_tile16_info[1],
|
||||
current_tile16_info[2], current_tile16_info[3], 212,
|
||||
selected_tile16_);
|
||||
gfx::UpdateTile16(tile16_blockset_, selected_tile16_);
|
||||
gfx::UpdateTile16(nullptr, tile16_blockset_, selected_tile16_);
|
||||
}
|
||||
// Get selected tile from cache
|
||||
auto* selected_tile = tile16_blockset_.tile_cache.GetTile(selected_tile16_);
|
||||
if (selected_tile && selected_tile->is_active()) {
|
||||
// Ensure the selected tile has a valid texture
|
||||
if (!selected_tile->texture()) {
|
||||
core::Renderer::Get().RenderBitmap(selected_tile);
|
||||
// Queue texture creation via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, selected_tile);
|
||||
}
|
||||
current_tile_canvas_.DrawBitmap(*selected_tile, 2, 4.0f);
|
||||
current_tile_canvas_.DrawBitmap(*selected_tile, 2, 2, 4.0f, 255);
|
||||
}
|
||||
current_tile_canvas_.DrawGrid(16.f);
|
||||
current_tile_canvas_.DrawOverlay();
|
||||
@@ -434,7 +439,7 @@ void ScreenEditor::DrawDungeonMapsRoomGfx() {
|
||||
current_tile16_info[0], current_tile16_info[1],
|
||||
current_tile16_info[2], current_tile16_info[3], 212,
|
||||
selected_tile16_);
|
||||
gfx::UpdateTile16(tile16_blockset_, selected_tile16_);
|
||||
gfx::UpdateTile16(nullptr, tile16_blockset_, selected_tile16_);
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
@@ -543,7 +548,9 @@ void ScreenEditor::LoadBinaryGfx() {
|
||||
converted_bin.begin() + ((i + 1) * 0x1000));
|
||||
sheets_.emplace(i, gfx::Bitmap(128, 32, 8, gfx_sheets[i]));
|
||||
sheets_[i].SetPalette(*rom()->mutable_dungeon_palette(3));
|
||||
Renderer::Get().RenderBitmap(&sheets_[i]);
|
||||
// Queue texture creation via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, &sheets_[i]);
|
||||
}
|
||||
binary_gfx_loaded_ = true;
|
||||
} else {
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "app/gfx/arena.h"
|
||||
#include "app/gfx/performance_profiler.h"
|
||||
#include "util/file_util.h"
|
||||
#include "app/core/window.h"
|
||||
#include "app/gfx/bitmap.h"
|
||||
#include "app/gfx/snes_palette.h"
|
||||
#include "app/gfx/snes_tile.h"
|
||||
@@ -38,7 +38,6 @@ std::string DisplayTextOverflowError(int pos, bool bank) {
|
||||
}
|
||||
} // namespace
|
||||
|
||||
using core::Renderer;
|
||||
|
||||
using ImGui::BeginChild;
|
||||
using ImGui::BeginTable;
|
||||
@@ -74,11 +73,12 @@ void MessageEditor::Initialize() {
|
||||
}
|
||||
message_preview_.font_gfx16_data_ =
|
||||
gfx::SnesTo8bppSheet(raw_font_gfx_data_, /*bpp=*/2, /*num_sheets=*/2);
|
||||
Renderer::Get().CreateAndRenderBitmap(
|
||||
kFontGfxMessageSize, kFontGfxMessageSize, kFontGfxMessageDepth,
|
||||
message_preview_.font_gfx16_data_, font_gfx_bitmap_,
|
||||
font_preview_colors_);
|
||||
*font_gfx_bitmap_.mutable_palette() = font_preview_colors_;
|
||||
// Create bitmap and queue texture creation
|
||||
font_gfx_bitmap_.Create(kFontGfxMessageSize, kFontGfxMessageSize,
|
||||
kFontGfxMessageDepth, message_preview_.font_gfx16_data_);
|
||||
font_gfx_bitmap_.SetPalette(font_preview_colors_);
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, &font_gfx_bitmap_);
|
||||
*current_font_gfx16_bitmap_.mutable_palette() = font_preview_colors_;
|
||||
|
||||
auto load_font = LoadFontGraphics(*rom());
|
||||
@@ -330,12 +330,16 @@ void MessageEditor::DrawMessagePreview() {
|
||||
if (current_font_gfx16_bitmap_.is_active()) {
|
||||
current_font_gfx16_bitmap_.mutable_data() =
|
||||
message_preview_.current_preview_data_;
|
||||
Renderer::Get().UpdateBitmap(¤t_font_gfx16_bitmap_);
|
||||
// Queue texture update via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, ¤t_font_gfx16_bitmap_);
|
||||
} else {
|
||||
Renderer::Get().CreateAndRenderBitmap(
|
||||
kCurrentMessageWidth, kCurrentMessageHeight, 172,
|
||||
message_preview_.current_preview_data_, current_font_gfx16_bitmap_,
|
||||
font_preview_colors_);
|
||||
// Create bitmap and queue texture creation
|
||||
current_font_gfx16_bitmap_.Create(kCurrentMessageWidth, kCurrentMessageHeight,
|
||||
172, message_preview_.current_preview_data_);
|
||||
current_font_gfx16_bitmap_.SetPalette(font_preview_colors_);
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, ¤t_font_gfx16_bitmap_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "app/core/asar_wrapper.h"
|
||||
#include "app/core/features.h"
|
||||
#include "app/core/window.h"
|
||||
#include "app/editor/overworld/map_properties.h"
|
||||
#include "app/editor/overworld/tile16_editor.h"
|
||||
#include "app/gfx/arena.h"
|
||||
@@ -43,7 +42,6 @@
|
||||
|
||||
namespace yaze::editor {
|
||||
|
||||
using core::Renderer;
|
||||
using namespace ImGui;
|
||||
|
||||
constexpr float kInputFieldSize = 30.f;
|
||||
@@ -710,7 +708,8 @@ void OverworldEditor::RenderUpdatedMapBitmap(
|
||||
current_bitmap.set_modified(true);
|
||||
|
||||
// Immediately update the texture to reflect changes
|
||||
core::Renderer::Get().UpdateBitmap(¤t_bitmap);
|
||||
// TODO: Queue texture for later rendering.
|
||||
// core::Renderer::Get().UpdateBitmap(¤t_bitmap);
|
||||
}
|
||||
|
||||
void OverworldEditor::CheckForOverworldEdits() {
|
||||
@@ -1092,11 +1091,13 @@ absl::Status OverworldEditor::CheckForCurrentMap() {
|
||||
|
||||
// Ensure tile16 blockset is fully updated before rendering
|
||||
if (tile16_blockset_.atlas.is_active()) {
|
||||
Renderer::Get().UpdateBitmap(&tile16_blockset_.atlas);
|
||||
// TODO: Queue texture for later rendering.
|
||||
// Renderer::Get().UpdateBitmap(&tile16_blockset_.atlas);
|
||||
}
|
||||
|
||||
// Update map texture with the traditional direct update approach
|
||||
Renderer::Get().UpdateBitmap(&maps_bmp_[current_map_]);
|
||||
// TODO: Queue texture for later rendering.
|
||||
// Renderer::Get().UpdateBitmap(&maps_bmp_[current_map_]);
|
||||
maps_bmp_[current_map_].set_modified(false);
|
||||
}
|
||||
|
||||
@@ -1411,9 +1412,10 @@ absl::Status OverworldEditor::DrawAreaGraphics() {
|
||||
overworld_.set_current_map(current_map_);
|
||||
palette_ = overworld_.current_area_palette();
|
||||
gfx::Bitmap bmp;
|
||||
Renderer::Get().CreateAndRenderBitmap(0x80, kOverworldMapSize, 0x08,
|
||||
overworld_.current_graphics(), bmp,
|
||||
palette_);
|
||||
// TODO: Queue texture for later rendering.
|
||||
// Renderer::Get().CreateAndRenderBitmap(0x80, kOverworldMapSize, 0x08,
|
||||
// overworld_.current_graphics(), bmp,
|
||||
// palette_);
|
||||
current_graphics_set_[current_map_] = bmp;
|
||||
}
|
||||
}
|
||||
@@ -1483,17 +1485,19 @@ absl::Status OverworldEditor::LoadGraphics() {
|
||||
// This avoids blocking the main thread with GPU texture creation
|
||||
{
|
||||
gfx::ScopedTimer gfx_timer("CreateBitmapWithoutTexture_Graphics");
|
||||
Renderer::Get().CreateBitmapWithoutTexture(0x80, kOverworldMapSize, 0x40,
|
||||
overworld_.current_graphics(),
|
||||
current_gfx_bmp_, palette_);
|
||||
// TODO: Queue texture for later rendering.
|
||||
// Renderer::Get().CreateBitmapWithoutTexture(0x80, kOverworldMapSize, 0x40,
|
||||
// overworld_.current_graphics(),
|
||||
// current_gfx_bmp_, palette_);
|
||||
}
|
||||
|
||||
LOG_DEBUG("OverworldEditor", "Loading overworld tileset (deferred textures).");
|
||||
{
|
||||
gfx::ScopedTimer tileset_timer("CreateBitmapWithoutTexture_Tileset");
|
||||
Renderer::Get().CreateBitmapWithoutTexture(
|
||||
0x80, 0x2000, 0x08, overworld_.tile16_blockset_data(),
|
||||
tile16_blockset_bmp_, palette_);
|
||||
// TODO: Queue texture for later rendering.
|
||||
// Renderer::Get().CreateBitmapWithoutTexture(
|
||||
// 0x80, 0x2000, 0x08, overworld_.tile16_blockset_data(),
|
||||
// tile16_blockset_bmp_, palette_);
|
||||
}
|
||||
map_blockset_loaded_ = true;
|
||||
|
||||
@@ -1504,8 +1508,14 @@ absl::Status OverworldEditor::LoadGraphics() {
|
||||
{
|
||||
gfx::ScopedTimer tilemap_timer("CreateTilemap");
|
||||
tile16_blockset_ =
|
||||
gfx::CreateTilemap(tile16_blockset_data, 0x80, 0x2000, kTile16Size,
|
||||
gfx::CreateTilemap(renderer_,tile16_blockset_data, 0x80, 0x2000, kTile16Size,
|
||||
zelda3::kNumTile16Individual, palette_);
|
||||
|
||||
// Queue texture creation for the tile16 blockset atlas
|
||||
if (tile16_blockset_.atlas.is_active() && tile16_blockset_.atlas.surface()) {
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, &tile16_blockset_.atlas);
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 2: Create bitmaps only for essential maps initially
|
||||
@@ -1566,7 +1576,9 @@ absl::Status OverworldEditor::LoadGraphics() {
|
||||
{
|
||||
gfx::ScopedTimer initial_textures_timer("CreateInitialTextures");
|
||||
for (int i = 0; i < initial_texture_count; ++i) {
|
||||
Renderer::Get().RenderBitmap(maps_to_texture[i]);
|
||||
// Queue texture creation/update for initial maps via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, maps_to_texture[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1588,7 +1600,10 @@ absl::Status OverworldEditor::LoadGraphics() {
|
||||
priority = (map_world == current_world_) ? 5 : 15; // Current world = priority 5, others = 15
|
||||
}
|
||||
|
||||
gfx::Arena::Get().QueueDeferredTexture(maps_to_texture[i], priority);
|
||||
// Queue texture creation for remaining maps via Arena's deferred system
|
||||
// Note: Priority system to be implemented in future enhancement
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, maps_to_texture[i]);
|
||||
}
|
||||
|
||||
if (core::FeatureFlags::get().overworld.kDrawOverworldSprites) {
|
||||
@@ -1617,20 +1632,16 @@ absl::Status OverworldEditor::LoadSpriteGraphics() {
|
||||
sprite_previews_[sprite.id()].Create(width, height, depth,
|
||||
*sprite.preview_graphics());
|
||||
sprite_previews_[sprite.id()].SetPalette(palette_);
|
||||
Renderer::Get().RenderBitmap(&(sprite_previews_[sprite.id()]));
|
||||
// TODO: Queue texture for later rendering.
|
||||
// Renderer::Get().RenderBitmap(&(sprite_previews_[sprite.id()]));
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
void OverworldEditor::ProcessDeferredTextures() {
|
||||
// Use Arena's centralized progressive loading system
|
||||
// This makes progressive loading available to all editors
|
||||
auto batch = gfx::Arena::Get().GetNextDeferredTextureBatch(4, 2);
|
||||
|
||||
for (auto* bitmap : batch) {
|
||||
if (bitmap && !bitmap->texture()) {
|
||||
Renderer::Get().RenderBitmap(bitmap);
|
||||
}
|
||||
// Process queued texture commands via Arena's deferred system
|
||||
if (renderer_) {
|
||||
gfx::Arena::Get().ProcessTextureQueue(renderer_);
|
||||
}
|
||||
|
||||
// Also process deferred map refreshes for modified maps
|
||||
@@ -1682,8 +1693,9 @@ void OverworldEditor::EnsureMapTexture(int map_index) {
|
||||
}
|
||||
|
||||
if (!bitmap.texture() && bitmap.is_active()) {
|
||||
Renderer::Get().RenderBitmap(&bitmap);
|
||||
// Note: Arena automatically removes from deferred queue when textures are created
|
||||
// Queue texture creation for this map
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, &bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1783,11 +1795,14 @@ void OverworldEditor::RefreshChildMapOnDemand(int map_index) {
|
||||
map_index);
|
||||
}
|
||||
|
||||
// CRITICAL FIX: Force COMPLETE texture recreation for immediate visibility
|
||||
// UpdateBitmap() was still deferred - we need to force a full re-render
|
||||
|
||||
// Always recreate the texture to ensure immediate GPU update
|
||||
Renderer::Get().RenderBitmap(&maps_bmp_[map_index]);
|
||||
// Queue texture update to ensure changes are visible
|
||||
if (maps_bmp_[map_index].texture()) {
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, &maps_bmp_[map_index]);
|
||||
} else {
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, &maps_bmp_[map_index]);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle multi-area maps (large, wide, tall) with safe coordination
|
||||
@@ -1933,9 +1948,10 @@ void OverworldEditor::RefreshMultiAreaMapsSafely(int map_index,
|
||||
}
|
||||
maps_bmp_[sibling].set_modified(false);
|
||||
|
||||
// Update texture if it exists
|
||||
// Queue texture update/creation
|
||||
if (maps_bmp_[sibling].texture()) {
|
||||
core::Renderer::Get().UpdateBitmap(&maps_bmp_[sibling]);
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, &maps_bmp_[sibling]);
|
||||
} else {
|
||||
EnsureMapTexture(sibling);
|
||||
}
|
||||
@@ -2192,8 +2208,19 @@ absl::Status OverworldEditor::RefreshTile16Blockset() {
|
||||
|
||||
const auto tile16_data = overworld_.tile16_blockset_data();
|
||||
|
||||
gfx::UpdateTilemap(tile16_blockset_, tile16_data);
|
||||
gfx::UpdateTilemap(renderer_, tile16_blockset_, tile16_data);
|
||||
tile16_blockset_.atlas.SetPalette(palette_);
|
||||
|
||||
// Queue texture update for the atlas
|
||||
if (tile16_blockset_.atlas.texture() && tile16_blockset_.atlas.is_active()) {
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, &tile16_blockset_.atlas);
|
||||
} else if (!tile16_blockset_.atlas.texture() && tile16_blockset_.atlas.is_active()) {
|
||||
// Create texture if it doesn't exist yet
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, &tile16_blockset_.atlas);
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ class OverworldEditor : public Editor, public gfx::GfxContext {
|
||||
// MapPropertiesSystem will be initialized after maps_bmp_ and canvas are ready
|
||||
}
|
||||
|
||||
void Initialize(gfx::IRenderer* renderer, Rom* rom);
|
||||
void Initialize() override;
|
||||
absl::Status Load() override;
|
||||
absl::Status Update() final;
|
||||
@@ -326,6 +327,7 @@ class OverworldEditor : public Editor, public gfx::GfxContext {
|
||||
|
||||
Rom* rom_;
|
||||
|
||||
gfx::IRenderer* renderer_;
|
||||
Tile16Editor tile16_editor_{rom_, &tile16_blockset_};
|
||||
GfxGroupEditor gfx_group_editor_;
|
||||
PaletteEditor palette_editor_;
|
||||
|
||||
@@ -138,7 +138,9 @@ absl::Status OverworldEditor::DrawScratchSpace() {
|
||||
if (all_gfx_loaded_) {
|
||||
palette_ = overworld_.current_area_palette();
|
||||
current_slot.scratch_bitmap.SetPalette(palette_);
|
||||
core::Renderer::Get().RenderBitmap(¤t_slot.scratch_bitmap);
|
||||
// Queue texture creation via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, ¤t_slot.scratch_bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,9 +317,9 @@ void OverworldEditor::UpdateScratchBitmapTile(int tile_x, int tile_y,
|
||||
}
|
||||
|
||||
scratch_slot.scratch_bitmap.set_modified(true);
|
||||
// Use batch operations for texture updates
|
||||
scratch_slot.scratch_bitmap.QueueTextureUpdate(
|
||||
core::Renderer::Get().renderer());
|
||||
// Queue texture update via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, &scratch_slot.scratch_bitmap);
|
||||
scratch_slot.in_use = true;
|
||||
}
|
||||
|
||||
@@ -360,7 +362,9 @@ absl::Status OverworldEditor::SaveCurrentSelectionToScratch(int slot) {
|
||||
if (all_gfx_loaded_) {
|
||||
palette_ = overworld_.current_area_palette();
|
||||
scratch_spaces_[slot].scratch_bitmap.SetPalette(palette_);
|
||||
core::Renderer::Get().RenderBitmap(
|
||||
// Queue texture creation via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE,
|
||||
&scratch_spaces_[slot].scratch_bitmap);
|
||||
}
|
||||
|
||||
@@ -398,8 +402,6 @@ absl::Status OverworldEditor::SaveCurrentSelectionToScratch(int slot) {
|
||||
scratch_spaces_[slot].in_use = true;
|
||||
}
|
||||
|
||||
// Process all queued texture updates at once
|
||||
gfx::Arena::Get().ProcessBatchTextureUpdates();
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
@@ -433,7 +435,9 @@ absl::Status OverworldEditor::ClearScratchSpace(int slot) {
|
||||
auto& data = scratch_spaces_[slot].scratch_bitmap.mutable_data();
|
||||
std::fill(data.begin(), data.end(), 0);
|
||||
scratch_spaces_[slot].scratch_bitmap.set_modified(true);
|
||||
core::Renderer::Get().UpdateBitmap(&scratch_spaces_[slot].scratch_bitmap);
|
||||
// Queue texture update via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, &scratch_spaces_[slot].scratch_bitmap);
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
|
||||
@@ -3,13 +3,12 @@
|
||||
#include <array>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "app/core/window.h"
|
||||
#include "app/gfx/arena.h"
|
||||
#include "app/gfx/bitmap.h"
|
||||
#include "app/gfx/backend/irenderer.h"
|
||||
#include "app/gfx/performance_profiler.h"
|
||||
#include "app/gfx/snes_palette.h"
|
||||
#include "app/gui/canvas.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/gui/input.h"
|
||||
#include "app/gui/style.h"
|
||||
#include "app/rom.h"
|
||||
@@ -22,7 +21,6 @@
|
||||
namespace yaze {
|
||||
namespace editor {
|
||||
|
||||
using core::Renderer;
|
||||
using namespace ImGui;
|
||||
|
||||
absl::Status Tile16Editor::Initialize(
|
||||
@@ -34,14 +32,16 @@ absl::Status Tile16Editor::Initialize(
|
||||
current_gfx_bmp_.Create(current_gfx_bmp.width(), current_gfx_bmp.height(),
|
||||
current_gfx_bmp.depth(), current_gfx_bmp.vector());
|
||||
current_gfx_bmp_.SetPalette(current_gfx_bmp.palette()); // Temporary palette
|
||||
core::Renderer::Get().RenderBitmap(¤t_gfx_bmp_);
|
||||
// TODO: Queue texture for later rendering.
|
||||
// core::Renderer::Get().RenderBitmap(¤t_gfx_bmp_);
|
||||
|
||||
// Copy the tile16 blockset bitmap
|
||||
tile16_blockset_bmp_.Create(
|
||||
tile16_blockset_bmp.width(), tile16_blockset_bmp.height(),
|
||||
tile16_blockset_bmp.depth(), tile16_blockset_bmp.vector());
|
||||
tile16_blockset_bmp_.SetPalette(tile16_blockset_bmp.palette());
|
||||
core::Renderer::Get().RenderBitmap(&tile16_blockset_bmp_);
|
||||
// TODO: Queue texture for later rendering.
|
||||
// core::Renderer::Get().RenderBitmap(&tile16_blockset_bmp_);
|
||||
|
||||
// Note: LoadTile8() will be called after palette is set by overworld editor
|
||||
// This ensures proper palette coordination from the start
|
||||
@@ -50,7 +50,8 @@ absl::Status Tile16Editor::Initialize(
|
||||
current_tile16_bmp_.Create(kTile16Size, kTile16Size, 8,
|
||||
std::vector<uint8_t>(kTile16PixelCount, 0));
|
||||
current_tile16_bmp_.SetPalette(tile16_blockset_bmp.palette());
|
||||
core::Renderer::Get().RenderBitmap(¤t_tile16_bmp_);
|
||||
// TODO: Queue texture for later rendering.
|
||||
// core::Renderer::Get().RenderBitmap(¤t_tile16_bmp_);
|
||||
|
||||
// Initialize enhanced canvas features with proper sizing
|
||||
tile16_edit_canvas_.InitializeDefaults();
|
||||
@@ -345,8 +346,9 @@ absl::Status Tile16Editor::RefreshTile16Blockset() {
|
||||
// Mark atlas as modified to trigger regeneration
|
||||
tile16_blockset_->atlas.set_modified(true);
|
||||
|
||||
// Update the atlas bitmap using the safer direct approach
|
||||
core::Renderer::Get().UpdateBitmap(&tile16_blockset_->atlas);
|
||||
// Queue texture update via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, &tile16_blockset_->atlas);
|
||||
|
||||
util::logf("Tile16 blockset refreshed and regenerated");
|
||||
return absl::OkStatus();
|
||||
@@ -390,9 +392,10 @@ absl::Status Tile16Editor::UpdateBlocksetBitmap() {
|
||||
}
|
||||
}
|
||||
|
||||
// Mark the blockset bitmap as modified and use batch texture update
|
||||
// Mark the blockset bitmap as modified and queue texture update
|
||||
tile16_blockset_bmp_.set_modified(true);
|
||||
tile16_blockset_bmp_.QueueTextureUpdate(nullptr); // Use batch operations
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, &tile16_blockset_bmp_);
|
||||
|
||||
// Also update the tile16 blockset atlas if available
|
||||
if (tile16_blockset_->atlas.is_active()) {
|
||||
@@ -415,11 +418,9 @@ absl::Status Tile16Editor::UpdateBlocksetBitmap() {
|
||||
}
|
||||
|
||||
tile16_blockset_->atlas.set_modified(true);
|
||||
tile16_blockset_->atlas.QueueTextureUpdate(nullptr);
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, &tile16_blockset_->atlas);
|
||||
}
|
||||
|
||||
// Process all queued texture updates at once
|
||||
gfx::Arena::Get().ProcessBatchTextureUpdates();
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
@@ -515,8 +516,9 @@ absl::Status Tile16Editor::RegenerateTile16BitmapFromROM() {
|
||||
}
|
||||
}
|
||||
|
||||
// Render the updated bitmap
|
||||
core::Renderer::Get().RenderBitmap(¤t_tile16_bmp_);
|
||||
// Queue texture creation via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, ¤t_tile16_bmp_);
|
||||
|
||||
util::logf("Regenerated Tile16 bitmap for tile %d from ROM data",
|
||||
current_tile16_);
|
||||
@@ -606,9 +608,10 @@ absl::Status Tile16Editor::DrawToCurrentTile16(ImVec2 pos,
|
||||
}
|
||||
}
|
||||
|
||||
// Mark the bitmap as modified and update the renderer
|
||||
// Mark the bitmap as modified and queue texture update
|
||||
current_tile16_bmp_.set_modified(true);
|
||||
core::Renderer::Get().UpdateBitmap(¤t_tile16_bmp_);
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, ¤t_tile16_bmp_);
|
||||
|
||||
// Update ROM data when painting to tile16
|
||||
auto* tile_data = GetCurrentTile16Data();
|
||||
@@ -893,8 +896,9 @@ absl::Status Tile16Editor::UpdateTile16Edit() {
|
||||
}
|
||||
}
|
||||
|
||||
// Render the display tile
|
||||
core::Renderer::Get().RenderBitmap(&display_tile);
|
||||
// Queue texture creation for display tile
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, &display_tile);
|
||||
|
||||
// CRITICAL FIX: Handle tile painting with simple click instead of click+drag
|
||||
// Draw the preview first
|
||||
@@ -1273,7 +1277,9 @@ absl::Status Tile16Editor::LoadTile8() {
|
||||
// Fallback to ROM palette
|
||||
tile_bitmap.SetPalette(rom()->palette_group().overworld_main[0]);
|
||||
}
|
||||
core::Renderer::Get().RenderBitmap(&tile_bitmap);
|
||||
// Queue texture creation via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, &tile_bitmap);
|
||||
} catch (const std::exception& e) {
|
||||
util::logf("Error creating tile at (%d,%d): %s", tile_x, tile_y,
|
||||
e.what());
|
||||
@@ -1362,8 +1368,9 @@ absl::Status Tile16Editor::SetCurrentTile(int tile_id) {
|
||||
current_tile16_bmp_.SetPalette(rom()->palette_group().overworld_main[0]);
|
||||
}
|
||||
|
||||
// Render the bitmap
|
||||
core::Renderer::Get().RenderBitmap(¤t_tile16_bmp_);
|
||||
// Queue texture creation via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, ¤t_tile16_bmp_);
|
||||
|
||||
// Simple success logging
|
||||
util::logf("SetCurrentTile: loaded tile %d successfully", tile_id);
|
||||
@@ -1382,7 +1389,9 @@ absl::Status Tile16Editor::CopyTile16ToClipboard(int tile_id) {
|
||||
clipboard_tile16_.Create(16, 16, 8, tile_data);
|
||||
clipboard_tile16_.SetPalette(tile16_blockset_->atlas.palette());
|
||||
}
|
||||
core::Renderer::Get().RenderBitmap(&clipboard_tile16_);
|
||||
// Queue texture creation via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, &clipboard_tile16_);
|
||||
|
||||
clipboard_has_data_ = true;
|
||||
return absl::OkStatus();
|
||||
@@ -1396,7 +1405,9 @@ absl::Status Tile16Editor::PasteTile16FromClipboard() {
|
||||
// Copy the clipboard data to the current tile16
|
||||
current_tile16_bmp_.Create(16, 16, 8, clipboard_tile16_.vector());
|
||||
current_tile16_bmp_.SetPalette(clipboard_tile16_.palette());
|
||||
core::Renderer::Get().RenderBitmap(¤t_tile16_bmp_);
|
||||
// Queue texture creation via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, ¤t_tile16_bmp_);
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
@@ -1409,7 +1420,9 @@ absl::Status Tile16Editor::SaveTile16ToScratchSpace(int slot) {
|
||||
// Create a copy of the current tile16 bitmap
|
||||
scratch_space_[slot].Create(16, 16, 8, current_tile16_bmp_.vector());
|
||||
scratch_space_[slot].SetPalette(current_tile16_bmp_.palette());
|
||||
core::Renderer::Get().RenderBitmap(&scratch_space_[slot]);
|
||||
// Queue texture creation via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, &scratch_space_[slot]);
|
||||
|
||||
scratch_space_used_[slot] = true;
|
||||
return absl::OkStatus();
|
||||
@@ -1427,7 +1440,9 @@ absl::Status Tile16Editor::LoadTile16FromScratchSpace(int slot) {
|
||||
// Copy the scratch space data to the current tile16
|
||||
current_tile16_bmp_.Create(16, 16, 8, scratch_space_[slot].vector());
|
||||
current_tile16_bmp_.SetPalette(scratch_space_[slot].palette());
|
||||
core::Renderer::Get().RenderBitmap(¤t_tile16_bmp_);
|
||||
// Queue texture creation via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, ¤t_tile16_bmp_);
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
@@ -1471,7 +1486,9 @@ absl::Status Tile16Editor::FlipTile16Horizontal() {
|
||||
current_tile16_bmp_.SetPalette(palette_);
|
||||
current_tile16_bmp_.set_modified(true);
|
||||
|
||||
core::Renderer::Get().UpdateBitmap(¤t_tile16_bmp_);
|
||||
// Queue texture update via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, ¤t_tile16_bmp_);
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
@@ -1504,7 +1521,9 @@ absl::Status Tile16Editor::FlipTile16Vertical() {
|
||||
current_tile16_bmp_.SetPalette(palette_);
|
||||
current_tile16_bmp_.set_modified(true);
|
||||
|
||||
core::Renderer::Get().UpdateBitmap(¤t_tile16_bmp_);
|
||||
// Queue texture update via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, ¤t_tile16_bmp_);
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
@@ -1537,7 +1556,9 @@ absl::Status Tile16Editor::RotateTile16() {
|
||||
current_tile16_bmp_.SetPalette(palette_);
|
||||
current_tile16_bmp_.set_modified(true);
|
||||
|
||||
core::Renderer::Get().UpdateBitmap(¤t_tile16_bmp_);
|
||||
// Queue texture update via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, ¤t_tile16_bmp_);
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
@@ -1574,7 +1595,9 @@ absl::Status Tile16Editor::FillTile16WithTile8(int tile8_id) {
|
||||
}
|
||||
|
||||
current_tile16_bmp_.set_modified(true);
|
||||
core::Renderer::Get().UpdateBitmap(¤t_tile16_bmp_);
|
||||
// Queue texture update via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, ¤t_tile16_bmp_);
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
@@ -1590,7 +1613,9 @@ absl::Status Tile16Editor::ClearTile16() {
|
||||
std::fill(data.begin(), data.end(), 0);
|
||||
|
||||
current_tile16_bmp_.set_modified(true);
|
||||
core::Renderer::Get().UpdateBitmap(¤t_tile16_bmp_);
|
||||
// Queue texture update via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, ¤t_tile16_bmp_);
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
@@ -1633,7 +1658,9 @@ absl::Status Tile16Editor::PreviewPaletteChange(uint8_t palette_id) {
|
||||
const auto& ow_main_pal_group = rom()->palette_group().overworld_main;
|
||||
if (ow_main_pal_group.size() > palette_id) {
|
||||
preview_tile16_.SetPaletteWithTransparent(ow_main_pal_group[0], palette_id);
|
||||
core::Renderer::Get().UpdateBitmap(&preview_tile16_);
|
||||
// Queue texture update via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, &preview_tile16_);
|
||||
preview_dirty_ = true;
|
||||
}
|
||||
|
||||
@@ -1691,7 +1718,9 @@ absl::Status Tile16Editor::Undo() {
|
||||
y_flip = previous_state.y_flip;
|
||||
priority_tile = previous_state.priority;
|
||||
|
||||
core::Renderer::Get().UpdateBitmap(¤t_tile16_bmp_);
|
||||
// Queue texture update via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, ¤t_tile16_bmp_);
|
||||
undo_stack_.pop_back();
|
||||
|
||||
return absl::OkStatus();
|
||||
@@ -1714,7 +1743,9 @@ absl::Status Tile16Editor::Redo() {
|
||||
y_flip = next_state.y_flip;
|
||||
priority_tile = next_state.priority;
|
||||
|
||||
core::Renderer::Get().UpdateBitmap(¤t_tile16_bmp_);
|
||||
// Queue texture update via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, ¤t_tile16_bmp_);
|
||||
redo_stack_.pop_back();
|
||||
|
||||
return absl::OkStatus();
|
||||
@@ -1800,7 +1831,9 @@ absl::Status Tile16Editor::UpdateOverworldTilemap() {
|
||||
}
|
||||
|
||||
tile16_blockset_->atlas.set_modified(true);
|
||||
core::Renderer::Get().UpdateBitmap(&tile16_blockset_->atlas);
|
||||
// Queue texture update via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, &tile16_blockset_->atlas);
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
@@ -1813,7 +1846,9 @@ absl::Status Tile16Editor::CommitChangesToBlockset() {
|
||||
|
||||
// Regenerate the tilemap data if needed
|
||||
if (tile16_blockset_->atlas.modified()) {
|
||||
core::Renderer::Get().UpdateBitmap(&tile16_blockset_->atlas);
|
||||
// Queue texture update via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, &tile16_blockset_->atlas);
|
||||
}
|
||||
|
||||
// Update individual cached tiles
|
||||
@@ -1857,7 +1892,9 @@ absl::Status Tile16Editor::CommitChangesToOverworld() {
|
||||
}
|
||||
|
||||
tile16_blockset_->atlas.set_modified(true);
|
||||
core::Renderer::Get().UpdateBitmap(&tile16_blockset_->atlas);
|
||||
// Queue texture update via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, &tile16_blockset_->atlas);
|
||||
}
|
||||
|
||||
// Step 4: Notify the parent editor (overworld editor) to regenerate its blockset
|
||||
@@ -2073,7 +2110,9 @@ absl::Status Tile16Editor::UpdateTile8Palette(int tile8_id) {
|
||||
// }
|
||||
|
||||
current_gfx_individual_[tile8_id].set_modified(true);
|
||||
Renderer::Get().UpdateBitmap(¤t_gfx_individual_[tile8_id]);
|
||||
// Queue texture update via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, ¤t_gfx_individual_[tile8_id]);
|
||||
|
||||
util::logf("Updated tile8 %d with palette slot %d (palette size: %zu colors)",
|
||||
tile8_id, current_palette_, display_palette.size());
|
||||
@@ -2125,7 +2164,9 @@ absl::Status Tile16Editor::RefreshAllPalettes() {
|
||||
// Apply the complete 256-color palette to the source bitmap (same as overworld)
|
||||
current_gfx_bmp_.SetPalette(display_palette);
|
||||
current_gfx_bmp_.set_modified(true);
|
||||
core::Renderer::Get().UpdateBitmap(¤t_gfx_bmp_);
|
||||
// Queue texture update via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, ¤t_gfx_bmp_);
|
||||
util::logf(
|
||||
"Applied complete 256-color palette to source bitmap (same as "
|
||||
"overworld)");
|
||||
@@ -2136,7 +2177,9 @@ absl::Status Tile16Editor::RefreshAllPalettes() {
|
||||
// Use complete 256-color palette (same as overworld system)
|
||||
current_tile16_bmp_.SetPalette(display_palette);
|
||||
current_tile16_bmp_.set_modified(true);
|
||||
core::Renderer::Get().UpdateBitmap(¤t_tile16_bmp_);
|
||||
// Queue texture update via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, ¤t_tile16_bmp_);
|
||||
}
|
||||
|
||||
// Update all individual tile8 graphics with complete 256-color palette
|
||||
@@ -2146,7 +2189,9 @@ absl::Status Tile16Editor::RefreshAllPalettes() {
|
||||
// The pixel data already contains correct color indices for the 256-color palette
|
||||
current_gfx_individual_[i].SetPalette(display_palette);
|
||||
current_gfx_individual_[i].set_modified(true);
|
||||
core::Renderer::Get().UpdateBitmap(¤t_gfx_individual_[i]);
|
||||
// Queue texture update via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, ¤t_gfx_individual_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user