Implement critical palette synchronization fixes in Tile16Editor and OverworldEditor
- Updated Tile16Editor to ensure consistent palette application across all graphics, aligning with the overworld palette for accurate color representation. - Added functionality to immediately apply palette changes in Tile16Editor, enhancing visual consistency during editing. - Implemented critical fixes to refresh all graphics with the correct overworld palette, improving user experience and reducing discrepancies in tile appearance. - Enhanced logging for palette updates to facilitate debugging and provide user feedback on changes.
This commit is contained in:
@@ -143,6 +143,10 @@ absl::Status OverworldEditor::Load() {
|
|||||||
RETURN_IF_ERROR(
|
RETURN_IF_ERROR(
|
||||||
tile16_editor_.Initialize(tile16_blockset_bmp_, current_gfx_bmp_,
|
tile16_editor_.Initialize(tile16_blockset_bmp_, current_gfx_bmp_,
|
||||||
*overworld_.mutable_all_tiles_types()));
|
*overworld_.mutable_all_tiles_types()));
|
||||||
|
|
||||||
|
// CRITICAL FIX: Initialize tile16 editor with the correct overworld palette
|
||||||
|
tile16_editor_.set_palette(palette_);
|
||||||
|
tile16_editor_.set_rom(rom_);
|
||||||
|
|
||||||
// Set up callback for when tile16 changes are committed
|
// Set up callback for when tile16 changes are committed
|
||||||
tile16_editor_.set_on_changes_committed([this]() -> absl::Status {
|
tile16_editor_.set_on_changes_committed([this]() -> absl::Status {
|
||||||
|
|||||||
@@ -31,10 +31,10 @@ absl::Status Tile16Editor::Initialize(
|
|||||||
std::array<uint8_t, 0x200>& all_tiles_types) {
|
std::array<uint8_t, 0x200>& all_tiles_types) {
|
||||||
all_tiles_types_ = all_tiles_types;
|
all_tiles_types_ = all_tiles_types;
|
||||||
|
|
||||||
// Copy the graphics bitmap
|
// Copy the graphics bitmap (palette will be set later by overworld editor)
|
||||||
current_gfx_bmp_.Create(current_gfx_bmp.width(), current_gfx_bmp.height(),
|
current_gfx_bmp_.Create(current_gfx_bmp.width(), current_gfx_bmp.height(),
|
||||||
current_gfx_bmp.depth(), current_gfx_bmp.vector());
|
current_gfx_bmp.depth(), current_gfx_bmp.vector());
|
||||||
current_gfx_bmp_.SetPalette(current_gfx_bmp.palette());
|
current_gfx_bmp_.SetPalette(current_gfx_bmp.palette()); // Temporary palette
|
||||||
core::Renderer::Get().RenderBitmap(¤t_gfx_bmp_);
|
core::Renderer::Get().RenderBitmap(¤t_gfx_bmp_);
|
||||||
|
|
||||||
// Copy the tile16 blockset bitmap
|
// Copy the tile16 blockset bitmap
|
||||||
@@ -967,6 +967,7 @@ absl::Status Tile16Editor::LoadTile8() {
|
|||||||
"Current graphics bitmap not initialized");
|
"Current graphics bitmap not initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CRITICAL FIX: Use the same palette system as the overworld
|
||||||
const auto& ow_main_pal_group = rom()->palette_group().overworld_main;
|
const auto& ow_main_pal_group = rom()->palette_group().overworld_main;
|
||||||
if (ow_main_pal_group.size() == 0) {
|
if (ow_main_pal_group.size() == 0) {
|
||||||
return absl::FailedPreconditionError("Overworld palette group not loaded");
|
return absl::FailedPreconditionError("Overworld palette group not loaded");
|
||||||
@@ -1088,11 +1089,11 @@ absl::Status Tile16Editor::SetCurrentTile(int tile_id) {
|
|||||||
// Create the bitmap with the extracted data
|
// Create the bitmap with the extracted data
|
||||||
current_tile16_bmp_.Create(kTile16Size, kTile16Size, 8, tile_data);
|
current_tile16_bmp_.Create(kTile16Size, kTile16Size, 8, tile_data);
|
||||||
|
|
||||||
// Set the correct palette - tile16 should have independent palette
|
// CRITICAL FIX: Use the same complete palette that the overworld uses
|
||||||
const auto& ow_main_pal_group = rom()->palette_group().overworld_main;
|
// This ensures tile16 editor colors match the overworld exactly
|
||||||
if (ow_main_pal_group.size() > 0) {
|
auto overworld_palette = rom()->palette_group().overworld_main[0]; // Get the current overworld palette
|
||||||
// Use SetPalette instead of SetPaletteWithTransparent for tile16
|
if (overworld_palette.size() > 0) {
|
||||||
current_tile16_bmp_.SetPalette(ow_main_pal_group[0]);
|
current_tile16_bmp_.SetPalette(overworld_palette);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the bitmap
|
// Render the bitmap
|
||||||
@@ -1339,25 +1340,29 @@ absl::Status Tile16Editor::CyclePalette(bool forward) {
|
|||||||
|
|
||||||
current_palette_ = new_palette;
|
current_palette_ = new_palette;
|
||||||
|
|
||||||
// Update all graphics with new palette
|
// CRITICAL FIX: Use the same palette coordination as the overworld
|
||||||
|
// The palette selection should affect how tiles appear in the tile16 editor
|
||||||
const auto& ow_main_pal_group = rom()->palette_group().overworld_main;
|
const auto& ow_main_pal_group = rom()->palette_group().overworld_main;
|
||||||
if (ow_main_pal_group.size() > current_palette_) {
|
if (ow_main_pal_group.size() > 0) {
|
||||||
current_gfx_bmp_.SetPaletteWithTransparent(ow_main_pal_group[0],
|
// Use the main overworld palette but apply the selected palette index
|
||||||
current_palette_);
|
auto main_palette = ow_main_pal_group[0];
|
||||||
current_tile16_bmp_.SetPaletteWithTransparent(ow_main_pal_group[0],
|
|
||||||
current_palette_);
|
// Apply the selected palette to all graphics consistently
|
||||||
|
current_gfx_bmp_.SetPaletteWithTransparent(main_palette, current_palette_);
|
||||||
|
current_tile16_bmp_.SetPaletteWithTransparent(main_palette, current_palette_);
|
||||||
|
|
||||||
// Update individual tile8 graphics
|
// Update individual tile8 graphics with the same palette coordination
|
||||||
for (auto& tile_gfx : current_gfx_individual_) {
|
for (auto& tile_gfx : current_gfx_individual_) {
|
||||||
if (tile_gfx.is_active()) {
|
if (tile_gfx.is_active()) {
|
||||||
tile_gfx.SetPaletteWithTransparent(ow_main_pal_group[0],
|
tile_gfx.SetPaletteWithTransparent(main_palette, current_palette_);
|
||||||
current_palette_);
|
|
||||||
core::Renderer::Get().UpdateBitmap(&tile_gfx);
|
core::Renderer::Get().UpdateBitmap(&tile_gfx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
core::Renderer::Get().UpdateBitmap(¤t_gfx_bmp_);
|
core::Renderer::Get().UpdateBitmap(¤t_gfx_bmp_);
|
||||||
core::Renderer::Get().UpdateBitmap(¤t_tile16_bmp_);
|
core::Renderer::Get().UpdateBitmap(¤t_tile16_bmp_);
|
||||||
|
|
||||||
|
util::logf("Updated all tile16 editor graphics to use palette %d", current_palette_);
|
||||||
}
|
}
|
||||||
|
|
||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
@@ -1635,50 +1640,18 @@ absl::Status Tile16Editor::UpdateTile8Palette(int tile8_id) {
|
|||||||
return absl::OkStatus(); // Skip inactive tiles
|
return absl::OkStatus(); // Skip inactive tiles
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the appropriate palette group
|
// CRITICAL FIX: Always use the overworld main palette for consistency
|
||||||
|
// This ensures all tile8 graphics match the overworld colors exactly
|
||||||
const auto& palette_groups = rom()->palette_group();
|
const auto& palette_groups = rom()->palette_group();
|
||||||
gfx::SnesPalette target_palette;
|
gfx::SnesPalette target_palette = palette_groups.overworld_main[0];
|
||||||
|
|
||||||
switch (current_palette_group_) {
|
|
||||||
case 0:
|
|
||||||
target_palette = palette_groups.overworld_main[0];
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
target_palette = palette_groups.overworld_aux[0];
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
target_palette = palette_groups.overworld_animated[0];
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
target_palette = palette_groups.dungeon_main[0];
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
target_palette = palette_groups.global_sprites[0];
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
target_palette = palette_groups.armors[0];
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
target_palette = palette_groups.swords[0];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
target_palette = palette_groups.overworld_main[0];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate which graphics sheet this tile belongs to
|
// Calculate which graphics sheet this tile belongs to
|
||||||
const int tiles_per_row = current_gfx_bmp_.width() / 8; // Usually 16
|
const int tiles_per_row = current_gfx_bmp_.width() / 8; // Usually 16
|
||||||
const int sheet_index = tile8_id / (tiles_per_row * 8); // 8 rows per sheet
|
const int sheet_index = tile8_id / (tiles_per_row * 8); // 8 rows per sheet
|
||||||
|
|
||||||
// For certain sheets (like sheet 0 - trees), use SetPalette instead of SetPaletteWithTransparent
|
// CRITICAL FIX: Use consistent palette application for all tile8 graphics
|
||||||
if (sheet_index == 0 || current_palette_group_ >= 3) {
|
// Apply the current palette selection to match overworld appearance
|
||||||
// Trees sheet and sprite sheets work better with direct palette
|
current_gfx_individual_[tile8_id].SetPaletteWithTransparent(target_palette, current_palette_);
|
||||||
current_gfx_individual_[tile8_id].SetPalette(target_palette);
|
|
||||||
} else {
|
|
||||||
// Other sheets use the transparent palette system
|
|
||||||
current_gfx_individual_[tile8_id].SetPaletteWithTransparent(
|
|
||||||
target_palette, current_palette_);
|
|
||||||
}
|
|
||||||
|
|
||||||
Renderer::Get().UpdateBitmap(¤t_gfx_individual_[tile8_id]);
|
Renderer::Get().UpdateBitmap(¤t_gfx_individual_[tile8_id]);
|
||||||
|
|
||||||
@@ -1686,25 +1659,34 @@ absl::Status Tile16Editor::UpdateTile8Palette(int tile8_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
absl::Status Tile16Editor::RefreshAllPalettes() {
|
absl::Status Tile16Editor::RefreshAllPalettes() {
|
||||||
|
// CRITICAL FIX: Ensure all graphics use the same palette coordination as overworld
|
||||||
|
if (!rom_) {
|
||||||
|
return absl::FailedPreconditionError("ROM not set");
|
||||||
|
}
|
||||||
|
|
||||||
const auto& palette_groups = rom()->palette_group();
|
const auto& palette_groups = rom()->palette_group();
|
||||||
|
auto main_palette = palette_groups.overworld_main[0];
|
||||||
|
|
||||||
// Update tile8 graphics
|
// CRITICAL FIX: Update tile8 source graphics display with forced texture update
|
||||||
current_gfx_bmp_.SetPaletteWithTransparent(palette_groups.overworld_main[0],
|
current_gfx_bmp_.SetPaletteWithTransparent(main_palette, current_palette_);
|
||||||
current_palette_);
|
current_gfx_bmp_.set_modified(true); // Force update
|
||||||
Renderer::Get().UpdateBitmap(¤t_gfx_bmp_);
|
Renderer::Get().UpdateBitmap(¤t_gfx_bmp_);
|
||||||
|
|
||||||
// Update current tile16
|
// Update current tile16 being edited
|
||||||
current_tile16_bmp_.SetPaletteWithTransparent(
|
current_tile16_bmp_.SetPaletteWithTransparent(main_palette, current_palette_);
|
||||||
palette_groups.overworld_main[0], current_palette_);
|
current_tile16_bmp_.set_modified(true); // Force update
|
||||||
Renderer::Get().UpdateBitmap(¤t_tile16_bmp_);
|
Renderer::Get().UpdateBitmap(¤t_tile16_bmp_);
|
||||||
|
|
||||||
// Update all individual tile8 graphics
|
// Update all individual tile8 graphics to use the same palette
|
||||||
for (size_t i = 0; i < current_gfx_individual_.size(); ++i) {
|
for (size_t i = 0; i < current_gfx_individual_.size(); ++i) {
|
||||||
if (current_gfx_individual_[i].is_active()) {
|
if (current_gfx_individual_[i].is_active()) {
|
||||||
RETURN_IF_ERROR(UpdateTile8Palette(static_cast<int>(i)));
|
current_gfx_individual_[i].SetPaletteWithTransparent(main_palette, current_palette_);
|
||||||
|
current_gfx_individual_[i].set_modified(true); // Force update
|
||||||
|
Renderer::Get().UpdateBitmap(¤t_gfx_individual_[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
util::logf("Refreshed all palettes in tile16 editor to use overworld palette %d", current_palette_);
|
||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "app/gfx/snes_tile.h"
|
#include "app/gfx/snes_tile.h"
|
||||||
#include "app/gui/canvas.h"
|
#include "app/gui/canvas.h"
|
||||||
#include "app/gui/input.h"
|
#include "app/gui/input.h"
|
||||||
|
#include "util/log.h"
|
||||||
#include "app/rom.h"
|
#include "app/rom.h"
|
||||||
#include "app/zelda3/overworld/overworld.h"
|
#include "app/zelda3/overworld/overworld.h"
|
||||||
#include "imgui/imgui.h"
|
#include "imgui/imgui.h"
|
||||||
@@ -125,6 +126,18 @@ class Tile16Editor : public gfx::GfxContext {
|
|||||||
void set_rom(Rom* rom) { rom_ = rom; }
|
void set_rom(Rom* rom) { rom_ = rom; }
|
||||||
Rom* rom() const { return rom_; }
|
Rom* rom() const { return rom_; }
|
||||||
|
|
||||||
|
// Set the palette from overworld to ensure color consistency
|
||||||
|
void set_palette(const gfx::SnesPalette& palette) {
|
||||||
|
palette_ = palette;
|
||||||
|
// Apply to all graphics immediately
|
||||||
|
if (rom_) {
|
||||||
|
auto status = RefreshAllPalettes();
|
||||||
|
if (!status.ok()) {
|
||||||
|
util::logf("Failed to refresh palettes: %s", status.message().data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Callback for when changes are committed to notify parent editor
|
// Callback for when changes are committed to notify parent editor
|
||||||
void set_on_changes_committed(std::function<absl::Status()> callback) {
|
void set_on_changes_committed(std::function<absl::Status()> callback) {
|
||||||
on_changes_committed_ = callback;
|
on_changes_committed_ = callback;
|
||||||
|
|||||||
Reference in New Issue
Block a user