Tile16 Editor updates (big commit)

This commit is contained in:
scawful
2024-01-23 22:37:23 -05:00
parent da06f46596
commit c3e616e60f
10 changed files with 213 additions and 137 deletions

View File

@@ -15,6 +15,8 @@
#include "app/gui/icons.h"
#include "app/gui/input.h"
#include "app/gui/pipeline.h"
#include "app/gui/style.h"
#include "app/gui/widgets.h"
#include "app/rom.h"
#include "app/zelda3/overworld.h"
@@ -36,17 +38,10 @@ using ImGui::TableNextRow;
using ImGui::TableSetupColumn;
absl::Status Tile16Editor::Update() {
// Create a tab for Tile16 Editing
static bool start_task = false;
if (ImGui::Button("Test")) {
start_task = true;
if (rom()->is_loaded() && !map_blockset_loaded_) {
RETURN_IF_ERROR(LoadTile8());
}
if (start_task && !map_blockset_loaded_) {
LoadTile8();
}
// Create a tab bar for Tile16 Editing and Tile16 Transfer
if (BeginTabBar("Tile16 Editor Tabs")) {
if (BeginTabItem("Tile16 Editing")) {
if (BeginTable("#Tile16EditorTable", 2, TABLE_BORDERS_RESIZABLE,
@@ -69,7 +64,6 @@ absl::Status Tile16Editor::Update() {
ImGui::EndTabItem();
}
// Create a tab for Tile16 Transfer
if (BeginTabItem("Tile16 Transfer")) {
if (BeginTable("#Tile16TransferTable", 2, TABLE_BORDERS_RESIZABLE,
ImVec2(0, 0))) {
@@ -99,16 +93,26 @@ absl::Status Tile16Editor::Update() {
}
absl::Status Tile16Editor::UpdateBlockset() {
gui::BitmapCanvasPipeline(blockset_canvas_, tile16_blockset_bmp_, 0x100,
(8192 * 2), 0x20, map_blockset_loaded_, true, 55);
gui::BeginPadding(2);
gui::BeginChildWithScrollbar(55);
blockset_canvas_.DrawBackground();
gui::EndPadding();
blockset_canvas_.DrawContextMenu();
blockset_canvas_.DrawTileSelector(32);
blockset_canvas_.DrawBitmap(tile16_blockset_bmp_, 0, map_blockset_loaded_);
blockset_canvas_.DrawGrid();
blockset_canvas_.DrawOverlay();
ImGui::EndChild();
if (!blockset_canvas_.points().empty()) {
uint16_t x = blockset_canvas_.points().front().x / 32;
uint16_t y = blockset_canvas_.points().front().y / 32;
notify_tile16.mutable_get() = x + (y * 8);
// notify_tile16.mutable_get() = x + (y * 8);
notify_tile16.mutable_get() = blockset_canvas_.GetTileIdFromMousePos();
notify_tile16.apply_changes();
if (notify_tile16.modified()) {
current_tile16_ = notify_tile16.get();
current_tile16_bmp_ = tile16_individual_[notify_tile16];
current_tile16_bmp_.ApplyPalette(
rom()->palette_group("ow_main")[current_palette_]);
@@ -119,33 +123,80 @@ absl::Status Tile16Editor::UpdateBlockset() {
return absl::OkStatus();
}
absl::Status Tile16Editor::DrawToCurrentTile16(ImVec2 click_position) {
// Calculate the tile position relative to the current active map
constexpr int tile_size = 8; // Tile size is 16x16 pixels
// Calculate the tile index for x and y based on the click_position
int tile_index_x = (static_cast<int>(click_position.x) % 64) / tile_size;
int tile_index_y = (static_cast<int>(click_position.y) % 64) / tile_size;
// Calculate the pixel start position based on tile index and tile size
ImVec2 start_position;
start_position.x = tile_index_x * tile_size;
start_position.y = tile_index_y * tile_size;
// Update the bitmap's pixel data based on the start_position and tile_data
for (int y = 0; y < tile_size; ++y) {
for (int x = 0; x < tile_size; ++x) {
int pixel_index = (start_position.y + y) * current_tile16_bmp_.width() +
(start_position.x + x);
current_tile16_bmp_.WriteToPixel(
pixel_index,
current_gfx_individual_[current_tile8_].data()[y * tile_size + x]);
}
}
}
absl::Status Tile16Editor::UpdateTile16Edit() {
if (ImGui::BeginChild("Tile8 Selector",
ImVec2(ImGui::GetContentRegionAvail().x, 0x100),
ImVec2(ImGui::GetContentRegionAvail().x, 0x120),
true)) {
tile8_source_canvas_.DrawBackground(
ImVec2(core::kTilesheetWidth * 2, core::kTilesheetHeight * 0x10 * 2));
tile8_source_canvas_.DrawContextMenu();
tile8_source_canvas_.DrawTileSelector(16);
if (tile8_source_canvas_.DrawTileSelector(16)) {
current_gfx_individual_[current_tile8_].ApplyPaletteWithTransparent(
rom()->palette_group("ow_main")[0], current_palette_);
rom()->UpdateBitmap(&current_gfx_individual_[current_tile8_]);
}
tile8_source_canvas_.DrawBitmap(current_gfx_bmp_, 0, 0, 2.0f);
tile8_source_canvas_.DrawGrid(16.0f);
tile8_source_canvas_.DrawOverlay();
}
ImGui::EndChild();
if (!tile8_source_canvas_.points().empty()) {
uint16_t x = tile8_source_canvas_.points().front().x / 16;
uint16_t y = tile8_source_canvas_.points().front().y / 16;
current_tile8_ = x + (y * 8);
current_gfx_individual_[current_tile8_].ApplyPaletteWithTransparent(
rom()->palette_group("ow_main")[0], current_palette_);
rom()->UpdateBitmap(&current_gfx_individual_[current_tile8_]);
}
ImGui::Text("Tile16 ID: %d", current_tile16_);
ImGui::Text("Tile8 ID: %d", current_tile8_);
// static gui::BitmapViewer bitmap_viewer_;
// bitmap_viewer_.Display(current_gfx_individual_, 4.0f);
MemoryEditor memory_editor;
memory_editor.DrawWindow("Tile8 Data", tile8_gfx_data_.data(),
tile8_gfx_data_.size(), 0x0000);
if (ImGui::BeginChild("Tile16 Editor Options",
ImVec2(ImGui::GetContentRegionAvail().x, 0x50), true)) {
tile16_edit_canvas_.DrawBackground(ImVec2(0x40, 0x40));
tile16_edit_canvas_.DrawContextMenu();
// if (current_tile8_bmp_.modified()) {
// rom()->UpdateBitmap(&current_tile8_bmp_);
// current_tile8_bmp_.set_modified(false);
// }
tile16_edit_canvas_.DrawBitmap(current_tile16_bmp_, 0, 0, 4.0f);
tile16_edit_canvas_.HandleTileEdits(
tile8_source_canvas_, current_gfx_individual_, current_tile8_bmp_,
current_tile8_, 4.0f);
if (!tile8_source_canvas_.points().empty()) {
if (tile16_edit_canvas_.DrawTilePainter(
current_gfx_individual_[current_tile8_], 32, 4.0f)) {
DrawToCurrentTile16(tile16_edit_canvas_.drawn_tile_position());
rom()->UpdateBitmap(&current_gfx_individual_[current_tile8_]);
}
}
tile16_edit_canvas_.DrawGrid(128.0f);
tile16_edit_canvas_.DrawOverlay();
}
@@ -161,11 +212,12 @@ void Tile16Editor::DrawTileEditControls() {
gui::InputHexByte("Palette", &notify_palette.mutable_get());
notify_palette.apply_changes();
if (notify_palette.modified()) {
current_gfx_bmp_.ApplyPalette(
rom()->palette_group("ow_main")[notify_palette.get()]);
current_tile16_bmp_.ApplyPalette(
rom()->palette_group("ow_main")[notify_palette.get()]);
current_gfx_bmp_.ApplyPaletteWithTransparent(
rom()->palette_group("ow_main")[0], notify_palette.get());
current_tile16_bmp_.ApplyPaletteWithTransparent(
rom()->palette_group("ow_main")[0], notify_palette.get());
rom()->UpdateBitmap(&current_gfx_bmp_);
rom()->UpdateBitmap(&current_tile16_bmp_);
}
ImGui::Checkbox("X Flip", &x_flip);
@@ -220,76 +272,64 @@ absl::Status Tile16Editor::InitBlockset(
tile16_blockset_bmp_ = tile16_blockset_bmp;
tile16_individual_ = tile16_individual;
current_gfx_bmp_ = current_gfx_bmp;
tile8_gfx_data_ = current_gfx_bmp_.vector();
return absl::OkStatus();
}
absl::Status Tile16Editor::LoadTile8() {
current_gfx_individual_.reserve(128);
current_gfx_individual_.reserve(1024);
// Define the task function
std::function<void(int)> taskFunc = [&](int index) {
auto current_gfx_data = current_gfx_bmp_.mutable_data();
std::vector<uint8_t> tile_data;
tile_data.reserve(0x40);
for (int i = 0; i < 0x40; i++) {
tile_data.emplace_back(0x00);
}
// std::function<void(int)> taskFunc = [&](int index) {
for (int index = 0; index < 1024; index++) {
std::vector<uint8_t> tile_data(0x40, 0x00);
// Copy the pixel data for the current tile into the vector
for (int ty = 0; ty < 8; ty++) {
for (int tx = 0; tx < 8; tx++) {
// Current Gfx Data is 16 sheets of 8x8 tiles ordered 16 wide by 4 tall
// Calculate the position in the tile data vector
int position = tx + (ty * 0x08);
uint8_t value =
current_gfx_data[(index % 16 * 32) + (index / 16 * 32 * 0x80) +
(ty * 0x80) + tx];
// Calculate the position in the current gfx data
int num_columns = current_gfx_bmp_.width() / 8;
int num_rows = current_gfx_bmp_.height() / 8;
int x = (index % num_columns) * 8 + tx;
int y = (index / num_columns) * 8 + ty;
int gfx_position = x + (y * 0x100);
// Get the pixel value from the current gfx data
uint8_t value = tile8_gfx_data_[gfx_position];
if (value & 0x80) {
value -= 0x88;
}
tile_data[position] = value;
}
}
current_gfx_individual_.emplace_back();
current_gfx_individual_[index].Create(0x08, 0x08, 0x80, tile_data);
current_gfx_individual_[index].ApplyPalette(
rom()->palette_group("ow_main")[current_palette_]);
current_gfx_individual_[index].ApplyPaletteWithTransparent(
rom()->palette_group("ow_main")[0], current_palette_);
rom()->RenderBitmap(&current_gfx_individual_[index]);
};
// Create the task manager
static bool started = false;
if (!started) {
task_manager_ = TaskManager<std::function<void(int)>>(127, 1);
started = true;
}
task_manager_.ExecuteTasks(taskFunc);
// };
if (task_manager_.IsTaskComplete()) {
// All tasks are complete
current_tile8_bmp_ = current_gfx_individual_[0];
map_blockset_loaded_ = true;
}
// auto current_gfx_data = current_gfx_bmp_.mutable_data();
// for (int i = 0; i < 128; i++) {
// std::vector<uint8_t> tile_data(0x40, 0x00);
// Copy the pixel data for the current tile into the vector
// for (int ty = 0; ty < 8; ty++) {
// for (int tx = 0; tx < 8; tx++) {
// int position = tx + (ty * 0x10);
// uint8_t value = current_gfx_data[(i % 16 * 32) + (i / 16 * 32 * 0x80)
// +
// (ty * 0x80) + tx];
// tile_data[position] = value;
// }
// }
// current_gfx_individual_data_.emplace_back(tile_data);
// current_gfx_individual_.emplace_back();
// current_gfx_individual_[i].Create(0x08, 0x08, 0x80, tile_data);
// current_gfx_individual_[i].ApplyPalette(
// rom()->palette_group("ow_main")[current_palette_]);
// rom()->RenderBitmap(&current_gfx_individual_[i]);
// // Create the task manager
// static bool started = false;
// if (!started) {
// task_manager_ = TaskManager<std::function<void(int)>>(1024, 60);
// started = true;
// }
// task_manager_.ExecuteTasks(taskFunc);
// if (task_manager_.IsTaskComplete()) {
// // All tasks are complete
map_blockset_loaded_ = true;
// }
return absl::OkStatus();
}

View File

@@ -8,13 +8,13 @@
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "app/core/editor.h"
#include "app/gui/pipeline.h"
#include "app/editor/modules/palette_editor.h"
#include "app/gfx/bitmap.h"
#include "app/gfx/snes_palette.h"
#include "app/gfx/snes_tile.h"
#include "app/gui/canvas.h"
#include "app/gui/icons.h"
#include "app/gui/pipeline.h"
#include "app/rom.h"
#include "app/zelda3/overworld.h"
@@ -27,6 +27,9 @@ class Tile16Editor : public SharedROM {
absl::Status Update();
absl::Status UpdateBlockset();
absl::Status DrawToCurrentTile16(ImVec2 pos);
absl::Status UpdateTile16Edit();
void DrawTileEditControls();
@@ -39,6 +42,14 @@ class Tile16Editor : public SharedROM {
absl::Status LoadTile8();
auto set_tile16(int id) {
current_tile16_ = id;
current_tile16_bmp_ = tile16_individual_[id];
current_tile16_bmp_.ApplyPalette(
rom()->palette_group("ow_main")[current_palette_]);
rom()->RenderBitmap(&current_tile16_bmp_);
}
private:
bool map_blockset_loaded_ = false;
bool transfer_started_ = false;
@@ -48,7 +59,7 @@ class Tile16Editor : public SharedROM {
int current_tile8_ = 0;
uint8_t current_palette_ = 0;
core::NotifyValue<uint8_t> notify_tile16;
core::NotifyValue<uint32_t> notify_tile16;
core::NotifyValue<uint8_t> notify_palette;
// Canvas dimensions
@@ -65,7 +76,8 @@ class Tile16Editor : public SharedROM {
int tile_size;
// Tile16 blockset for selecting the tile to edit
gui::Canvas blockset_canvas_;
gui::Canvas blockset_canvas_{ImVec2(0x100, 0x4000),
gui::CanvasGridSize::k32x32};
gfx::Bitmap tile16_blockset_bmp_;
// Canvas for editing the selected tile
@@ -88,6 +100,8 @@ class Tile16Editor : public SharedROM {
std::vector<uint8_t> current_tile16_data_;
std::vector<uint8_t> tile8_gfx_data_;
PaletteEditor palette_editor_;
gfx::SNESPalette palette_;

View File

@@ -185,7 +185,6 @@ void OverworldEditor::DrawUsageGrid() {
absl::Status OverworldEditor::DrawToolset() {
static bool show_gfx_group = false;
static bool show_tile16 = false;
static bool show_properties = false;
if (BeginTable("OWToolset", 20, kToolsetTableFlags, ImVec2(0, 0))) {
@@ -260,7 +259,7 @@ absl::Status OverworldEditor::DrawToolset() {
TableNextColumn();
if (ImGui::Button(ICON_MD_GRID_VIEW)) {
show_tile16 = !show_tile16;
show_tile16_editor_ = !show_tile16_editor_;
}
TableNextColumn();
@@ -288,9 +287,9 @@ absl::Status OverworldEditor::DrawToolset() {
RETURN_IF_ERROR(DrawExperimentalModal())
}
if (show_tile16) {
if (show_tile16_editor_) {
// Create a table in ImGui for the Tile16 Editor
ImGui::Begin("Tile16 Editor", &show_tile16);
ImGui::Begin("Tile16 Editor", &show_tile16_editor_);
RETURN_IF_ERROR(tile16_editor_.Update())
ImGui::End();
}
@@ -537,7 +536,7 @@ void DrawExitEditorPopup(zelda3::OverworldExit &exit) {
void OverworldEditor::DrawOverworldExits(ImVec2 canvas_p0, ImVec2 scrolling) {
int i = 0;
for (auto &each : overworld_.Exits()) {
for (auto &each : *overworld_.exits()) {
if (each.map_id_ < 0x40 + (current_world_ * 0x40) &&
each.map_id_ >= (current_world_ * 0x40)) {
ow_map_canvas_.DrawRect(each.x_, each.y_, 16, 16,
@@ -781,7 +780,15 @@ void OverworldEditor::DrawTile16Selector() {
blockset_canvas_.DrawContextMenu();
blockset_canvas_.DrawBitmap(tile16_blockset_bmp_, /*border_offset=*/2,
map_blockset_loaded_);
blockset_canvas_.DrawTileSelector(32.0f);
if (blockset_canvas_.DrawTileSelector(32.0f)) {
// Open the tile16 editor to the tile
auto tile_pos = blockset_canvas_.points().front();
int grid_x = static_cast<int>(tile_pos.x / 32);
int grid_y = static_cast<int>(tile_pos.y / 32);
int id = grid_x + grid_y * 8;
tile16_editor_.set_tile16(id);
show_tile16_editor_ = true;
}
blockset_canvas_.DrawGrid();
blockset_canvas_.DrawOverlay();
ImGui::EndChild();
@@ -865,7 +872,7 @@ absl::Status OverworldEditor::LoadGraphics() {
current_gfx_bmp_, palette_);
// Create the tile16 blockset image
gui::BuildAndRenderBitmapPipeline(0x80, 0x2000, 0x80,
gui::BuildAndRenderBitmapPipeline(0x80, 0x2000, 0x08,
overworld_.Tile16Blockset(), *rom(),
tile16_blockset_bmp_, palette_);
map_blockset_loaded_ = true;