backend-infra-engineer: Pre-0.2.2 2024 Q1 snapshot
This commit is contained in:
@@ -4,8 +4,6 @@
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#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"
|
||||
@@ -15,20 +13,13 @@
|
||||
#include "app/gui/canvas.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/rom.h"
|
||||
#include "app/zelda3/overworld.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
absl::Status GfxContext::Update() { return absl::OkStatus(); }
|
||||
|
||||
gfx::Bitmap GfxContext::current_ow_gfx_bmp_;
|
||||
gfx::SNESPalette GfxContext::current_ow_palette_;
|
||||
gfx::Bitmap GfxContext::tile16_blockset_bmp_;
|
||||
gfx::Bitmap GfxContext::tile8_blockset_bmp_;
|
||||
std::vector<gfx::Bitmap> GfxContext::tile16_individual_bmp_;
|
||||
std::vector<gfx::Bitmap> GfxContext::tile8_individual_bmp_;
|
||||
std::unordered_map<uint8_t, gfx::Paletteset> GfxContext::palettesets_;
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
|
||||
@@ -6,24 +6,15 @@
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
#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"
|
||||
|
||||
// Create a class which manages the current VRAM state of Link to the Past,
|
||||
// including static members for the Bitmaps and Palettes as well as the current
|
||||
// blockset as to update all of the overworld maps with the new blockset when it
|
||||
// is changed. This class will also manage the current tile16 and tile8
|
||||
// selection, as well as the current palette selection.
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
@@ -34,19 +25,8 @@ class GfxContext {
|
||||
absl::Status Update();
|
||||
|
||||
protected:
|
||||
static gfx::Bitmap current_ow_gfx_bmp_;
|
||||
|
||||
static gfx::SNESPalette current_ow_palette_;
|
||||
|
||||
static gfx::Bitmap tile16_blockset_bmp_;
|
||||
|
||||
static gfx::Bitmap tile8_blockset_bmp_;
|
||||
|
||||
// Bitmaps for the tile16 individual tiles
|
||||
static std::vector<gfx::Bitmap> tile16_individual_bmp_;
|
||||
|
||||
// Bitmaps for the tile8 individual tiles
|
||||
static std::vector<gfx::Bitmap> tile8_individual_bmp_;
|
||||
// Palettesets for the tile16 individual tiles
|
||||
static std::unordered_map<uint8_t, gfx::Paletteset> palettesets_;
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <imgui/imgui.h>
|
||||
|
||||
#include "app/core/common.h"
|
||||
#include "app/core/labeling.h"
|
||||
#include "app/gfx/snes_palette.h"
|
||||
#include "app/gui/canvas.h"
|
||||
#include "app/gui/icons.h"
|
||||
@@ -28,38 +29,126 @@ using ImGui::TableNextRow;
|
||||
using ImGui::TableSetupColumn;
|
||||
|
||||
absl::Status DungeonEditor::Update() {
|
||||
if (!is_loaded_ && rom()->isLoaded()) {
|
||||
for (int i = 0; i < 0x100; i++) {
|
||||
if (!is_loaded_ && rom()->is_loaded()) {
|
||||
for (int i = 0; i < 0x100 + 40; i++) {
|
||||
rooms_.emplace_back(zelda3::dungeon::Room(i));
|
||||
rooms_[i].LoadHeader();
|
||||
rooms_[i].LoadRoomFromROM();
|
||||
if (flags()->kDrawDungeonRoomGraphics) {
|
||||
rooms_[i].LoadRoomGraphics();
|
||||
}
|
||||
|
||||
room_size_pointers_.push_back(rooms_[i].room_size_ptr());
|
||||
if (rooms_[i].room_size_ptr() != 0x0A8000) {
|
||||
room_size_addresses_[i] = rooms_[i].room_size_ptr();
|
||||
}
|
||||
|
||||
auto dungeon_palette_ptr = rom()->paletteset_ids[rooms_[i].palette][0];
|
||||
ASSIGN_OR_RETURN(auto palette_id,
|
||||
rom()->ReadWord(0xDEC4B + dungeon_palette_ptr));
|
||||
int p_id = palette_id / 180;
|
||||
auto color = rom()->palette_group("dungeon_main")[p_id][3];
|
||||
|
||||
room_palette_[rooms_[i].palette] = color.rgb();
|
||||
}
|
||||
graphics_bin_ = rom()->graphics_bin();
|
||||
|
||||
LoadDungeonRoomSize();
|
||||
LoadRoomEntrances();
|
||||
|
||||
// Load the palette group and palette for the dungeon
|
||||
full_palette_ =
|
||||
rom()->palette_group("dungeon_main")[current_palette_group_id_];
|
||||
current_palette_group_ =
|
||||
gfx::CreatePaletteGroupFromLargePalette(full_palette_);
|
||||
ASSIGN_OR_RETURN(current_palette_group_,
|
||||
gfx::CreatePaletteGroupFromLargePalette(full_palette_));
|
||||
|
||||
graphics_bin_ = *rom()->mutable_bitmap_manager();
|
||||
// Create a vector of pointers to the current block bitmaps
|
||||
for (int block : rooms_[current_room_id_].blocks()) {
|
||||
room_gfx_sheets_.emplace_back(&graphics_bin_[block]);
|
||||
room_gfx_sheets_.emplace_back(graphics_bin_[block].get());
|
||||
}
|
||||
|
||||
is_loaded_ = true;
|
||||
}
|
||||
|
||||
if (refresh_graphics_) {
|
||||
for (int block : rooms_[current_room_id_].blocks()) {
|
||||
graphics_bin_[block].ApplyPalette(
|
||||
current_palette_group_[current_palette_id_]);
|
||||
rom()->UpdateBitmap(&graphics_bin_[block]);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
int block = rooms_[current_room_id_].blocks()[i];
|
||||
graphics_bin_[block].get()->ApplyPaletteWithTransparent(
|
||||
current_palette_group_[current_palette_id_], 0);
|
||||
rom()->UpdateBitmap(graphics_bin_[block].get(), true);
|
||||
}
|
||||
for (int i = 9; i < 16; i++) {
|
||||
int block = rooms_[current_room_id_].blocks()[i];
|
||||
graphics_bin_[block].get()->ApplyPaletteWithTransparent(
|
||||
rom()->palette_group("sprites_aux1")[current_palette_id_], 0);
|
||||
rom()->UpdateBitmap(graphics_bin_[block].get(), true);
|
||||
}
|
||||
|
||||
refresh_graphics_ = false;
|
||||
}
|
||||
|
||||
TAB_BAR("##DungeonEditorTabBar")
|
||||
TAB_ITEM("Room Editor")
|
||||
UpdateDungeonRoomView();
|
||||
END_TAB_ITEM()
|
||||
TAB_ITEM("Usage Statistics")
|
||||
if (is_loaded_) {
|
||||
static bool calc_stats = false;
|
||||
if (!calc_stats) {
|
||||
CalculateUsageStats();
|
||||
calc_stats = true;
|
||||
}
|
||||
DrawUsageStats();
|
||||
}
|
||||
END_TAB_ITEM()
|
||||
END_TAB_BAR()
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
void DungeonEditor::LoadDungeonRoomSize() {
|
||||
std::map<int, std::vector<int>> rooms_by_bank;
|
||||
for (const auto& room : room_size_addresses_) {
|
||||
int bank = room.second >> 16;
|
||||
rooms_by_bank[bank].push_back(room.second);
|
||||
}
|
||||
|
||||
// Process and calculate room sizes within each bank
|
||||
for (auto& bank_rooms : rooms_by_bank) {
|
||||
// Sort the rooms within this bank
|
||||
std::sort(bank_rooms.second.begin(), bank_rooms.second.end());
|
||||
|
||||
for (size_t i = 0; i < bank_rooms.second.size(); ++i) {
|
||||
int room_ptr = bank_rooms.second[i];
|
||||
|
||||
// Identify the room ID for the current room pointer
|
||||
int room_id =
|
||||
std::find_if(room_size_addresses_.begin(), room_size_addresses_.end(),
|
||||
[room_ptr](const auto& entry) {
|
||||
return entry.second == room_ptr;
|
||||
})
|
||||
->first;
|
||||
|
||||
if (room_ptr != 0x0A8000) {
|
||||
if (i < bank_rooms.second.size() - 1) {
|
||||
// Calculate size as difference between current room and next room
|
||||
// in the same bank
|
||||
rooms_[room_id].set_room_size(bank_rooms.second[i + 1] - room_ptr);
|
||||
} else {
|
||||
// Calculate size for the last room in this bank
|
||||
int bank_end_address = (bank_rooms.first << 16) | 0xFFFF;
|
||||
rooms_[room_id].set_room_size(bank_end_address - room_ptr + 1);
|
||||
}
|
||||
total_room_size_ += rooms_[room_id].room_size();
|
||||
} else {
|
||||
// Room with address 0x0A8000
|
||||
rooms_[room_id].set_room_size(0x00);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonEditor::UpdateDungeonRoomView() {
|
||||
DrawToolset();
|
||||
|
||||
if (palette_showing_) {
|
||||
@@ -81,7 +170,14 @@ absl::Status DungeonEditor::Update() {
|
||||
TableNextRow();
|
||||
|
||||
TableNextColumn();
|
||||
TAB_BAR("##DungeonRoomTabBar");
|
||||
TAB_ITEM("Rooms");
|
||||
DrawRoomSelector();
|
||||
END_TAB_ITEM();
|
||||
TAB_ITEM("Entrances");
|
||||
DrawEntranceSelector();
|
||||
END_TAB_ITEM();
|
||||
END_TAB_BAR();
|
||||
|
||||
TableNextColumn();
|
||||
DrawDungeonTabView();
|
||||
@@ -90,7 +186,6 @@ absl::Status DungeonEditor::Update() {
|
||||
DrawTileSelector();
|
||||
ImGui::EndTable();
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
void DungeonEditor::DrawToolset() {
|
||||
@@ -110,47 +205,47 @@ void DungeonEditor::DrawToolset() {
|
||||
TableSetupColumn("#doorTool");
|
||||
TableSetupColumn("#blockTool");
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
if (ImGui::Button(ICON_MD_UNDO)) {
|
||||
PRINT_IF_ERROR(Undo());
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
if (ImGui::Button(ICON_MD_REDO)) {
|
||||
PRINT_IF_ERROR(Redo());
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
ImGui::Text(ICON_MD_MORE_VERT);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
if (ImGui::RadioButton(ICON_MD_FILTER_NONE,
|
||||
background_type_ == kBackgroundAny)) {
|
||||
background_type_ = kBackgroundAny;
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
if (ImGui::RadioButton(ICON_MD_FILTER_1,
|
||||
background_type_ == kBackground1)) {
|
||||
background_type_ = kBackground1;
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
if (ImGui::RadioButton(ICON_MD_FILTER_2,
|
||||
background_type_ == kBackground2)) {
|
||||
background_type_ = kBackground2;
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
if (ImGui::RadioButton(ICON_MD_FILTER_3,
|
||||
background_type_ == kBackground3)) {
|
||||
background_type_ = kBackground3;
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
ImGui::Text(ICON_MD_MORE_VERT);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
if (ImGui::RadioButton(ICON_MD_PEST_CONTROL, placement_type_ == kSprite)) {
|
||||
placement_type_ = kSprite;
|
||||
}
|
||||
@@ -158,7 +253,7 @@ void DungeonEditor::DrawToolset() {
|
||||
ImGui::SetTooltip("Sprites");
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
if (ImGui::RadioButton(ICON_MD_GRASS, placement_type_ == kItem)) {
|
||||
placement_type_ = kItem;
|
||||
}
|
||||
@@ -166,7 +261,7 @@ void DungeonEditor::DrawToolset() {
|
||||
ImGui::SetTooltip("Items");
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
if (ImGui::RadioButton(ICON_MD_SENSOR_DOOR, placement_type_ == kDoor)) {
|
||||
placement_type_ = kDoor;
|
||||
}
|
||||
@@ -174,7 +269,7 @@ void DungeonEditor::DrawToolset() {
|
||||
ImGui::SetTooltip("Doors");
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
if (ImGui::RadioButton(ICON_MD_SQUARE, placement_type_ == kBlock)) {
|
||||
placement_type_ = kBlock;
|
||||
}
|
||||
@@ -182,7 +277,7 @@ void DungeonEditor::DrawToolset() {
|
||||
ImGui::SetTooltip("Blocks");
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
if (ImGui::Button(ICON_MD_PALETTE)) {
|
||||
palette_showing_ = !palette_showing_;
|
||||
}
|
||||
@@ -192,7 +287,7 @@ void DungeonEditor::DrawToolset() {
|
||||
}
|
||||
|
||||
void DungeonEditor::DrawRoomSelector() {
|
||||
if (rom()->isLoaded()) {
|
||||
if (rom()->is_loaded()) {
|
||||
gui::InputHexWord("Room ID", ¤t_room_id_);
|
||||
gui::InputHex("Palette ID", ¤t_palette_id_);
|
||||
|
||||
@@ -201,10 +296,15 @@ void DungeonEditor::DrawRoomSelector() {
|
||||
ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
|
||||
int i = 0;
|
||||
for (const auto each_room_name : zelda3::dungeon::kRoomNames) {
|
||||
ImGui::Selectable(each_room_name.data(), current_room_id_ == i,
|
||||
ImGuiSelectableFlags_AllowDoubleClick);
|
||||
rom()->resource_label()->SelectableLabelWithNameEdit(
|
||||
current_room_id_ == i, "Dungeon Room Names",
|
||||
core::UppercaseHexByte(i), zelda3::dungeon::kRoomNames[i].data());
|
||||
if (ImGui::IsItemClicked()) {
|
||||
active_rooms_.push_back(i);
|
||||
// TODO: Jump to tab if room is already open
|
||||
current_room_id_ = i;
|
||||
if (!active_rooms_.contains(i)) {
|
||||
active_rooms_.push_back(i);
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
@@ -213,12 +313,110 @@ void DungeonEditor::DrawRoomSelector() {
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonEditor::DrawEntranceSelector() {
|
||||
if (rom()->is_loaded()) {
|
||||
gui::InputHexWord("Entrance ID",
|
||||
&entrances_[current_entrance_id_].entrance_id_);
|
||||
|
||||
gui::InputHexWord("Room ID", &entrances_[current_entrance_id_].room_, 50.f,
|
||||
true);
|
||||
ImGui::SameLine();
|
||||
gui::InputHexByte("Dungeon ID",
|
||||
&entrances_[current_entrance_id_].dungeon_id_, 50.f,
|
||||
true);
|
||||
|
||||
gui::InputHexByte("Blockset", &entrances_[current_entrance_id_].blockset_,
|
||||
50.f, true);
|
||||
ImGui::SameLine();
|
||||
|
||||
gui::InputHexByte("Music", &entrances_[current_entrance_id_].music_, 50.f,
|
||||
true);
|
||||
ImGui::SameLine();
|
||||
gui::InputHexByte("Floor", &entrances_[current_entrance_id_].floor_);
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
gui::InputHexWord("Player X ",
|
||||
&entrances_[current_entrance_id_].x_position_);
|
||||
ImGui::SameLine();
|
||||
gui::InputHexWord("Player Y ",
|
||||
&entrances_[current_entrance_id_].y_position_);
|
||||
|
||||
gui::InputHexWord("Camera X",
|
||||
&entrances_[current_entrance_id_].camera_trigger_x_);
|
||||
ImGui::SameLine();
|
||||
gui::InputHexWord("Camera Y",
|
||||
&entrances_[current_entrance_id_].camera_trigger_y_);
|
||||
|
||||
gui::InputHexWord("Scroll X ",
|
||||
&entrances_[current_entrance_id_].camera_x_);
|
||||
ImGui::SameLine();
|
||||
gui::InputHexWord("Scroll Y ",
|
||||
&entrances_[current_entrance_id_].camera_y_);
|
||||
|
||||
gui::InputHexWord("Exit", &entrances_[current_entrance_id_].exit_, 50.f,
|
||||
true);
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Camera Boundaries");
|
||||
ImGui::Separator();
|
||||
ImGui::Text("\t\t\t\t\tNorth East South West");
|
||||
gui::InputHexByte("Quadrant",
|
||||
&entrances_[current_entrance_id_].camera_boundary_qn_,
|
||||
50.f, true);
|
||||
ImGui::SameLine();
|
||||
gui::InputHexByte("", &entrances_[current_entrance_id_].camera_boundary_qe_,
|
||||
50.f, true);
|
||||
ImGui::SameLine();
|
||||
gui::InputHexByte("", &entrances_[current_entrance_id_].camera_boundary_qs_,
|
||||
50.f, true);
|
||||
ImGui::SameLine();
|
||||
gui::InputHexByte("", &entrances_[current_entrance_id_].camera_boundary_qw_,
|
||||
50.f, true);
|
||||
|
||||
gui::InputHexByte("Full room",
|
||||
&entrances_[current_entrance_id_].camera_boundary_fn_,
|
||||
50.f, true);
|
||||
ImGui::SameLine();
|
||||
gui::InputHexByte("", &entrances_[current_entrance_id_].camera_boundary_fe_,
|
||||
50.f, true);
|
||||
ImGui::SameLine();
|
||||
gui::InputHexByte("", &entrances_[current_entrance_id_].camera_boundary_fs_,
|
||||
50.f, true);
|
||||
ImGui::SameLine();
|
||||
gui::InputHexByte("", &entrances_[current_entrance_id_].camera_boundary_fw_,
|
||||
50.f, true);
|
||||
|
||||
if (ImGui::BeginChild("EntranceSelector", ImVec2(0, 0), true,
|
||||
ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
|
||||
for (int i = 0; i < 0x85 + 7; i++) {
|
||||
rom()->resource_label()->SelectableLabelWithNameEdit(
|
||||
current_entrance_id_ == i, "Dungeon Entrance Names",
|
||||
core::UppercaseHexByte(i),
|
||||
zelda3::dungeon::kEntranceNames[i].data());
|
||||
|
||||
if (ImGui::IsItemClicked()) {
|
||||
current_entrance_id_ = i;
|
||||
if (!active_rooms_.contains(i)) {
|
||||
active_rooms_.push_back(entrances_[i].room_);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonEditor::DrawDungeonTabView() {
|
||||
static int next_tab_id = 0;
|
||||
|
||||
if (ImGui::BeginTabBar("MyTabBar", kDungeonTabBarFlags)) {
|
||||
// TODO: Manage the room that is being added to the tab bar.
|
||||
if (ImGui::TabItemButton("+", kDungeonTabFlags)) {
|
||||
if (std::find(active_rooms_.begin(), active_rooms_.end(),
|
||||
current_room_id_) != active_rooms_.end()) {
|
||||
// Room is already open
|
||||
next_tab_id++;
|
||||
}
|
||||
active_rooms_.push_back(next_tab_id++); // Add new tab
|
||||
}
|
||||
|
||||
@@ -226,6 +424,11 @@ void DungeonEditor::DrawDungeonTabView() {
|
||||
for (int n = 0; n < active_rooms_.Size;) {
|
||||
bool open = true;
|
||||
|
||||
if (active_rooms_[n] > sizeof(zelda3::dungeon::kRoomNames) / 4) {
|
||||
active_rooms_.erase(active_rooms_.Data + n);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem(
|
||||
zelda3::dungeon::kRoomNames[active_rooms_[n]].data(), &open,
|
||||
ImGuiTabItemFlags_None)) {
|
||||
@@ -269,8 +472,11 @@ void DungeonEditor::DrawDungeonCanvas(int room_id) {
|
||||
|
||||
ImGui::EndGroup();
|
||||
|
||||
canvas_.DrawBackground();
|
||||
canvas_.DrawBackground(ImVec2(0x200, 0x200));
|
||||
canvas_.DrawContextMenu();
|
||||
if (is_loaded_) {
|
||||
canvas_.DrawBitmap(rooms_[room_id].layer1(), 0, 0);
|
||||
}
|
||||
canvas_.DrawGrid();
|
||||
canvas_.DrawOverlay();
|
||||
}
|
||||
@@ -289,8 +495,8 @@ void DungeonEditor::DrawRoomGraphics() {
|
||||
if (current_block >= 1) {
|
||||
top_left_y = room_gfx_canvas_.zero_point().y + height * current_block;
|
||||
}
|
||||
room_gfx_canvas_.GetDrawList()->AddImage(
|
||||
(void*)graphics_bin_[block].texture(),
|
||||
room_gfx_canvas_.draw_list()->AddImage(
|
||||
(void*)graphics_bin_[block].get()->texture(),
|
||||
ImVec2(room_gfx_canvas_.zero_point().x + 2, top_left_y),
|
||||
ImVec2(room_gfx_canvas_.zero_point().x + 0x100,
|
||||
room_gfx_canvas_.zero_point().y + offset));
|
||||
@@ -328,7 +534,7 @@ void DungeonEditor::DrawObjectRenderer() {
|
||||
ImGui::GetContentRegionAvail().x);
|
||||
TableSetupColumn("Canvas");
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
ImGui::BeginChild("DungeonObjectButtons", ImVec2(250, 0), true);
|
||||
|
||||
int selected_object = 0;
|
||||
@@ -348,7 +554,7 @@ void DungeonEditor::DrawObjectRenderer() {
|
||||
ImGui::EndChild();
|
||||
|
||||
// Right side of the table - Canvas
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
ImGui::BeginChild("DungeonObjectCanvas", ImVec2(276, 0x10 * 0x40 + 1),
|
||||
true);
|
||||
|
||||
@@ -365,14 +571,283 @@ void DungeonEditor::DrawObjectRenderer() {
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
// if (object_loaded_) {
|
||||
// ImGui::Begin("Memory Viewer", &object_loaded_, 0);
|
||||
// auto memory = object_renderer_.memory();
|
||||
// static MemoryEditor mem_edit;
|
||||
// mem_edit.DrawContents((void*)object_renderer_.memory_ptr(),
|
||||
// memory.size());
|
||||
// ImGui::End();
|
||||
// }
|
||||
if (object_loaded_) {
|
||||
ImGui::Begin("Memory Viewer", &object_loaded_, 0);
|
||||
static MemoryEditor mem_edit;
|
||||
mem_edit.DrawContents((void*)object_renderer_.mutable_memory(),
|
||||
object_renderer_.mutable_memory()->size());
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonEditor::LoadRoomEntrances() {
|
||||
for (int i = 0; i < 0x07; ++i) {
|
||||
entrances_.emplace_back(zelda3::dungeon::RoomEntrance(*rom(), i, true));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 0x85; ++i) {
|
||||
entrances_.emplace_back(zelda3::dungeon::RoomEntrance(*rom(), i, false));
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
void DungeonEditor::CalculateUsageStats() {
|
||||
// Create a hash map of the usage for elements of each Dungeon Room such as
|
||||
// the blockset, spriteset, palette, etc. This is so we can keep track of
|
||||
// which graphics sets and palette sets are in use and which are not.
|
||||
|
||||
for (const auto& room : rooms_) {
|
||||
// Blockset
|
||||
if (blockset_usage_.find(room.blockset) == blockset_usage_.end()) {
|
||||
blockset_usage_[room.blockset] = 1;
|
||||
} else {
|
||||
blockset_usage_[room.blockset] += 1;
|
||||
}
|
||||
|
||||
// Spriteset
|
||||
if (spriteset_usage_.find(room.spriteset) == spriteset_usage_.end()) {
|
||||
spriteset_usage_[room.spriteset] = 1;
|
||||
} else {
|
||||
spriteset_usage_[room.spriteset] += 1;
|
||||
}
|
||||
|
||||
// Palette
|
||||
if (palette_usage_.find(room.palette) == palette_usage_.end()) {
|
||||
palette_usage_[room.palette] = 1;
|
||||
} else {
|
||||
palette_usage_[room.palette] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonEditor::RenderSetUsage(
|
||||
const absl::flat_hash_map<uint16_t, int>& usage_map, uint16_t& selected_set,
|
||||
int spriteset_offset) {
|
||||
// Sort the usage map by set number
|
||||
std::vector<std::pair<uint16_t, int>> sorted_usage(usage_map.begin(),
|
||||
usage_map.end());
|
||||
std::sort(sorted_usage.begin(), sorted_usage.end(),
|
||||
[](const auto& a, const auto& b) { return a.first < b.first; });
|
||||
|
||||
for (const auto& [set, count] : sorted_usage) {
|
||||
std::string display_str;
|
||||
if (spriteset_offset != 0x00) {
|
||||
display_str = absl::StrFormat("%#02x, %#02x: %d", set,
|
||||
(set + spriteset_offset), count);
|
||||
} else {
|
||||
display_str =
|
||||
absl::StrFormat("%#02x: %d", (set + spriteset_offset), count);
|
||||
}
|
||||
if (ImGui::Selectable(display_str.c_str(), selected_set == set)) {
|
||||
selected_set = set; // Update the selected set when clicked
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Calculate the unused sets in a usage map
|
||||
// Range for blocksets 0-0x24
|
||||
// Range for spritesets 0-0x8F
|
||||
// Range for palettes 0-0x47
|
||||
template <typename T>
|
||||
void RenderUnusedSets(const absl::flat_hash_map<T, int>& usage_map, int max_set,
|
||||
int spriteset_offset = 0x00) {
|
||||
std::vector<int> unused_sets;
|
||||
for (int i = 0; i < max_set; i++) {
|
||||
if (usage_map.find(i) == usage_map.end()) {
|
||||
unused_sets.push_back(i);
|
||||
}
|
||||
}
|
||||
for (const auto& set : unused_sets) {
|
||||
if (spriteset_offset != 0x00) {
|
||||
ImGui::Text("%#02x, %#02x", set, (set + spriteset_offset));
|
||||
} else {
|
||||
ImGui::Text("%#02x", set);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void DungeonEditor::DrawUsageStats() {
|
||||
if (ImGui::Button("Refresh")) {
|
||||
selected_blockset_ = 0xFFFF;
|
||||
selected_spriteset_ = 0xFFFF;
|
||||
selected_palette_ = 0xFFFF;
|
||||
spriteset_usage_.clear();
|
||||
blockset_usage_.clear();
|
||||
palette_usage_.clear();
|
||||
CalculateUsageStats();
|
||||
}
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
|
||||
if (ImGui::BeginTable("DungeonUsageStatsTable", 8,
|
||||
kDungeonTableFlags | ImGuiTableFlags_SizingFixedFit,
|
||||
ImGui::GetContentRegionAvail())) {
|
||||
TableSetupColumn("Blockset Usage");
|
||||
TableSetupColumn("Unused Blockset");
|
||||
TableSetupColumn("Palette Usage");
|
||||
TableSetupColumn("Unused Palette");
|
||||
TableSetupColumn("Spriteset Usage");
|
||||
TableSetupColumn("Unused Spriteset");
|
||||
TableSetupColumn("Usage Grid");
|
||||
TableSetupColumn("Group Preview");
|
||||
TableHeadersRow();
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
TableNextColumn();
|
||||
ImGui::BeginChild("BlocksetUsageScroll", ImVec2(0, 0), true,
|
||||
ImGuiWindowFlags_HorizontalScrollbar);
|
||||
RenderSetUsage(blockset_usage_, selected_blockset_);
|
||||
ImGui::EndChild();
|
||||
|
||||
TableNextColumn();
|
||||
ImGui::BeginChild("UnusedBlocksetScroll", ImVec2(0, 0), true,
|
||||
ImGuiWindowFlags_HorizontalScrollbar);
|
||||
RenderUnusedSets(blockset_usage_, 0x25);
|
||||
ImGui::EndChild();
|
||||
|
||||
TableNextColumn();
|
||||
ImGui::BeginChild("PaletteUsageScroll", ImVec2(0, 0), true,
|
||||
ImGuiWindowFlags_HorizontalScrollbar);
|
||||
RenderSetUsage(palette_usage_, selected_palette_);
|
||||
ImGui::EndChild();
|
||||
|
||||
TableNextColumn();
|
||||
ImGui::BeginChild("UnusedPaletteScroll", ImVec2(0, 0), true,
|
||||
ImGuiWindowFlags_HorizontalScrollbar);
|
||||
RenderUnusedSets(palette_usage_, 0x48);
|
||||
ImGui::EndChild();
|
||||
|
||||
TableNextColumn();
|
||||
|
||||
ImGui::BeginChild("SpritesetUsageScroll", ImVec2(0, 0), true,
|
||||
ImGuiWindowFlags_HorizontalScrollbar);
|
||||
RenderSetUsage(spriteset_usage_, selected_spriteset_, 0x40);
|
||||
ImGui::EndChild();
|
||||
|
||||
TableNextColumn();
|
||||
ImGui::BeginChild("UnusedSpritesetScroll", ImVec2(0, 0), true,
|
||||
ImGuiWindowFlags_HorizontalScrollbar);
|
||||
RenderUnusedSets(spriteset_usage_, 0x90, 0x40);
|
||||
ImGui::EndChild();
|
||||
|
||||
TableNextColumn();
|
||||
ImGui::BeginChild("UsageGrid", ImVec2(0, 0), true,
|
||||
ImGuiWindowFlags_HorizontalScrollbar);
|
||||
ImGui::Text("%s",
|
||||
absl::StrFormat("Total size of all rooms: %d hex format: %#06x",
|
||||
total_room_size_, total_room_size_)
|
||||
.c_str());
|
||||
DrawUsageGrid();
|
||||
ImGui::EndChild();
|
||||
|
||||
TableNextColumn();
|
||||
if (selected_blockset_ < 0x25) {
|
||||
gfx_group_editor_.SetSelectedBlockset(selected_blockset_);
|
||||
gfx_group_editor_.DrawBlocksetViewer(true);
|
||||
} else if (selected_spriteset_ < 0x90) {
|
||||
gfx_group_editor_.SetSelectedSpriteset(selected_spriteset_ + 0x40);
|
||||
gfx_group_editor_.DrawSpritesetViewer(true);
|
||||
}
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
void DungeonEditor::DrawUsageGrid() {
|
||||
// Create a grid of 295 small squares which is 16 squares wide
|
||||
// Each square represents a room in the game
|
||||
// When you hover a square it should show a hover tooltip with the properties
|
||||
// of the room such as the blockset, spriteset, palette, etc. Calculate the
|
||||
// number of rows
|
||||
int totalSquares = 296;
|
||||
int squaresWide = 16;
|
||||
int squaresTall = (totalSquares + squaresWide - 1) /
|
||||
squaresWide; // Ceiling of totalSquares/squaresWide
|
||||
|
||||
// Loop through each row
|
||||
for (int row = 0; row < squaresTall; ++row) {
|
||||
// Start a new line for each row
|
||||
ImGui::NewLine();
|
||||
|
||||
// Loop through each column in the row
|
||||
for (int col = 0; col < squaresWide; ++col) {
|
||||
// Check if we have reached 295 squares
|
||||
if (row * squaresWide + col >= totalSquares) {
|
||||
break;
|
||||
}
|
||||
// Determine if this square should be highlighted
|
||||
const auto& room = rooms_[row * squaresWide + col];
|
||||
|
||||
// Create a button or selectable for each square
|
||||
ImGui::BeginGroup();
|
||||
ImVec4 color = room_palette_[room.palette];
|
||||
color.x = color.x / 255;
|
||||
color.y = color.y / 255;
|
||||
color.z = color.z / 255;
|
||||
color.w = 1.0f;
|
||||
if (rooms_[row * squaresWide + col].room_size() > 0xFFFF) {
|
||||
color = ImVec4(1.0f, 0.0f, 0.0f, 1.0f); // Or any highlight color
|
||||
}
|
||||
if (rooms_[row * squaresWide + col].room_size() == 0) {
|
||||
color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f); // Or any highlight color
|
||||
}
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, color);
|
||||
// Make the button text darker
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
|
||||
bool highlight = room.blockset == selected_blockset_ ||
|
||||
room.spriteset == selected_spriteset_ ||
|
||||
room.palette == selected_palette_;
|
||||
|
||||
// Set highlight color if needed
|
||||
if (highlight) {
|
||||
ImGui::PushStyleColor(
|
||||
ImGuiCol_Button,
|
||||
ImVec4(1.0f, 0.5f, 0.0f, 1.0f)); // Or any highlight color
|
||||
}
|
||||
if (ImGui::Button(absl::StrFormat(
|
||||
"%#x", rooms_[row * squaresWide + col].room_size())
|
||||
.c_str(),
|
||||
ImVec2(55, 30))) {
|
||||
// Switch over to the room editor tab
|
||||
// and add a room tab by the ID of the square
|
||||
// that was clicked
|
||||
}
|
||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
|
||||
ImGui::OpenPopup(
|
||||
absl::StrFormat("RoomContextMenu%d", row * squaresWide + col)
|
||||
.c_str());
|
||||
}
|
||||
ImGui::PopStyleColor(2);
|
||||
ImGui::EndGroup();
|
||||
|
||||
// Reset style if it was highlighted
|
||||
if (highlight) {
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
// Check if the square is hovered
|
||||
if (ImGui::IsItemHovered()) {
|
||||
// Display a tooltip with all the room properties
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("Room ID: %d", row * squaresWide + col);
|
||||
ImGui::Text("Blockset: %#02x", room.blockset);
|
||||
ImGui::Text("Spriteset: %#02x", room.spriteset);
|
||||
ImGui::Text("Palette: %#02x", room.palette);
|
||||
ImGui::Text("Floor1: %#02x", room.floor1);
|
||||
ImGui::Text("Floor2: %#02x", room.floor2);
|
||||
ImGui::Text("Message ID: %#04x", room.message_id_);
|
||||
ImGui::Text("Size: %#06x", room.room_size());
|
||||
ImGui::Text("Size Pointer: %#06x", room.room_size_ptr());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
// Keep squares in the same line
|
||||
ImGui::SameLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
|
||||
@@ -5,11 +5,14 @@
|
||||
|
||||
#include "app/core/common.h"
|
||||
#include "app/core/editor.h"
|
||||
#include "app/core/labeling.h"
|
||||
#include "app/editor/modules/gfx_group_editor.h"
|
||||
#include "app/editor/modules/palette_editor.h"
|
||||
#include "app/gui/canvas.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/rom.h"
|
||||
#include "zelda3/dungeon/room.h"
|
||||
#include "zelda3/dungeon/room_entrance.h"
|
||||
#include "zelda3/dungeon/room_object.h"
|
||||
|
||||
namespace yaze {
|
||||
@@ -40,9 +43,16 @@ class DungeonEditor : public Editor,
|
||||
absl::Status Undo() override { return absl::OkStatus(); }
|
||||
absl::Status Redo() override { return absl::OkStatus(); }
|
||||
|
||||
void add_room(int i) { active_rooms_.push_back(i); }
|
||||
|
||||
private:
|
||||
void LoadDungeonRoomSize();
|
||||
|
||||
void UpdateDungeonRoomView();
|
||||
|
||||
void DrawToolset();
|
||||
void DrawRoomSelector();
|
||||
void DrawEntranceSelector();
|
||||
|
||||
void DrawDungeonTabView();
|
||||
void DrawDungeonCanvas(int room_id);
|
||||
@@ -51,6 +61,14 @@ class DungeonEditor : public Editor,
|
||||
void DrawTileSelector();
|
||||
void DrawObjectRenderer();
|
||||
|
||||
void LoadRoomEntrances();
|
||||
|
||||
void CalculateUsageStats();
|
||||
void DrawUsageStats();
|
||||
void DrawUsageGrid();
|
||||
void RenderSetUsage(const absl::flat_hash_map<uint16_t, int>& usage_map,
|
||||
uint16_t& selected_set, int spriteset_offset = 0x00);
|
||||
|
||||
enum BackgroundType {
|
||||
kNoBackground,
|
||||
kBackground1,
|
||||
@@ -70,15 +88,17 @@ class DungeonEditor : public Editor,
|
||||
bool refresh_graphics_ = false;
|
||||
bool show_object_render_ = false;
|
||||
|
||||
uint16_t current_entrance_id_ = 0;
|
||||
uint16_t current_room_id_ = 0;
|
||||
uint64_t current_palette_id_ = 0;
|
||||
uint64_t current_palette_group_id_ = 0;
|
||||
|
||||
ImVector<int> active_rooms_;
|
||||
|
||||
GfxGroupEditor gfx_group_editor_;
|
||||
PaletteEditor palette_editor_;
|
||||
gfx::SNESPalette current_palette_;
|
||||
gfx::SNESPalette full_palette_;
|
||||
gfx::SnesPalette current_palette_;
|
||||
gfx::SnesPalette full_palette_;
|
||||
gfx::PaletteGroup current_palette_group_;
|
||||
|
||||
gui::Canvas canvas_;
|
||||
@@ -86,12 +106,28 @@ class DungeonEditor : public Editor,
|
||||
gui::Canvas object_canvas_;
|
||||
|
||||
gfx::Bitmap room_gfx_bmp_;
|
||||
gfx::BitmapTable graphics_bin_;
|
||||
gfx::BitmapManager graphics_bin_;
|
||||
|
||||
std::vector<gfx::Bitmap*> room_gfx_sheets_;
|
||||
std::vector<zelda3::dungeon::Room> rooms_;
|
||||
std::vector<zelda3::dungeon::RoomEntrance> entrances_;
|
||||
std::vector<gfx::BitmapManager> room_graphics_;
|
||||
zelda3::dungeon::DungeonObjectRenderer object_renderer_;
|
||||
|
||||
absl::flat_hash_map<uint16_t, int> spriteset_usage_;
|
||||
absl::flat_hash_map<uint16_t, int> blockset_usage_;
|
||||
absl::flat_hash_map<uint16_t, int> palette_usage_;
|
||||
|
||||
std::vector<int64_t> room_size_pointers_;
|
||||
|
||||
uint16_t selected_blockset_ = 0xFFFF; // 0xFFFF indicates no selection
|
||||
uint16_t selected_spriteset_ = 0xFFFF;
|
||||
uint16_t selected_palette_ = 0xFFFF;
|
||||
|
||||
uint64_t total_room_size_ = 0;
|
||||
|
||||
std::unordered_map<int, int> room_size_addresses_;
|
||||
std::unordered_map<int, ImVec4> room_palette_;
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
|
||||
@@ -28,6 +28,7 @@ using ImGui::Button;
|
||||
using ImGui::InputInt;
|
||||
using ImGui::InputText;
|
||||
using ImGui::SameLine;
|
||||
using ImGui::TableNextColumn;
|
||||
|
||||
constexpr ImGuiTableFlags kGfxEditTableFlags =
|
||||
ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable |
|
||||
@@ -63,13 +64,13 @@ absl::Status GraphicsEditor::UpdateGfxEdit() {
|
||||
status_ = UpdateGfxSheetList();
|
||||
|
||||
NEXT_COLUMN();
|
||||
if (rom()->isLoaded()) {
|
||||
if (rom()->is_loaded()) {
|
||||
DrawGfxEditToolset();
|
||||
status_ = UpdateGfxTabView();
|
||||
}
|
||||
|
||||
NEXT_COLUMN();
|
||||
if (rom()->isLoaded()) {
|
||||
if (rom()->is_loaded()) {
|
||||
status_ = UpdatePaletteColumn();
|
||||
}
|
||||
}
|
||||
@@ -87,38 +88,41 @@ void GraphicsEditor::DrawGfxEditToolset() {
|
||||
"Zoom In", "Current Color", "Tile Size"})
|
||||
ImGui::TableSetupColumn(name);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
if (Button(ICON_MD_SELECT_ALL)) {
|
||||
gfx_edit_mode_ = GfxEditMode::kSelect;
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
if (Button(ICON_MD_DRAW)) {
|
||||
gfx_edit_mode_ = GfxEditMode::kPencil;
|
||||
}
|
||||
HOVER_HINT("Draw with current color");
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
if (Button(ICON_MD_FORMAT_COLOR_FILL)) {
|
||||
gfx_edit_mode_ = GfxEditMode::kFill;
|
||||
}
|
||||
HOVER_HINT("Fill with current color");
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
if (Button(ICON_MD_CONTENT_COPY)) {
|
||||
std::vector<uint8_t> png_data =
|
||||
rom()->bitmap_manager().GetBitmap(current_sheet_)->GetPngData();
|
||||
rom()->bitmap_manager().shared_bitmap(current_sheet_)->GetPngData();
|
||||
CopyImageToClipboard(png_data);
|
||||
}
|
||||
HOVER_HINT("Copy to Clipboard");
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
if (Button(ICON_MD_CONTENT_PASTE)) {
|
||||
std::vector<uint8_t> png_data;
|
||||
int width, height;
|
||||
GetImageFromClipboard(png_data, width, height);
|
||||
if (png_data.size() > 0) {
|
||||
rom()
|
||||
->bitmap_manager()
|
||||
.GetBitmap(current_sheet_)
|
||||
->LoadFromPngData(png_data, width, height);
|
||||
->mutable_bitmap_manager()
|
||||
->mutable_bitmap(current_sheet_)
|
||||
->Create(width, height, 8, png_data);
|
||||
rom()->UpdateBitmap(rom()
|
||||
->mutable_bitmap_manager()
|
||||
->mutable_bitmap(current_sheet_)
|
||||
@@ -127,35 +131,35 @@ void GraphicsEditor::DrawGfxEditToolset() {
|
||||
}
|
||||
HOVER_HINT("Paste from Clipboard");
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
if (Button(ICON_MD_ZOOM_OUT)) {
|
||||
if (current_scale_ >= 0.0f) {
|
||||
current_scale_ -= 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
if (Button(ICON_MD_ZOOM_IN)) {
|
||||
if (current_scale_ <= 16.0f) {
|
||||
current_scale_ += 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
auto bitmap = rom()->bitmap_manager()[current_sheet_];
|
||||
auto palette = bitmap->palette();
|
||||
for (int i = 0; i < 8; i++) {
|
||||
ImGui::SameLine();
|
||||
auto color =
|
||||
ImVec4(palette[i].GetRGB().x / 255.0f, palette[i].GetRGB().y / 255.0f,
|
||||
palette[i].GetRGB().z / 255.0f, 255.0f);
|
||||
ImVec4(palette[i].rgb().x / 255.0f, palette[i].rgb().y / 255.0f,
|
||||
palette[i].rgb().z / 255.0f, 255.0f);
|
||||
if (ImGui::ColorButton(absl::StrFormat("Palette Color %d", i).c_str(),
|
||||
color)) {
|
||||
current_color_ = color;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
gui::InputHexByte("Tile Size", &tile_size_, 0x01);
|
||||
|
||||
ImGui::EndTable();
|
||||
@@ -173,43 +177,48 @@ absl::Status GraphicsEditor::UpdateGfxSheetList() {
|
||||
ImGuiWindowFlags_NoDecoration);
|
||||
ImGui::PopStyleVar();
|
||||
gui::Canvas graphics_bin_canvas_;
|
||||
auto select_tile_event = [&]() {
|
||||
if (value.get()->IsActive()) {
|
||||
auto texture = value.get()->texture();
|
||||
graphics_bin_canvas_.GetDrawList()->AddImage(
|
||||
(void*)texture,
|
||||
ImVec2(graphics_bin_canvas_.zero_point().x + 2,
|
||||
graphics_bin_canvas_.zero_point().y + 2),
|
||||
ImVec2(graphics_bin_canvas_.zero_point().x +
|
||||
value.get()->width() * sheet_scale_,
|
||||
graphics_bin_canvas_.zero_point().y +
|
||||
value.get()->height() * sheet_scale_));
|
||||
// auto select_tile_event = [&]() {
|
||||
// };
|
||||
// graphics_bin_canvas_.UpdateEvent(
|
||||
// select_tile_event, ImVec2(0x100 + 1, 0x40 + 1), 0x20, sheet_scale_,
|
||||
// /*grid_size=*/16.0f);
|
||||
|
||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
|
||||
current_sheet_ = key;
|
||||
open_sheets_.insert(key);
|
||||
}
|
||||
graphics_bin_canvas_.DrawBackground(ImVec2(0x100 + 1, 0x40 + 1));
|
||||
graphics_bin_canvas_.DrawContextMenu();
|
||||
if (value.get()->is_active()) {
|
||||
auto texture = value.get()->texture();
|
||||
graphics_bin_canvas_.draw_list()->AddImage(
|
||||
(void*)texture,
|
||||
ImVec2(graphics_bin_canvas_.zero_point().x + 2,
|
||||
graphics_bin_canvas_.zero_point().y + 2),
|
||||
ImVec2(graphics_bin_canvas_.zero_point().x +
|
||||
value.get()->width() * sheet_scale_,
|
||||
graphics_bin_canvas_.zero_point().y +
|
||||
value.get()->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);
|
||||
|
||||
graphics_bin_canvas_.GetDrawList()->AddRectFilled(
|
||||
rent_min, rent_max, IM_COL32(0, 125, 0, 128));
|
||||
|
||||
graphics_bin_canvas_.GetDrawList()->AddText(
|
||||
text_pos, IM_COL32(125, 255, 125, 255),
|
||||
absl::StrFormat("%02X", key).c_str());
|
||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
|
||||
current_sheet_ = key;
|
||||
open_sheets_.insert(key);
|
||||
}
|
||||
};
|
||||
|
||||
graphics_bin_canvas_.UpdateEvent(
|
||||
select_tile_event, ImVec2(0x100 + 1, 0x40 + 1), 0x20, sheet_scale_,
|
||||
/*grid_size=*/16.0f);
|
||||
// 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);
|
||||
|
||||
graphics_bin_canvas_.draw_list()->AddRectFilled(rent_min, rent_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());
|
||||
}
|
||||
graphics_bin_canvas_.DrawGrid(16.0f);
|
||||
graphics_bin_canvas_.DrawOverlay();
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
|
||||
ImGui::EndChild();
|
||||
}
|
||||
@@ -249,18 +258,19 @@ absl::Status GraphicsEditor::UpdateGfxTabView() {
|
||||
ImGuiWindowFlags_AlwaysVerticalScrollbar |
|
||||
ImGuiWindowFlags_AlwaysHorizontalScrollbar);
|
||||
|
||||
gfx::Bitmap& current_bitmap =
|
||||
*rom()->mutable_bitmap_manager()->mutable_bitmap(sheet_id);
|
||||
|
||||
auto draw_tile_event = [&]() {
|
||||
gfx::Bitmap& current_bitmap =
|
||||
*rom()->mutable_bitmap_manager()->mutable_bitmap(sheet_id);
|
||||
current_sheet_canvas_.DrawTileOnBitmap(tile_size_, current_bitmap,
|
||||
current_sheet_canvas_.DrawTileOnBitmap(tile_size_, ¤t_bitmap,
|
||||
current_color_);
|
||||
rom()->UpdateBitmap(¤t_bitmap);
|
||||
rom()->UpdateBitmap(¤t_bitmap, true);
|
||||
};
|
||||
|
||||
auto size = ImVec2(0x80, 0x20);
|
||||
current_sheet_canvas_.UpdateColorPainter(
|
||||
*rom()->bitmap_manager()[sheet_id], current_color_, draw_tile_event,
|
||||
size, tile_size_, current_scale_, 8.0f);
|
||||
tile_size_, current_scale_);
|
||||
|
||||
ImGui::EndChild();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
@@ -289,12 +299,13 @@ absl::Status GraphicsEditor::UpdateGfxTabView() {
|
||||
ImGui::Begin(absl::StrFormat("##GfxEditPaletteChildWindow%d", id).c_str(),
|
||||
&active, ImGuiWindowFlags_AlwaysUseWindowPadding);
|
||||
current_sheet_ = id;
|
||||
// ImVec2(0x100, 0x40),
|
||||
current_sheet_canvas_.UpdateColorPainter(
|
||||
*rom()->bitmap_manager()[id], current_color_,
|
||||
[&]() {
|
||||
|
||||
},
|
||||
ImVec2(0x100, 0x40), tile_size_, current_scale_, 8.0f);
|
||||
tile_size_, current_scale_);
|
||||
ImGui::End();
|
||||
|
||||
if (active == false) {
|
||||
@@ -315,7 +326,7 @@ absl::Status GraphicsEditor::UpdatePaletteColumn() {
|
||||
|
||||
auto palette = palette_group[edit_palette_index_];
|
||||
|
||||
if (rom()->isLoaded()) {
|
||||
if (rom()->is_loaded()) {
|
||||
gui::TextWithSeparators("ROM Palette");
|
||||
ImGui::SetNextItemWidth(100.f);
|
||||
ImGui::Combo("Palette Group", (int*)&edit_palette_group_name_index_,
|
||||
@@ -345,14 +356,19 @@ absl::Status GraphicsEditor::UpdateLinkGfxView() {
|
||||
const auto link_gfx_offset = 0x80000;
|
||||
const auto link_gfx_length = 0x7000;
|
||||
|
||||
// Load Links graphics from the ROM
|
||||
RETURN_IF_ERROR(rom()->LoadLinkGraphics());
|
||||
// TODO: Finish Rom::LoadLinkGraphics and implement this
|
||||
if (ImGui::Button("Load Link Graphics (Experimental)")) {
|
||||
if (rom()->is_loaded()) {
|
||||
// Load Links graphics from the ROM
|
||||
rom()->LoadLinkGraphics();
|
||||
|
||||
// Split it into the pose data frames
|
||||
// Create an animation step display for the poses
|
||||
// Allow the user to modify the frames used in an anim step
|
||||
// LinkOAM_AnimationSteps:
|
||||
// #_0D85FB
|
||||
// Split it into the pose data frames
|
||||
// Create an animation step display for the poses
|
||||
// Allow the user to modify the frames used in an anim step
|
||||
// LinkOAM_AnimationSteps:
|
||||
// #_0D85FB
|
||||
}
|
||||
}
|
||||
|
||||
END_TAB_ITEM()
|
||||
return absl::OkStatus();
|
||||
@@ -424,7 +440,7 @@ absl::Status GraphicsEditor::DrawToolset() {
|
||||
for (const auto& name : kGfxToolsetColumnNames)
|
||||
ImGui::TableSetupColumn(name.data());
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
TableNextColumn();
|
||||
if (Button(ICON_MD_MEMORY)) {
|
||||
if (!open_memory_editor_) {
|
||||
open_memory_editor_ = true;
|
||||
@@ -527,8 +543,12 @@ absl::Status GraphicsEditor::DrawPaletteControls() {
|
||||
if (col_file_palette_group_.size() != 0) {
|
||||
col_file_palette_group_.Clear();
|
||||
}
|
||||
col_file_palette_group_ = gfx::CreatePaletteGroupFromColFile(col_data_);
|
||||
col_file_palette_ = gfx::SNESPalette(col_data_);
|
||||
auto col_file_palette_group_status =
|
||||
gfx::CreatePaletteGroupFromColFile(col_data_);
|
||||
if (col_file_palette_group_status.ok()) {
|
||||
col_file_palette_group_ = col_file_palette_group_status.value();
|
||||
}
|
||||
col_file_palette_ = gfx::SnesPalette(col_data_);
|
||||
|
||||
// gigaleak dev format based code
|
||||
decoded_col_ = gfx::DecodeColFile(col_file_path_);
|
||||
@@ -539,7 +559,7 @@ absl::Status GraphicsEditor::DrawPaletteControls() {
|
||||
gui::ButtonPipe("Copy COL Path",
|
||||
[this]() { ImGui::SetClipboardText(col_file_path_); });
|
||||
|
||||
if (rom()->isLoaded()) {
|
||||
if (rom()->is_loaded()) {
|
||||
gui::TextWithSeparators("ROM Palette");
|
||||
gui::InputHex("Palette Index", ¤t_palette_index_);
|
||||
ImGui::Combo("Palette", ¤t_palette_, kPaletteGroupAddressesKeys,
|
||||
@@ -644,7 +664,7 @@ absl::Status GraphicsEditor::DrawClipboardImport() {
|
||||
gui::InputHex("Num Sheets", &num_sheets_to_load_);
|
||||
|
||||
gui::ButtonPipe("Decompress Clipboard Data", [this]() {
|
||||
if (temp_rom_.isLoaded()) {
|
||||
if (temp_rom_.is_loaded()) {
|
||||
status_ = DecompressImportData(0x40000);
|
||||
} else {
|
||||
status_ = absl::InvalidArgumentError(
|
||||
@@ -690,7 +710,7 @@ absl::Status GraphicsEditor::DecompressImportData(int size) {
|
||||
bin_bitmap_.Create(core::kTilesheetWidth, 0x2000, core::kTilesheetDepth,
|
||||
converted_sheet);
|
||||
|
||||
if (rom()->isLoaded()) {
|
||||
if (rom()->is_loaded()) {
|
||||
auto palette_group = rom()->palette_group("ow_main");
|
||||
z3_rom_palette_ = palette_group[current_palette_];
|
||||
if (col_file_) {
|
||||
|
||||
@@ -176,13 +176,14 @@ class GraphicsEditor : public SharedROM {
|
||||
gfx::BitmapTable clipboard_graphics_bin_;
|
||||
gfx::BitmapTable link_graphics_;
|
||||
gfx::PaletteGroup col_file_palette_group_;
|
||||
gfx::SNESPalette z3_rom_palette_;
|
||||
gfx::SNESPalette col_file_palette_;
|
||||
gfx::SNESPalette link_palette_;
|
||||
gfx::SnesPalette z3_rom_palette_;
|
||||
gfx::SnesPalette col_file_palette_;
|
||||
gfx::SnesPalette link_palette_;
|
||||
gui::Canvas import_canvas_;
|
||||
gui::Canvas scr_canvas_;
|
||||
gui::Canvas super_donkey_canvas_;
|
||||
gui::Canvas current_sheet_canvas_;
|
||||
gui::Canvas current_sheet_canvas_{ImVec2(0x80, 0x20),
|
||||
gui::CanvasGridSize::k8x8};
|
||||
absl::Status status_;
|
||||
};
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <ImGuiFileDialog/ImGuiFileDialog.h>
|
||||
#include <imgui/imgui.h>
|
||||
#include <imgui/misc/cpp/imgui_stdlib.h>
|
||||
#include <imgui_internal.h>
|
||||
#include <imgui_memory_editor.h>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
@@ -113,6 +114,7 @@ class RecentFilesManager {
|
||||
} // namespace
|
||||
|
||||
using ImGui::BeginMenu;
|
||||
using ImGui::Checkbox;
|
||||
using ImGui::MenuItem;
|
||||
using ImGui::Text;
|
||||
|
||||
@@ -121,6 +123,24 @@ void MasterEditor::SetupScreen(std::shared_ptr<SDL_Renderer> renderer) {
|
||||
rom()->SetupRenderer(renderer);
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Function to switch the active tab in a tab bar
|
||||
void SetTabBarTab(ImGuiTabBar* tab_bar, ImGuiID tab_id) {
|
||||
if (tab_bar == NULL) return;
|
||||
|
||||
// Find the tab item with the specified tab_id
|
||||
ImGuiTabItem* tab_item = &tab_bar->Tabs[tab_id];
|
||||
tab_item->LastFrameVisible = -1;
|
||||
tab_item->LastFrameSelected = -1;
|
||||
tab_bar->VisibleTabId = tab_id;
|
||||
tab_bar->VisibleTabWasSubmitted = true;
|
||||
tab_bar->SelectedTabId = tab_id;
|
||||
tab_bar->NextSelectedTabId = tab_id;
|
||||
tab_bar->ReorderRequestTabId = tab_id;
|
||||
tab_bar->CurrFrameVisible = -1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
absl::Status MasterEditor::Update() {
|
||||
NewMasterFrame();
|
||||
|
||||
@@ -130,22 +150,29 @@ absl::Status MasterEditor::Update() {
|
||||
DrawAboutPopup();
|
||||
DrawInfoPopup();
|
||||
|
||||
if (rom()->isLoaded() && !rom_assets_loaded_) {
|
||||
if (rom()->is_loaded() && !rom_assets_loaded_) {
|
||||
// Initialize overworld graphics, maps, and palettes
|
||||
RETURN_IF_ERROR(overworld_editor_.LoadGraphics());
|
||||
rom_assets_loaded_ = true;
|
||||
}
|
||||
|
||||
TAB_BAR("##TabBar")
|
||||
auto current_tab_bar = ImGui::GetCurrentContext()->CurrentTabBar;
|
||||
|
||||
gui::RenderTabItem("Overworld", [&]() {
|
||||
current_editor_ = &overworld_editor_;
|
||||
status_ = overworld_editor_.Update();
|
||||
});
|
||||
if (overworld_editor_.jump_to_tab() == -1) {
|
||||
gui::RenderTabItem("Overworld", [&]() {
|
||||
current_editor_ = &overworld_editor_;
|
||||
status_ = overworld_editor_.Update();
|
||||
});
|
||||
}
|
||||
|
||||
gui::RenderTabItem("Dungeon", [&]() {
|
||||
current_editor_ = &dungeon_editor_;
|
||||
status_ = dungeon_editor_.Update();
|
||||
if (overworld_editor_.jump_to_tab() != -1) {
|
||||
dungeon_editor_.add_room(overworld_editor_.jump_to_tab());
|
||||
overworld_editor_.jump_to_tab_ = -1;
|
||||
}
|
||||
});
|
||||
|
||||
gui::RenderTabItem("Graphics",
|
||||
@@ -195,6 +222,10 @@ void MasterEditor::DrawStatusPopup() {
|
||||
if (ImGui::Button("OK", gui::kDefaultModalSize)) {
|
||||
show_status_ = false;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button(ICON_MD_CONTENT_COPY, ImVec2(50, 0))) {
|
||||
ImGui::SetClipboardText(prev_status_.ToString().c_str());
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
@@ -203,7 +234,7 @@ void MasterEditor::DrawAboutPopup() {
|
||||
if (about_) ImGui::OpenPopup("About");
|
||||
if (ImGui::BeginPopupModal("About", nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
Text("Yet Another Zelda3 Editor - v0.05");
|
||||
Text("Yet Another Zelda3 Editor - v%.2f", core::kYazeVersion);
|
||||
Text("Written by: scawful");
|
||||
ImGui::Spacing();
|
||||
Text("Special Thanks: Zarby89, JaredBrian");
|
||||
@@ -307,35 +338,66 @@ void MasterEditor::DrawFileMenu() {
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
MENU_ITEM2("Save", "Ctrl+S") { status_ = rom()->SaveToFile(backup_rom_); }
|
||||
MENU_ITEM2("Save", "Ctrl+S") {
|
||||
if (rom()->is_loaded()) {
|
||||
SaveRom();
|
||||
}
|
||||
}
|
||||
MENU_ITEM("Save As..") { save_as_menu = true; }
|
||||
|
||||
if (rom()->isLoaded()) {
|
||||
if (rom()->is_loaded()) {
|
||||
MENU_ITEM("Reload") { status_ = rom()->Reload(); }
|
||||
MENU_ITEM("Close") { status_ = rom()->Close(); }
|
||||
MENU_ITEM("Close") {
|
||||
status_ = rom()->Close();
|
||||
rom_assets_loaded_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (BeginMenu("Options")) {
|
||||
MenuItem("Backup ROM", "", &backup_rom_);
|
||||
MenuItem("Save New Auto", "", &save_new_auto_);
|
||||
ImGui::Separator();
|
||||
Text("Experiment Flags");
|
||||
ImGui::Checkbox("Enable Texture Streaming",
|
||||
&mutable_flags()->kLoadTexturesAsStreaming);
|
||||
ImGui::Checkbox("Enable Overworld Sprites",
|
||||
&mutable_flags()->kDrawOverworldSprites);
|
||||
ImGui::Checkbox("Use Bitmap Manager",
|
||||
&mutable_flags()->kUseBitmapManager);
|
||||
ImGui::Checkbox("Log Instructions to Debugger",
|
||||
&mutable_flags()->kLogInstructions);
|
||||
ImGui::Checkbox("Use New ImGui Input",
|
||||
&mutable_flags()->kUseNewImGuiInput);
|
||||
ImGui::Checkbox("Save All Palettes", &mutable_flags()->kSaveAllPalettes);
|
||||
ImGui::Checkbox("Save With Change Queue",
|
||||
&mutable_flags()->kSaveWithChangeQueue);
|
||||
ImGui::Checkbox("Draw Dungeon Room Graphics",
|
||||
&mutable_flags()->kDrawDungeonRoomGraphics);
|
||||
if (BeginMenu("Experiment Flags")) {
|
||||
if (BeginMenu("Overworld Flags")) {
|
||||
Checkbox("Enable Overworld Sprites",
|
||||
&mutable_flags()->overworld.kDrawOverworldSprites);
|
||||
ImGui::Separator();
|
||||
Checkbox("Save Overworld Maps",
|
||||
&mutable_flags()->overworld.kSaveOverworldMaps);
|
||||
Checkbox("Save Overworld Entrances",
|
||||
&mutable_flags()->overworld.kSaveOverworldEntrances);
|
||||
Checkbox("Save Overworld Exits",
|
||||
&mutable_flags()->overworld.kSaveOverworldExits);
|
||||
Checkbox("Save Overworld Items",
|
||||
&mutable_flags()->overworld.kSaveOverworldItems);
|
||||
Checkbox("Save Overworld Properties",
|
||||
&mutable_flags()->overworld.kSaveOverworldProperties);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (BeginMenu("Dungeon Flags")) {
|
||||
Checkbox("Draw Dungeon Room Graphics",
|
||||
&mutable_flags()->kDrawDungeonRoomGraphics);
|
||||
ImGui::Separator();
|
||||
Checkbox("Save Dungeon Maps", &mutable_flags()->kSaveDungeonMaps);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
Checkbox("Enable Console Logging", &mutable_flags()->kLogToConsole);
|
||||
Checkbox("Enable Texture Streaming",
|
||||
&mutable_flags()->kLoadTexturesAsStreaming);
|
||||
Checkbox("Use Bitmap Manager", &mutable_flags()->kUseBitmapManager);
|
||||
Checkbox("Log Instructions to Debugger",
|
||||
&mutable_flags()->kLogInstructions);
|
||||
Checkbox("Save All Palettes", &mutable_flags()->kSaveAllPalettes);
|
||||
Checkbox("Save With Change Queue",
|
||||
&mutable_flags()->kSaveWithChangeQueue);
|
||||
Checkbox("Use New ImGui Input", &mutable_flags()->kUseNewImGuiInput);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
@@ -353,7 +415,7 @@ void MasterEditor::DrawFileMenu() {
|
||||
ImGui::Begin("Save As..", &save_as_menu, ImGuiWindowFlags_AlwaysAutoResize);
|
||||
ImGui::InputText("Filename", &save_as_filename);
|
||||
if (ImGui::Button("Save", gui::kDefaultModalSize)) {
|
||||
status_ = rom()->SaveToFile(backup_rom_, save_as_filename);
|
||||
SaveRom();
|
||||
save_as_menu = false;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
@@ -388,6 +450,7 @@ void MasterEditor::DrawViewMenu() {
|
||||
static bool show_memory_viewer = false;
|
||||
static bool show_palette_editor = false;
|
||||
static bool show_emulator = false;
|
||||
static bool show_resource_label_manager = false;
|
||||
|
||||
if (show_emulator) {
|
||||
ImGui::Begin("Emulator", &show_emulator, ImGuiWindowFlags_MenuBar);
|
||||
@@ -441,12 +504,20 @@ void MasterEditor::DrawViewMenu() {
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
if (show_resource_label_manager) {
|
||||
rom()->resource_label()->DisplayLabels(&show_resource_label_manager);
|
||||
}
|
||||
|
||||
if (BeginMenu("View")) {
|
||||
MenuItem("Emulator", nullptr, &show_emulator);
|
||||
MenuItem("HEX Editor", nullptr, &show_memory_editor);
|
||||
MenuItem("ASM Editor", nullptr, &show_asm_editor);
|
||||
MenuItem("Palette Editor", nullptr, &show_palette_editor);
|
||||
MenuItem("Memory Viewer", nullptr, &show_memory_viewer);
|
||||
ImGui::Separator();
|
||||
MenuItem("Resource Label Manager", nullptr, &show_resource_label_manager);
|
||||
ImGui::Separator();
|
||||
MenuItem("Hex Editor", nullptr, &show_memory_editor);
|
||||
MenuItem("Assembly Editor", nullptr, &show_asm_editor);
|
||||
MenuItem("Palette Editor", nullptr, &show_palette_editor);
|
||||
ImGui::Separator();
|
||||
MenuItem("ImGui Demo", nullptr, &show_imgui_demo);
|
||||
MenuItem("ImGui Metrics", nullptr, &show_imgui_metrics);
|
||||
ImGui::EndMenu();
|
||||
@@ -455,12 +526,32 @@ void MasterEditor::DrawViewMenu() {
|
||||
|
||||
void MasterEditor::DrawHelpMenu() {
|
||||
static bool open_rom_help = false;
|
||||
static bool open_supported_features = false;
|
||||
if (BeginMenu("Help")) {
|
||||
if (MenuItem("How to open a ROM")) open_rom_help = true;
|
||||
if (MenuItem("Supported Features")) open_supported_features = true;
|
||||
|
||||
if (MenuItem("About")) about_ = true;
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (open_supported_features) ImGui::OpenPopup("Supported Features");
|
||||
if (ImGui::BeginPopupModal("Supported Features", nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
// TODO: Expand on details of what is currently implemented.
|
||||
ImGui::BulletText("Overworld Editing");
|
||||
ImGui::BulletText("Dungeon Editing");
|
||||
ImGui::BulletText("Sprite Editing");
|
||||
ImGui::BulletText("Palette Editing");
|
||||
ImGui::BulletText("Screen Editing");
|
||||
|
||||
if (ImGui::Button("Close", gui::kDefaultModalSize)) {
|
||||
open_supported_features = false;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (open_rom_help) ImGui::OpenPopup("Open a ROM");
|
||||
if (ImGui::BeginPopupModal("Open a ROM", nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
@@ -479,6 +570,41 @@ void MasterEditor::DrawHelpMenu() {
|
||||
}
|
||||
}
|
||||
|
||||
void MasterEditor::SaveRom() {
|
||||
if (flags()->kSaveDungeonMaps) {
|
||||
status_ = screen_editor_.SaveDungeonMaps();
|
||||
RETURN_VOID_IF_ERROR(status_);
|
||||
}
|
||||
if (flags()->overworld.kSaveOverworldMaps) {
|
||||
RETURN_VOID_IF_ERROR(
|
||||
status_ = overworld_editor_.overworld()->CreateTile32Tilemap());
|
||||
status_ = overworld_editor_.overworld()->SaveMap32Tiles();
|
||||
RETURN_VOID_IF_ERROR(status_);
|
||||
status_ = overworld_editor_.overworld()->SaveMap16Tiles();
|
||||
RETURN_VOID_IF_ERROR(status_);
|
||||
status_ = overworld_editor_.overworld()->SaveOverworldMaps();
|
||||
RETURN_VOID_IF_ERROR(status_);
|
||||
}
|
||||
if (flags()->overworld.kSaveOverworldEntrances) {
|
||||
status_ = overworld_editor_.overworld()->SaveEntrances();
|
||||
RETURN_VOID_IF_ERROR(status_);
|
||||
}
|
||||
if (flags()->overworld.kSaveOverworldExits) {
|
||||
status_ = overworld_editor_.overworld()->SaveExits();
|
||||
RETURN_VOID_IF_ERROR(status_);
|
||||
}
|
||||
if (flags()->overworld.kSaveOverworldItems) {
|
||||
status_ = overworld_editor_.overworld()->SaveItems();
|
||||
RETURN_VOID_IF_ERROR(status_);
|
||||
}
|
||||
if (flags()->overworld.kSaveOverworldProperties) {
|
||||
status_ = overworld_editor_.overworld()->SaveMapProperties();
|
||||
RETURN_VOID_IF_ERROR(status_);
|
||||
}
|
||||
|
||||
status_ = rom()->SaveToFile(backup_rom_, save_new_auto_);
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
} // namespace yaze
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef YAZE_APP_EDITOR_MASTER_EDITOR_H
|
||||
#define YAZE_APP_EDITOR_MASTER_EDITOR_H
|
||||
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS 1
|
||||
|
||||
#include <ImGuiColorTextEdit/TextEditor.h>
|
||||
#include <ImGuiFileDialog/ImGuiFileDialog.h>
|
||||
#include <imgui/imgui.h>
|
||||
@@ -55,9 +57,12 @@ class MasterEditor : public SharedROM,
|
||||
void DrawViewMenu();
|
||||
void DrawHelpMenu();
|
||||
|
||||
void SaveRom();
|
||||
|
||||
bool about_ = false;
|
||||
bool rom_info_ = false;
|
||||
bool backup_rom_ = true;
|
||||
bool backup_rom_ = false;
|
||||
bool save_new_auto_ = true;
|
||||
bool show_status_ = false;
|
||||
bool rom_assets_loaded_ = false;
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "app/gfx/snes_palette.h"
|
||||
#include "app/gfx/snes_tile.h"
|
||||
#include "app/gui/canvas.h"
|
||||
#include "app/gui/color.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/gui/input.h"
|
||||
#include "app/gui/pipeline.h"
|
||||
@@ -33,89 +34,15 @@ absl::Status GfxGroupEditor::Update() {
|
||||
if (ImGui::BeginTabBar("GfxGroupEditor")) {
|
||||
if (ImGui::BeginTabItem("Main")) {
|
||||
gui::InputHexByte("Selected Blockset", &selected_blockset_);
|
||||
ImGui::Text("Values");
|
||||
if (ImGui::BeginTable("##BlocksetTable", 2, ImGuiTableFlags_Borders,
|
||||
ImVec2(0, 0))) {
|
||||
TableSetupColumn("Inputs", ImGuiTableColumnFlags_WidthStretch,
|
||||
ImGui::GetContentRegionAvail().x);
|
||||
TableSetupColumn("Sheets", ImGuiTableColumnFlags_WidthFixed, 256);
|
||||
TableHeadersRow();
|
||||
TableNextRow();
|
||||
TableNextColumn();
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
for (int i = 0; i < 8; i++) {
|
||||
ImGui::SetNextItemWidth(100.f);
|
||||
gui::InputHexByte(("##blockset0" + std::to_string(i)).c_str(),
|
||||
&rom()->main_blockset_ids[selected_blockset_][i]);
|
||||
if (i != 3 && i != 7) {
|
||||
SameLine();
|
||||
}
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
TableNextColumn();
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
for (int i = 0; i < 8; i++) {
|
||||
int sheet_id = rom()->main_blockset_ids[selected_blockset_][i];
|
||||
auto &sheet = *rom()->bitmap_manager()[sheet_id];
|
||||
if (sheet_id != last_sheet_id_) {
|
||||
last_sheet_id_ = sheet_id;
|
||||
auto palette_group = rom()->palette_group("ow_main");
|
||||
auto palette = palette_group[preview_palette_id_];
|
||||
sheet.ApplyPalette(palette);
|
||||
rom()->UpdateBitmap(&sheet);
|
||||
}
|
||||
gui::BitmapCanvasPipeline(blockset_canvas_, sheet, 256, 0x10 * 0x04,
|
||||
0x20, true, false, 22);
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
DrawBlocksetViewer();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("Rooms")) {
|
||||
gui::InputHexByte("Selected Blockset", &selected_roomset_);
|
||||
|
||||
ImGui::Text("Values - Overwrites 4 of main blockset");
|
||||
if (ImGui::BeginTable("##Roomstable", 2, ImGuiTableFlags_Borders,
|
||||
ImVec2(0, 0))) {
|
||||
TableSetupColumn("Inputs", ImGuiTableColumnFlags_WidthStretch,
|
||||
ImGui::GetContentRegionAvail().x);
|
||||
TableSetupColumn("Sheets", ImGuiTableColumnFlags_WidthFixed, 256);
|
||||
TableHeadersRow();
|
||||
TableNextRow();
|
||||
TableNextColumn();
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
ImGui::SetNextItemWidth(100.f);
|
||||
gui::InputHexByte(("##roomset0" + std::to_string(i)).c_str(),
|
||||
&rom()->room_blockset_ids[selected_roomset_][i]);
|
||||
if (i != 3 && i != 7) {
|
||||
SameLine();
|
||||
}
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
TableNextColumn();
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int sheet_id = rom()->room_blockset_ids[selected_roomset_][i];
|
||||
auto &sheet = *rom()->bitmap_manager()[sheet_id];
|
||||
gui::BitmapCanvasPipeline(roomset_canvas_, sheet, 256, 0x10 * 0x04,
|
||||
0x20, true, false, 23);
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
DrawRoomsetViewer();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
@@ -123,43 +50,12 @@ absl::Status GfxGroupEditor::Update() {
|
||||
gui::InputHexByte("Selected Spriteset", &selected_spriteset_);
|
||||
|
||||
ImGui::Text("Values");
|
||||
if (ImGui::BeginTable("##SpritesTable", 2, ImGuiTableFlags_Borders,
|
||||
ImVec2(0, 0))) {
|
||||
TableSetupColumn("Inputs", ImGuiTableColumnFlags_WidthStretch,
|
||||
ImGui::GetContentRegionAvail().x);
|
||||
TableSetupColumn("Sheets", ImGuiTableColumnFlags_WidthFixed, 256);
|
||||
TableHeadersRow();
|
||||
TableNextRow();
|
||||
TableNextColumn();
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
ImGui::SetNextItemWidth(100.f);
|
||||
gui::InputHexByte(("##spriteset0" + std::to_string(i)).c_str(),
|
||||
&rom()->spriteset_ids[selected_spriteset_][i]);
|
||||
if (i != 3 && i != 7) {
|
||||
SameLine();
|
||||
}
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
TableNextColumn();
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int sheet_id = rom()->spriteset_ids[selected_spriteset_][i];
|
||||
auto sheet = *rom()->bitmap_manager()[sheet_id];
|
||||
gui::BitmapCanvasPipeline(spriteset_canvas_, sheet, 256,
|
||||
0x10 * 0x04, 0x20, true, false, 24);
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
DrawSpritesetViewer();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("Palettes")) {
|
||||
DrawPaletteViewer();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
@@ -173,6 +69,183 @@ absl::Status GfxGroupEditor::Update() {
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
void GfxGroupEditor::DrawBlocksetViewer(bool sheet_only) {
|
||||
if (ImGui::BeginTable("##BlocksetTable", sheet_only ? 1 : 2,
|
||||
ImGuiTableFlags_Borders, ImVec2(0, 0))) {
|
||||
if (!sheet_only) {
|
||||
TableSetupColumn("Inputs", ImGuiTableColumnFlags_WidthStretch,
|
||||
ImGui::GetContentRegionAvail().x);
|
||||
}
|
||||
|
||||
TableSetupColumn("Sheets", ImGuiTableColumnFlags_WidthFixed, 256);
|
||||
TableHeadersRow();
|
||||
TableNextRow();
|
||||
if (!sheet_only) {
|
||||
TableNextColumn();
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
for (int i = 0; i < 8; i++) {
|
||||
ImGui::SetNextItemWidth(100.f);
|
||||
gui::InputHexByte(("0x" + std::to_string(i)).c_str(),
|
||||
&rom()->main_blockset_ids[selected_blockset_][i]);
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
}
|
||||
TableNextColumn();
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
for (int i = 0; i < 8; i++) {
|
||||
int sheet_id = rom()->main_blockset_ids[selected_blockset_][i];
|
||||
auto &sheet = *rom()->bitmap_manager()[sheet_id];
|
||||
// if (sheet_id != last_sheet_id_) {
|
||||
// last_sheet_id_ = sheet_id;
|
||||
// auto palette_group = rom()->palette_group("ow_main");
|
||||
// auto palette = palette_group[preview_palette_id_];
|
||||
// sheet.ApplyPalette(palette);
|
||||
// rom()->UpdateBitmap(&sheet);
|
||||
// }
|
||||
gui::BitmapCanvasPipeline(blockset_canvas_, sheet, 256, 0x10 * 0x04,
|
||||
0x20, true, false, 22);
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
void GfxGroupEditor::DrawRoomsetViewer() {
|
||||
ImGui::Text("Values - Overwrites 4 of main blockset");
|
||||
if (ImGui::BeginTable("##Roomstable", 2, ImGuiTableFlags_Borders,
|
||||
ImVec2(0, 0))) {
|
||||
TableSetupColumn("Inputs", ImGuiTableColumnFlags_WidthStretch,
|
||||
ImGui::GetContentRegionAvail().x);
|
||||
TableSetupColumn("Sheets", ImGuiTableColumnFlags_WidthFixed, 256);
|
||||
TableHeadersRow();
|
||||
TableNextRow();
|
||||
TableNextColumn();
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
ImGui::SetNextItemWidth(100.f);
|
||||
gui::InputHexByte(("0x" + std::to_string(i)).c_str(),
|
||||
&rom()->room_blockset_ids[selected_roomset_][i]);
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
TableNextColumn();
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int sheet_id = rom()->room_blockset_ids[selected_roomset_][i];
|
||||
auto &sheet = *rom()->bitmap_manager()[sheet_id];
|
||||
gui::BitmapCanvasPipeline(roomset_canvas_, sheet, 256, 0x10 * 0x04,
|
||||
0x20, true, false, 23);
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
void GfxGroupEditor::DrawSpritesetViewer(bool sheet_only) {
|
||||
if (ImGui::BeginTable("##SpritesTable", sheet_only ? 1 : 2,
|
||||
ImGuiTableFlags_Borders, ImVec2(0, 0))) {
|
||||
if (!sheet_only) {
|
||||
TableSetupColumn("Inputs", ImGuiTableColumnFlags_WidthStretch,
|
||||
ImGui::GetContentRegionAvail().x);
|
||||
}
|
||||
TableSetupColumn("Sheets", ImGuiTableColumnFlags_WidthFixed, 256);
|
||||
TableHeadersRow();
|
||||
TableNextRow();
|
||||
if (!sheet_only) {
|
||||
TableNextColumn();
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
ImGui::SetNextItemWidth(100.f);
|
||||
gui::InputHexByte(("0x" + std::to_string(i)).c_str(),
|
||||
&rom()->spriteset_ids[selected_spriteset_][i]);
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
}
|
||||
TableNextColumn();
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int sheet_id = rom()->spriteset_ids[selected_spriteset_][i];
|
||||
auto sheet = *rom()->bitmap_manager()[115 + sheet_id];
|
||||
gui::BitmapCanvasPipeline(spriteset_canvas_, sheet, 256, 0x10 * 0x04,
|
||||
0x20, true, false, 24);
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
void DrawPaletteFromPaletteGroup(gfx::SnesPalette &palette) {
|
||||
for (int n = 0; n < palette.size(); n++) {
|
||||
ImGui::PushID(n);
|
||||
if ((n % 8) != 0) ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
|
||||
|
||||
auto popup_id = absl::StrCat("Palette", n);
|
||||
|
||||
// Small icon of the color in the palette
|
||||
if (gui::SnesColorButton(popup_id, palette[n],
|
||||
ImGuiColorEditFlags_NoAlpha |
|
||||
ImGuiColorEditFlags_NoPicker |
|
||||
ImGuiColorEditFlags_NoTooltip)) {
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void GfxGroupEditor::DrawPaletteViewer() {
|
||||
static uint8_t selected_paletteset = 0;
|
||||
|
||||
gui::InputHexByte("Selected Paletteset", &selected_paletteset);
|
||||
|
||||
auto dungeon_main_palette_val = rom()->paletteset_ids[selected_paletteset][0];
|
||||
auto dungeon_spr_pal_1_val = rom()->paletteset_ids[selected_paletteset][1];
|
||||
auto dungeon_spr_pal_2_val = rom()->paletteset_ids[selected_paletteset][2];
|
||||
auto dungeon_spr_pal_3_val = rom()->paletteset_ids[selected_paletteset][3];
|
||||
|
||||
gui::InputHexByte("Dungeon Main", &dungeon_main_palette_val);
|
||||
gui::InputHexByte("Dungeon Spr Pal 1", &dungeon_spr_pal_1_val);
|
||||
gui::InputHexByte("Dungeon Spr Pal 2", &dungeon_spr_pal_2_val);
|
||||
gui::InputHexByte("Dungeon Spr Pal 3", &dungeon_spr_pal_3_val);
|
||||
|
||||
auto &palette =
|
||||
*rom()
|
||||
->mutable_palette_group(
|
||||
"dungeon_main")[rom()->paletteset_ids[selected_paletteset][0]]
|
||||
.mutable_palette(0);
|
||||
DrawPaletteFromPaletteGroup(palette);
|
||||
auto &spr_aux_pal1 =
|
||||
*rom()
|
||||
->mutable_palette_group(
|
||||
"sprites_aux1")[rom()->paletteset_ids[selected_paletteset][1]]
|
||||
.mutable_palette(0);
|
||||
DrawPaletteFromPaletteGroup(spr_aux_pal1);
|
||||
auto &spr_aux_pal2 =
|
||||
*rom()
|
||||
->mutable_palette_group(
|
||||
"sprites_aux2")[rom()->paletteset_ids[selected_paletteset][2]]
|
||||
.mutable_palette(0);
|
||||
DrawPaletteFromPaletteGroup(spr_aux_pal2);
|
||||
auto &spr_aux_pal3 =
|
||||
*rom()
|
||||
->mutable_palette_group(
|
||||
"sprites_aux3")[rom()->paletteset_ids[selected_paletteset][3]]
|
||||
.mutable_palette(0);
|
||||
DrawPaletteFromPaletteGroup(spr_aux_pal3);
|
||||
}
|
||||
|
||||
void GfxGroupEditor::InitBlockset(gfx::Bitmap tile16_blockset) {
|
||||
tile16_blockset_bmp_ = tile16_blockset;
|
||||
}
|
||||
|
||||
@@ -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/gui/widgets.h"
|
||||
#include "app/rom.h"
|
||||
#include "app/zelda3/overworld.h"
|
||||
@@ -27,6 +27,17 @@ class GfxGroupEditor : public SharedROM {
|
||||
public:
|
||||
absl::Status Update();
|
||||
|
||||
void DrawBlocksetViewer(bool sheet_only = false);
|
||||
void DrawRoomsetViewer();
|
||||
void DrawSpritesetViewer(bool sheet_only = false);
|
||||
void DrawPaletteViewer();
|
||||
|
||||
void SetSelectedBlockset(uint8_t blockset) { selected_blockset_ = blockset; }
|
||||
void SetSelectedRoomset(uint8_t roomset) { selected_roomset_ = roomset; }
|
||||
void SetSelectedSpriteset(uint8_t spriteset) {
|
||||
selected_spriteset_ = spriteset;
|
||||
}
|
||||
|
||||
void InitBlockset(gfx::Bitmap tile16_blockset);
|
||||
|
||||
private:
|
||||
@@ -36,11 +47,13 @@ class GfxGroupEditor : public SharedROM {
|
||||
uint8_t selected_roomset_ = 0;
|
||||
uint8_t selected_spriteset_ = 0;
|
||||
|
||||
PaletteEditor palette_editor_;
|
||||
|
||||
gui::Canvas blockset_canvas_;
|
||||
gui::Canvas roomset_canvas_;
|
||||
gui::Canvas spriteset_canvas_;
|
||||
|
||||
gfx::SNESPalette palette_;
|
||||
gfx::SnesPalette palette_;
|
||||
gfx::PaletteGroup palette_group_;
|
||||
gfx::Bitmap tile16_blockset_bmp_;
|
||||
|
||||
|
||||
@@ -35,6 +35,15 @@ namespace app {
|
||||
namespace editor {
|
||||
|
||||
absl::Status PaletteEditor::Update() {
|
||||
if (rom()->is_loaded()) {
|
||||
// Initialize the labels
|
||||
for (int i = 0; i < kNumPalettes; i++) {
|
||||
rom()->resource_label()->CreateOrGetLabel(
|
||||
"Palette Group Name", std::to_string(i),
|
||||
std::string(kPaletteGroupNames[i]));
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::BeginTable("paletteEditorTable", 2,
|
||||
ImGuiTableFlags_Reorderable |
|
||||
ImGuiTableFlags_Resizable |
|
||||
@@ -55,7 +64,9 @@ absl::Status PaletteEditor::Update() {
|
||||
}
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Test Column");
|
||||
if (gui::SnesColorEdit4("Color Picker", current_color_,
|
||||
ImGuiColorEditFlags_NoAlpha)) {
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
@@ -64,14 +75,14 @@ absl::Status PaletteEditor::Update() {
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
void PaletteEditor::EditColorInPalette(gfx::SNESPalette& palette, int index) {
|
||||
void PaletteEditor::EditColorInPalette(gfx::SnesPalette& palette, int index) {
|
||||
if (index >= palette.size()) {
|
||||
// Handle error: the index is out of bounds
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the current color
|
||||
auto currentColor = palette.GetColor(index).GetRGB();
|
||||
auto currentColor = palette.GetColor(index).rgb();
|
||||
if (ImGui::ColorPicker4("Color Picker", (float*)&palette[index])) {
|
||||
// The color was modified, update it in the palette
|
||||
palette(index, currentColor);
|
||||
@@ -79,56 +90,57 @@ void PaletteEditor::EditColorInPalette(gfx::SNESPalette& palette, int index) {
|
||||
}
|
||||
|
||||
void PaletteEditor::ResetColorToOriginal(
|
||||
gfx::SNESPalette& palette, int index,
|
||||
const gfx::SNESPalette& originalPalette) {
|
||||
gfx::SnesPalette& palette, int index,
|
||||
const gfx::SnesPalette& originalPalette) {
|
||||
if (index >= palette.size() || index >= originalPalette.size()) {
|
||||
// Handle error: the index is out of bounds
|
||||
return;
|
||||
}
|
||||
|
||||
auto originalColor = originalPalette.GetColor(index).GetRGB();
|
||||
auto originalColor = originalPalette.GetColor(index).rgb();
|
||||
palette(index, originalColor);
|
||||
}
|
||||
|
||||
absl::Status PaletteEditor::DrawPaletteGroup(int category) {
|
||||
if (!rom()->isLoaded()) {
|
||||
if (!rom()->is_loaded()) {
|
||||
return absl::NotFoundError("ROM not open, no palettes to display");
|
||||
}
|
||||
|
||||
const auto size =
|
||||
rom()->palette_group(kPaletteGroupNames[category].data()).size();
|
||||
auto palettes = rom()->palette_group(kPaletteGroupNames[category].data());
|
||||
auto palettes =
|
||||
rom()->mutable_palette_group(kPaletteGroupNames[category].data());
|
||||
static bool edit_color = false;
|
||||
for (int j = 0; j < size; j++) {
|
||||
ImGui::Text("%d", j);
|
||||
|
||||
auto palette = palettes[j];
|
||||
auto pal_size = palette.size();
|
||||
// ImGui::Text("%d", j);
|
||||
rom()->resource_label()->SelectableLabelWithNameEdit(
|
||||
false, "Palette Group Name", std::to_string(j),
|
||||
std::string(kPaletteGroupNames[category]));
|
||||
auto palette = palettes->mutable_palette(j);
|
||||
auto pal_size = palette->size();
|
||||
|
||||
for (int n = 0; n < pal_size; n++) {
|
||||
ImGui::PushID(n);
|
||||
if ((n % 8) != 0) ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
|
||||
if ((n % 7) != 0) ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
|
||||
|
||||
auto popup_id =
|
||||
absl::StrCat(kPaletteCategoryNames[category].data(), j, "_", n);
|
||||
|
||||
// Small icon of the color in the palette
|
||||
if (gui::SNESColorButton(popup_id, palette[n], palette_button_flags)) {
|
||||
edit_color = true;
|
||||
if (gui::SnesColorButton(popup_id, *palette->mutable_color(n),
|
||||
palette_button_flags)) {
|
||||
current_color_ = palette->GetColor(n);
|
||||
// EditColorInPalette(*palette, n);
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopupContextItem(popup_id.c_str())) {
|
||||
RETURN_IF_ERROR(HandleColorPopup(palette, category, j, n))
|
||||
RETURN_IF_ERROR(HandleColorPopup(*palette, category, j, n))
|
||||
}
|
||||
|
||||
if (edit_color) {
|
||||
// The color button was clicked, open the popup
|
||||
if (ImGui::ColorEdit4(popup_id.c_str(),
|
||||
gfx::ToFloatArray(palette[n]).data(),
|
||||
palette_button_flags)) {
|
||||
EditColorInPalette(palette, n);
|
||||
}
|
||||
}
|
||||
// if (gui::SnesColorEdit4(popup_id.c_str(), (*palette)[n],
|
||||
// palette_button_flags)) {
|
||||
// EditColorInPalette(*palette, n);
|
||||
// }
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
@@ -136,16 +148,15 @@ absl::Status PaletteEditor::DrawPaletteGroup(int category) {
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status PaletteEditor::HandleColorPopup(gfx::SNESPalette& palette, int i,
|
||||
absl::Status PaletteEditor::HandleColorPopup(gfx::SnesPalette& palette, int i,
|
||||
int j, int n) {
|
||||
auto col = gfx::ToFloatArray(palette[n]);
|
||||
if (ImGui::ColorEdit4("Edit Color", col.data(), color_popup_flags)) {
|
||||
if (gui::SnesColorEdit4("Edit Color", palette[n], color_popup_flags)) {
|
||||
RETURN_IF_ERROR(rom()->UpdatePaletteColor(kPaletteGroupNames[i].data(), j,
|
||||
n, palette[n]))
|
||||
}
|
||||
|
||||
if (ImGui::Button("Copy as..", ImVec2(-1, 0))) ImGui::OpenPopup("Copy");
|
||||
|
||||
if (ImGui::BeginPopup("Copy")) {
|
||||
int cr = IM_F32_TO_INT8_SAT(col[0]);
|
||||
int cg = IM_F32_TO_INT8_SAT(col[1]);
|
||||
@@ -167,7 +178,7 @@ absl::Status PaletteEditor::HandleColorPopup(gfx::SNESPalette& palette, int i,
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
void PaletteEditor::DisplayPalette(gfx::SNESPalette& palette, bool loaded) {
|
||||
void PaletteEditor::DisplayPalette(gfx::SnesPalette& palette, bool loaded) {
|
||||
static ImVec4 color = ImVec4(0, 0, 0, 255.f);
|
||||
ImGuiColorEditFlags misc_flags = ImGuiColorEditFlags_AlphaPreview |
|
||||
ImGuiColorEditFlags_NoDragDrop |
|
||||
@@ -245,7 +256,7 @@ void PaletteEditor::DisplayPalette(gfx::SNESPalette& palette, bool loaded) {
|
||||
}
|
||||
}
|
||||
|
||||
void PaletteEditor::DrawPortablePalette(gfx::SNESPalette& palette) {
|
||||
void PaletteEditor::DrawPortablePalette(gfx::SnesPalette& palette) {
|
||||
static bool init = false;
|
||||
if (!init) {
|
||||
InitializeSavedPalette(palette);
|
||||
|
||||
@@ -26,19 +26,19 @@ static constexpr absl::string_view kPaletteGroupNames[] = {
|
||||
"ow_mini_map", "3d_object", "3d_object"};
|
||||
|
||||
struct PaletteChange {
|
||||
std::string groupName;
|
||||
size_t paletteIndex;
|
||||
size_t colorIndex;
|
||||
gfx::SNESColor originalColor;
|
||||
gfx::SNESColor newColor;
|
||||
std::string group_name;
|
||||
size_t palette_index;
|
||||
size_t color_index;
|
||||
gfx::SnesColor original_color;
|
||||
gfx::SnesColor new_color;
|
||||
};
|
||||
|
||||
class PaletteEditorHistory {
|
||||
public:
|
||||
// Record a change in the palette editor
|
||||
void RecordChange(const std::string& groupName, size_t paletteIndex,
|
||||
size_t colorIndex, const gfx::SNESColor& originalColor,
|
||||
const gfx::SNESColor& newColor) {
|
||||
size_t colorIndex, const gfx::SnesColor& originalColor,
|
||||
const gfx::SnesColor& newColor) {
|
||||
// Check size and remove the oldest if necessary
|
||||
if (recentChanges.size() >= maxHistorySize) {
|
||||
recentChanges.pop_front();
|
||||
@@ -55,19 +55,19 @@ class PaletteEditorHistory {
|
||||
}
|
||||
|
||||
// Restore the original color
|
||||
gfx::SNESColor GetOriginalColor(const std::string& groupName,
|
||||
gfx::SnesColor GetOriginalColor(const std::string& groupName,
|
||||
size_t paletteIndex,
|
||||
size_t colorIndex) const {
|
||||
for (const auto& change : recentChanges) {
|
||||
if (change.groupName == groupName &&
|
||||
change.paletteIndex == paletteIndex &&
|
||||
change.colorIndex == colorIndex) {
|
||||
return change.originalColor;
|
||||
if (change.group_name == groupName &&
|
||||
change.palette_index == paletteIndex &&
|
||||
change.color_index == colorIndex) {
|
||||
return change.original_color;
|
||||
}
|
||||
}
|
||||
// Handle error or return default (this is just an example,
|
||||
// handle as appropriate for your application)
|
||||
return gfx::SNESColor();
|
||||
return gfx::SnesColor();
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -80,21 +80,21 @@ class PaletteEditor : public SharedROM {
|
||||
absl::Status Update();
|
||||
absl::Status DrawPaletteGroups();
|
||||
|
||||
void EditColorInPalette(gfx::SNESPalette& palette, int index);
|
||||
void ResetColorToOriginal(gfx::SNESPalette& palette, int index,
|
||||
const gfx::SNESPalette& originalPalette);
|
||||
void DisplayPalette(gfx::SNESPalette& palette, bool loaded);
|
||||
void DrawPortablePalette(gfx::SNESPalette& palette);
|
||||
void EditColorInPalette(gfx::SnesPalette& palette, int index);
|
||||
void ResetColorToOriginal(gfx::SnesPalette& palette, int index,
|
||||
const gfx::SnesPalette& originalPalette);
|
||||
void DisplayPalette(gfx::SnesPalette& palette, bool loaded);
|
||||
void DrawPortablePalette(gfx::SnesPalette& palette);
|
||||
absl::Status DrawPaletteGroup(int category);
|
||||
|
||||
private:
|
||||
absl::Status DrawPaletteGroup(int category);
|
||||
absl::Status HandleColorPopup(gfx::SNESPalette& palette, int i, int j, int n);
|
||||
absl::Status HandleColorPopup(gfx::SnesPalette& palette, int i, int j, int n);
|
||||
|
||||
void InitializeSavedPalette(const gfx::SNESPalette& palette) {
|
||||
void InitializeSavedPalette(const gfx::SnesPalette& palette) {
|
||||
for (int n = 0; n < palette.size(); n++) {
|
||||
saved_palette_[n].x = palette.GetColor(n).GetRGB().x / 255;
|
||||
saved_palette_[n].y = palette.GetColor(n).GetRGB().y / 255;
|
||||
saved_palette_[n].z = palette.GetColor(n).GetRGB().z / 255;
|
||||
saved_palette_[n].x = palette.GetColor(n).rgb().x / 255;
|
||||
saved_palette_[n].y = palette.GetColor(n).rgb().y / 255;
|
||||
saved_palette_[n].z = palette.GetColor(n).rgb().z / 255;
|
||||
saved_palette_[n].w = 255; // Alpha
|
||||
}
|
||||
}
|
||||
@@ -104,12 +104,11 @@ class PaletteEditor : public SharedROM {
|
||||
PaletteEditorHistory history_;
|
||||
|
||||
ImVec4 saved_palette_[256] = {};
|
||||
ImVec4 current_color_;
|
||||
gfx::SnesColor current_color_;
|
||||
|
||||
ImGuiColorEditFlags color_popup_flags =
|
||||
ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoAlpha;
|
||||
ImGuiColorEditFlags palette_button_flags =
|
||||
ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoTooltip;
|
||||
ImGuiColorEditFlags palette_button_flags = ImGuiColorEditFlags_NoAlpha;
|
||||
ImGuiColorEditFlags palette_button_flags_2 = ImGuiColorEditFlags_NoAlpha |
|
||||
ImGuiColorEditFlags_NoPicker |
|
||||
ImGuiColorEditFlags_NoTooltip;
|
||||
|
||||
@@ -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,80 +38,97 @@ 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());
|
||||
ImVector<std::string> tile16_names;
|
||||
for (int i = 0; i < 0x200; ++i) {
|
||||
std::string str = core::UppercaseHexByte(all_tiles_types_[i]);
|
||||
tile16_names.push_back(str);
|
||||
}
|
||||
|
||||
*tile8_source_canvas_.mutable_labels(0) = tile16_names;
|
||||
*tile8_source_canvas_.custom_labels_enabled() = true;
|
||||
}
|
||||
|
||||
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,
|
||||
ImVec2(0, 0))) {
|
||||
TableSetupColumn("Tiles", ImGuiTableColumnFlags_WidthFixed,
|
||||
ImGui::GetContentRegionAvail().x);
|
||||
TableSetupColumn("Properties", ImGuiTableColumnFlags_WidthStretch,
|
||||
ImGui::GetContentRegionAvail().x);
|
||||
TableHeadersRow();
|
||||
TableNextRow();
|
||||
TableNextColumn();
|
||||
RETURN_IF_ERROR(UpdateBlockset());
|
||||
|
||||
TableNextColumn();
|
||||
RETURN_IF_ERROR(UpdateTile16Edit());
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
// Create a tab for Tile16 Transfer
|
||||
if (BeginTabItem("Tile16 Transfer")) {
|
||||
if (BeginTable("#Tile16TransferTable", 2,
|
||||
ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable,
|
||||
ImVec2(0, 0))) {
|
||||
TableSetupColumn("Current ROM Tiles", ImGuiTableColumnFlags_WidthFixed,
|
||||
ImGui::GetContentRegionAvail().x / 2);
|
||||
TableSetupColumn("Transfer ROM Tiles", ImGuiTableColumnFlags_WidthFixed,
|
||||
ImGui::GetContentRegionAvail().x / 2);
|
||||
TableHeadersRow();
|
||||
TableNextRow();
|
||||
|
||||
TableNextColumn();
|
||||
RETURN_IF_ERROR(UpdateBlockset());
|
||||
|
||||
TableNextColumn();
|
||||
RETURN_IF_ERROR(UpdateTransferTileCanvas());
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
RETURN_IF_ERROR(DrawTile16Editor());
|
||||
RETURN_IF_ERROR(UpdateTile16Transfer());
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status Tile16Editor::DrawTile16Editor() {
|
||||
if (BeginTabItem("Tile16 Editing")) {
|
||||
if (BeginTable("#Tile16EditorTable", 2, TABLE_BORDERS_RESIZABLE,
|
||||
ImVec2(0, 0))) {
|
||||
TableSetupColumn("Tiles", ImGuiTableColumnFlags_WidthFixed,
|
||||
ImGui::GetContentRegionAvail().x);
|
||||
TableSetupColumn("Properties", ImGuiTableColumnFlags_WidthStretch,
|
||||
ImGui::GetContentRegionAvail().x);
|
||||
TableHeadersRow();
|
||||
TableNextRow();
|
||||
TableNextColumn();
|
||||
RETURN_IF_ERROR(UpdateBlockset());
|
||||
|
||||
TableNextColumn();
|
||||
RETURN_IF_ERROR(UpdateTile16Edit());
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status Tile16Editor::UpdateTile16Transfer() {
|
||||
if (BeginTabItem("Tile16 Transfer")) {
|
||||
if (BeginTable("#Tile16TransferTable", 2, TABLE_BORDERS_RESIZABLE,
|
||||
ImVec2(0, 0))) {
|
||||
TableSetupColumn("Current ROM Tiles", ImGuiTableColumnFlags_WidthFixed,
|
||||
ImGui::GetContentRegionAvail().x / 2);
|
||||
TableSetupColumn("Transfer ROM Tiles", ImGuiTableColumnFlags_WidthFixed,
|
||||
ImGui::GetContentRegionAvail().x / 2);
|
||||
TableHeadersRow();
|
||||
TableNextRow();
|
||||
|
||||
TableNextColumn();
|
||||
RETURN_IF_ERROR(UpdateBlockset());
|
||||
|
||||
TableNextColumn();
|
||||
RETURN_IF_ERROR(UpdateTransferTileCanvas());
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
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("##Tile16EditorBlocksetScrollRegion");
|
||||
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;
|
||||
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_]);
|
||||
@@ -120,34 +139,84 @@ absl::Status Tile16Editor::UpdateBlockset() {
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status Tile16Editor::DrawToCurrentTile16(ImVec2 click_position) {
|
||||
constexpr int tile8_size = 8;
|
||||
constexpr int tile16_size = 16;
|
||||
|
||||
// Calculate the tile index for x and y based on the click_position
|
||||
// Adjusting for Tile16 (16x16) which contains 4 Tile8 (8x8)
|
||||
int tile_index_x = static_cast<int>(click_position.x) / tile8_size;
|
||||
int tile_index_y = static_cast<int>(click_position.y) / tile8_size;
|
||||
std::cout << "Tile Index X: " << tile_index_x << std::endl;
|
||||
std::cout << "Tile Index Y: " << tile_index_y << std::endl;
|
||||
|
||||
// Calculate the pixel start position within the Tile16
|
||||
ImVec2 start_position;
|
||||
start_position.x = ((tile_index_x) / 4) * 0x40;
|
||||
start_position.y = ((tile_index_y) / 4) * 0x40;
|
||||
std::cout << "Start Position X: " << start_position.x << std::endl;
|
||||
std::cout << "Start Position Y: " << start_position.y << std::endl;
|
||||
|
||||
// Draw the Tile8 to the correct position within the Tile16
|
||||
for (int y = 0; y < tile8_size; ++y) {
|
||||
for (int x = 0; x < tile8_size; ++x) {
|
||||
int pixel_index =
|
||||
(start_position.y + y) * tile16_size + ((start_position.x) + x);
|
||||
int gfx_pixel_index = y * tile8_size + x;
|
||||
current_tile16_bmp_.WriteToPixel(
|
||||
pixel_index,
|
||||
current_gfx_individual_[current_tile8_].data()[gfx_pixel_index]);
|
||||
}
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status Tile16Editor::UpdateTile16Edit() {
|
||||
if (ImGui::BeginChild("Tile8 Selector",
|
||||
ImVec2(ImGui::GetContentRegionAvail().x, 0x100),
|
||||
ImVec2(ImGui::GetContentRegionAvail().x, 0x175),
|
||||
true)) {
|
||||
tile8_source_canvas_.DrawBackground(
|
||||
ImVec2(core::kTilesheetWidth * 2, core::kTilesheetHeight * 0x10 * 2));
|
||||
ImVec2(core::kTilesheetWidth * 4, core::kTilesheetHeight * 0x10 * 4));
|
||||
tile8_source_canvas_.DrawContextMenu();
|
||||
tile8_source_canvas_.DrawTileSelector(16);
|
||||
tile8_source_canvas_.DrawBitmap(current_gfx_bmp_, 0, 0, 2.0f);
|
||||
tile8_source_canvas_.DrawGrid(16.0f);
|
||||
if (tile8_source_canvas_.DrawTileSelector(32)) {
|
||||
current_gfx_individual_[current_tile8_].ApplyPaletteWithTransparent(
|
||||
rom()->palette_group("ow_main")[0], current_palette_);
|
||||
rom()->UpdateBitmap(¤t_gfx_individual_[current_tile8_]);
|
||||
}
|
||||
tile8_source_canvas_.DrawBitmap(current_gfx_bmp_, 0, 0, 4.0f);
|
||||
tile8_source_canvas_.DrawGrid(32.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(¤t_gfx_individual_[current_tile8_]);
|
||||
}
|
||||
|
||||
ImGui::Text("Tile16 ID: %d", current_tile16_);
|
||||
ImGui::Text("Tile8 ID: %d", current_tile8_);
|
||||
|
||||
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(¤t_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_, 2.0f);
|
||||
|
||||
tile16_edit_canvas_.DrawGrid(128.0f);
|
||||
if (!tile8_source_canvas_.points().empty()) {
|
||||
if (tile16_edit_canvas_.DrawTilePainter(
|
||||
current_gfx_individual_[current_tile8_], 16, 2.0f)) {
|
||||
RETURN_IF_ERROR(
|
||||
DrawToCurrentTile16(tile16_edit_canvas_.drawn_tile_position()));
|
||||
rom()->UpdateBitmap(¤t_tile16_bmp_);
|
||||
}
|
||||
}
|
||||
tile16_edit_canvas_.DrawGrid(64.0f);
|
||||
tile16_edit_canvas_.DrawOverlay();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
@@ -162,11 +231,22 @@ void Tile16Editor::DrawTileEditControls() {
|
||||
gui::InputHexByte("Palette", ¬ify_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()]);
|
||||
rom()->UpdateBitmap(¤t_gfx_bmp_);
|
||||
auto palette = palettesets_[current_palette_].main;
|
||||
auto value = notify_palette.get();
|
||||
if (notify_palette.get() > 0x04 && notify_palette.get() < 0x06) {
|
||||
palette = palettesets_[current_palette_].aux1;
|
||||
value -= 0x04;
|
||||
} else if (notify_palette.get() > 0x06) {
|
||||
palette = palettesets_[current_palette_].aux2;
|
||||
value -= 0x06;
|
||||
}
|
||||
|
||||
if (value > 0x00) {
|
||||
current_gfx_bmp_.ApplyPaletteWithTransparent(palette, value);
|
||||
current_tile16_bmp_.ApplyPaletteWithTransparent(palette, value);
|
||||
rom()->UpdateBitmap(¤t_gfx_bmp_);
|
||||
rom()->UpdateBitmap(¤t_tile16_bmp_);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Checkbox("X Flip", &x_flip);
|
||||
@@ -188,13 +268,14 @@ absl::Status Tile16Editor::UpdateTransferTileCanvas() {
|
||||
transfer_started_ = true;
|
||||
});
|
||||
|
||||
// TODO: Implement tile16 transfer
|
||||
if (transfer_started_ && !transfer_blockset_loaded_) {
|
||||
PRINT_IF_ERROR(transfer_rom_.LoadAllGraphicsData())
|
||||
graphics_bin_ = transfer_rom_.graphics_bin();
|
||||
|
||||
// Load the Link to the Past overworld.
|
||||
PRINT_IF_ERROR(transfer_overworld_.Load(transfer_rom_))
|
||||
transfer_overworld_.SetCurrentMap(0);
|
||||
transfer_overworld_.set_current_map(0);
|
||||
palette_ = transfer_overworld_.AreaPalette();
|
||||
|
||||
// Create the tile16 blockset image
|
||||
@@ -212,84 +293,59 @@ absl::Status Tile16Editor::UpdateTransferTileCanvas() {
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
using core::TaskManager;
|
||||
|
||||
absl::Status Tile16Editor::InitBlockset(
|
||||
const gfx::Bitmap& tile16_blockset_bmp, gfx::Bitmap current_gfx_bmp,
|
||||
const std::vector<gfx::Bitmap>& tile16_individual) {
|
||||
const std::vector<gfx::Bitmap>& tile16_individual,
|
||||
uint8_t all_tiles_types[0x200]) {
|
||||
all_tiles_types_ = all_tiles_types;
|
||||
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);
|
||||
}
|
||||
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].Create(0x08, 0x08, 0x08, tile_data);
|
||||
current_gfx_individual_[index].ApplyPaletteWithTransparent(
|
||||
rom()->palette_group("ow_main")[0], current_palette_);
|
||||
rom()->RenderBitmap(¤t_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);
|
||||
map_blockset_loaded_ = true;
|
||||
|
||||
// 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(¤t_gfx_individual_[i]);
|
||||
// }
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
|
||||
@@ -8,13 +8,14 @@
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "app/core/editor.h"
|
||||
#include "app/gui/pipeline.h"
|
||||
#include "app/editor/context/gfx_context.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"
|
||||
|
||||
@@ -22,11 +23,15 @@ namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
class Tile16Editor : public SharedROM {
|
||||
class Tile16Editor : public GfxContext, public SharedROM {
|
||||
public:
|
||||
absl::Status Update();
|
||||
|
||||
absl::Status DrawTile16Editor();
|
||||
absl::Status UpdateTile16Transfer();
|
||||
absl::Status UpdateBlockset();
|
||||
|
||||
absl::Status DrawToCurrentTile16(ImVec2 pos);
|
||||
|
||||
absl::Status UpdateTile16Edit();
|
||||
|
||||
void DrawTileEditControls();
|
||||
@@ -35,10 +40,19 @@ class Tile16Editor : public SharedROM {
|
||||
|
||||
absl::Status InitBlockset(const gfx::Bitmap& tile16_blockset_bmp,
|
||||
gfx::Bitmap current_gfx_bmp,
|
||||
const std::vector<gfx::Bitmap>& tile16_individual);
|
||||
const std::vector<gfx::Bitmap>& tile16_individual,
|
||||
uint8_t all_tiles_types[0x200]);
|
||||
|
||||
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(¤t_tile16_bmp_);
|
||||
}
|
||||
|
||||
private:
|
||||
bool map_blockset_loaded_ = false;
|
||||
bool transfer_started_ = false;
|
||||
@@ -48,7 +62,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
|
||||
@@ -64,8 +78,11 @@ class Tile16Editor : public SharedROM {
|
||||
bool priority_tile;
|
||||
int tile_size;
|
||||
|
||||
uint8_t *all_tiles_types_;
|
||||
|
||||
// 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,9 +105,11 @@ class Tile16Editor : public SharedROM {
|
||||
|
||||
std::vector<uint8_t> current_tile16_data_;
|
||||
|
||||
std::vector<uint8_t> tile8_gfx_data_;
|
||||
|
||||
PaletteEditor palette_editor_;
|
||||
|
||||
gfx::SNESPalette palette_;
|
||||
gfx::SnesPalette palette_;
|
||||
zelda3::Overworld transfer_overworld_;
|
||||
|
||||
gfx::BitmapTable graphics_bin_;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,7 @@
|
||||
#define YAZE_APP_EDITOR_OVERWORLDEDITOR_H
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
#include <imgui/imgui_internal.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <unordered_map>
|
||||
@@ -12,6 +13,7 @@
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "app/core/common.h"
|
||||
#include "app/core/editor.h"
|
||||
#include "app/editor/context/gfx_context.h"
|
||||
#include "app/editor/modules/gfx_group_editor.h"
|
||||
#include "app/editor/modules/palette_editor.h"
|
||||
#include "app/editor/modules/tile16_editor.h"
|
||||
@@ -36,12 +38,14 @@ static constexpr uint kTile8DisplayHeight = 64;
|
||||
static constexpr float kInputFieldSize = 30.f;
|
||||
|
||||
static constexpr absl::string_view kToolsetColumnNames[] = {
|
||||
"#undoTool", "#redoTool", "#drawTool", "#separator2",
|
||||
"#zoomOutTool", "#zoomInTool", "#separator", "#history",
|
||||
"#entranceTool", "#exitTool", "#itemTool", "#spriteTool",
|
||||
"#transportTool", "#musicTool", "#separator3", "#tilemapTool"};
|
||||
"#undoTool", "#redoTool", "#separator2", "#zoomOutTool",
|
||||
"#zoomInTool", "#separator", "#drawTool", "#history",
|
||||
"#entranceTool", "#exitTool", "#itemTool", "#spriteTool",
|
||||
"#transportTool", "#musicTool", "#separator3", "#tilemapTool",
|
||||
"propertiesTool"};
|
||||
|
||||
constexpr ImGuiTableFlags kOWMapFlags = ImGuiTableFlags_Borders;
|
||||
constexpr ImGuiTableFlags kOWMapFlags =
|
||||
ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable;
|
||||
constexpr ImGuiTableFlags kToolsetTableFlags = ImGuiTableFlags_SizingFixedFit;
|
||||
constexpr ImGuiTableFlags kOWEditFlags =
|
||||
ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable |
|
||||
@@ -59,6 +63,7 @@ constexpr absl::string_view kOWMapTable = "#MapSettingsTable";
|
||||
|
||||
class OverworldEditor : public Editor,
|
||||
public SharedROM,
|
||||
public GfxContext,
|
||||
public core::ExperimentFlags {
|
||||
public:
|
||||
absl::Status Update() final;
|
||||
@@ -70,17 +75,20 @@ class OverworldEditor : public Editor,
|
||||
|
||||
auto overworld() { return &overworld_; }
|
||||
|
||||
int jump_to_tab() { return jump_to_tab_; }
|
||||
int jump_to_tab_ = -1;
|
||||
|
||||
void Shutdown() {
|
||||
for (auto &bmp : tile16_individual_) {
|
||||
for (auto& bmp : tile16_individual_) {
|
||||
bmp.Cleanup();
|
||||
}
|
||||
for (auto &[i, bmp] : maps_bmp_) {
|
||||
for (auto& [i, bmp] : maps_bmp_) {
|
||||
bmp.Cleanup();
|
||||
}
|
||||
for (auto &[i, bmp] : graphics_bin_) {
|
||||
for (auto& [i, bmp] : graphics_bin_) {
|
||||
bmp.Cleanup();
|
||||
}
|
||||
for (auto &[i, bmp] : current_graphics_set_) {
|
||||
for (auto& [i, bmp] : current_graphics_set_) {
|
||||
bmp.Cleanup();
|
||||
}
|
||||
}
|
||||
@@ -88,29 +96,52 @@ class OverworldEditor : public Editor,
|
||||
absl::Status LoadGraphics();
|
||||
|
||||
private:
|
||||
absl::Status UpdateOverworldEdit();
|
||||
|
||||
absl::Status DrawToolset();
|
||||
void DrawOverworldMapSettings();
|
||||
|
||||
void DrawOverworldEntrances(ImVec2 canvas_p, ImVec2 scrolling);
|
||||
void DrawOverworldMaps();
|
||||
void RefreshChildMap(int i);
|
||||
void RefreshOverworldMap();
|
||||
void RefreshMapPalette();
|
||||
void RefreshMapProperties();
|
||||
void RefreshTile16Blockset();
|
||||
|
||||
void DrawOverworldEntrances(ImVec2 canvas_p, ImVec2 scrolling,
|
||||
bool holes = false);
|
||||
void DrawOverworldExits(ImVec2 zero, ImVec2 scrolling);
|
||||
void DrawOverworldItems();
|
||||
void DrawOverworldSprites();
|
||||
|
||||
void DrawOverworldMaps();
|
||||
void DrawOverworldEdits();
|
||||
void RenderUpdatedMapBitmap(const ImVec2 &click_position,
|
||||
const Bytes &tile_data);
|
||||
void SaveOverworldChanges();
|
||||
void DetermineActiveMap(const ImVec2 &mouse_position);
|
||||
|
||||
void RenderUpdatedMapBitmap(const ImVec2& click_position,
|
||||
const Bytes& tile_data);
|
||||
void CheckForOverworldEdits();
|
||||
void CheckForCurrentMap();
|
||||
void CheckForSelectRectangle();
|
||||
void DrawOverworldCanvas();
|
||||
|
||||
void DrawTile16Selector();
|
||||
void DrawTile8Selector();
|
||||
void DrawAreaGraphics();
|
||||
void DrawTileSelector();
|
||||
|
||||
absl::Status LoadSpriteGraphics();
|
||||
|
||||
void DrawOverworldProperties();
|
||||
|
||||
absl::Status DrawExperimentalModal();
|
||||
|
||||
absl::Status UpdateUsageStats();
|
||||
void DrawUsageGrid();
|
||||
void CalculateUsageStats();
|
||||
|
||||
void LoadAnimatedMaps();
|
||||
void DrawDebugWindow();
|
||||
|
||||
auto gfx_group_editor() const { return gfx_group_editor_; }
|
||||
|
||||
enum class EditingMode {
|
||||
DRAW_TILE,
|
||||
ENTRANCES,
|
||||
@@ -118,16 +149,25 @@ class OverworldEditor : public Editor,
|
||||
ITEMS,
|
||||
SPRITES,
|
||||
TRANSPORTS,
|
||||
MUSIC
|
||||
MUSIC,
|
||||
PAN
|
||||
};
|
||||
|
||||
EditingMode current_mode = EditingMode::DRAW_TILE;
|
||||
EditingMode previous_mode = EditingMode::DRAW_TILE;
|
||||
|
||||
int current_world_ = 0;
|
||||
int current_map_ = 0;
|
||||
int current_parent_ = 0;
|
||||
int game_state_ = 1;
|
||||
int current_tile16_ = 0;
|
||||
int selected_tile_ = 0;
|
||||
int game_state_ = 0;
|
||||
|
||||
int current_blockset_ = 0;
|
||||
|
||||
int selected_entrance_ = 0;
|
||||
int selected_usage_map_ = 0xFFFF;
|
||||
|
||||
char map_gfx_[3] = "";
|
||||
char map_palette_[3] = "";
|
||||
char spr_gfx_[3] = "";
|
||||
@@ -149,10 +189,21 @@ class OverworldEditor : public Editor,
|
||||
bool is_dragging_entrance_ = false;
|
||||
bool show_tile16_editor_ = false;
|
||||
bool show_gfx_group_editor_ = false;
|
||||
bool overworld_canvas_fullscreen_ = false;
|
||||
bool middle_mouse_dragging_ = false;
|
||||
|
||||
bool IsMouseHoveringOverEntrance(const zelda3::OverworldEntrance &entrance,
|
||||
ImVec2 canvas_p, ImVec2 scrolling);
|
||||
zelda3::OverworldEntrance *dragged_entrance_;
|
||||
bool is_dragging_entity_ = false;
|
||||
zelda3::OverworldEntity* dragged_entity_;
|
||||
zelda3::OverworldEntity* current_entity_;
|
||||
|
||||
int current_entrance_id_ = 0;
|
||||
zelda3::OverworldEntrance current_entrance_;
|
||||
int current_exit_id_ = 0;
|
||||
zelda3::OverworldExit current_exit_;
|
||||
int current_item_id_ = 0;
|
||||
zelda3::OverworldItem current_item_;
|
||||
int current_sprite_id_ = 0;
|
||||
zelda3::Sprite current_sprite_;
|
||||
|
||||
bool show_experimental = false;
|
||||
std::string ow_tilemap_filename_ = "";
|
||||
@@ -170,12 +221,18 @@ class OverworldEditor : public Editor,
|
||||
PaletteEditor palette_editor_;
|
||||
zelda3::Overworld overworld_;
|
||||
|
||||
gui::Canvas ow_map_canvas_;
|
||||
gui::Canvas current_gfx_canvas_;
|
||||
gui::Canvas blockset_canvas_;
|
||||
gui::Canvas graphics_bin_canvas_;
|
||||
gui::Canvas ow_map_canvas_{ImVec2(0x200 * 8, 0x200 * 8),
|
||||
gui::CanvasGridSize::k64x64};
|
||||
gui::Canvas current_gfx_canvas_{ImVec2(0x100 + 1, 0x10 * 0x40 + 1),
|
||||
gui::CanvasGridSize::k32x32};
|
||||
gui::Canvas blockset_canvas_{ImVec2(0x100 + 1, 0x2000 + 1),
|
||||
gui::CanvasGridSize::k32x32};
|
||||
gui::Canvas graphics_bin_canvas_{
|
||||
ImVec2(0x100 + 1, kNumSheetsToLoad * 0x40 + 1),
|
||||
gui::CanvasGridSize::k16x16};
|
||||
gui::Canvas properties_canvas_;
|
||||
|
||||
gfx::SNESPalette palette_;
|
||||
gfx::SnesPalette palette_;
|
||||
gfx::Bitmap selected_tile_bmp_;
|
||||
gfx::Bitmap tile16_blockset_bmp_;
|
||||
gfx::Bitmap current_gfx_bmp_;
|
||||
@@ -186,6 +243,8 @@ class OverworldEditor : public Editor,
|
||||
gfx::BitmapTable current_graphics_set_;
|
||||
gfx::BitmapTable sprite_previews_;
|
||||
|
||||
gfx::BitmapTable animated_maps_;
|
||||
|
||||
absl::Status status_;
|
||||
};
|
||||
} // namespace editor
|
||||
|
||||
@@ -15,9 +15,11 @@
|
||||
#include "app/core/constants.h"
|
||||
#include "app/gfx/bitmap.h"
|
||||
#include "app/gfx/snes_tile.h"
|
||||
#include "app/gfx/tilesheet.h"
|
||||
#include "app/gui/canvas.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/gui/input.h"
|
||||
#include "app/zelda3/dungeon/room.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
@@ -27,11 +29,15 @@ ScreenEditor::ScreenEditor() { screen_canvas_.SetCanvasSize(ImVec2(512, 512)); }
|
||||
|
||||
void ScreenEditor::Update() {
|
||||
TAB_BAR("##TabBar")
|
||||
TAB_ITEM("Dungeon Maps")
|
||||
if (rom()->is_loaded()) {
|
||||
DrawDungeonMapsEditor();
|
||||
}
|
||||
END_TAB_ITEM()
|
||||
DrawInventoryMenuEditor();
|
||||
DrawOverworldMapEditor();
|
||||
DrawTitleScreenEditor();
|
||||
DrawNamingScreenEditor();
|
||||
DrawOverworldMapEditor();
|
||||
DrawDungeonMapsEditor();
|
||||
END_TAB_BAR()
|
||||
}
|
||||
|
||||
@@ -39,7 +45,7 @@ void ScreenEditor::DrawInventoryMenuEditor() {
|
||||
TAB_ITEM("Inventory Menu")
|
||||
|
||||
static bool create = false;
|
||||
if (!create && rom()->isLoaded()) {
|
||||
if (!create && rom()->is_loaded()) {
|
||||
inventory_.Create();
|
||||
palette_ = inventory_.Palette();
|
||||
create = true;
|
||||
@@ -76,43 +82,6 @@ void ScreenEditor::DrawInventoryMenuEditor() {
|
||||
END_TAB_ITEM()
|
||||
}
|
||||
|
||||
void ScreenEditor::DrawTitleScreenEditor() {
|
||||
TAB_ITEM("Title Screen")
|
||||
END_TAB_ITEM()
|
||||
}
|
||||
void ScreenEditor::DrawNamingScreenEditor() {
|
||||
TAB_ITEM("Naming Screen")
|
||||
END_TAB_ITEM()
|
||||
}
|
||||
void ScreenEditor::DrawOverworldMapEditor() {
|
||||
TAB_ITEM("Overworld Map")
|
||||
END_TAB_ITEM()
|
||||
}
|
||||
void ScreenEditor::DrawDungeonMapsEditor() {
|
||||
TAB_ITEM("Dungeon Maps")
|
||||
END_TAB_ITEM()
|
||||
}
|
||||
|
||||
void ScreenEditor::DrawToolset() {
|
||||
static bool show_bg1 = true;
|
||||
static bool show_bg2 = true;
|
||||
static bool show_bg3 = true;
|
||||
|
||||
static bool drawing_bg1 = true;
|
||||
static bool drawing_bg2 = false;
|
||||
static bool drawing_bg3 = false;
|
||||
|
||||
ImGui::Checkbox("Show BG1", &show_bg1);
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Show BG2", &show_bg2);
|
||||
|
||||
ImGui::Checkbox("Draw BG1", &drawing_bg1);
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Draw BG2", &drawing_bg2);
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Draw BG3", &drawing_bg3);
|
||||
}
|
||||
|
||||
void ScreenEditor::DrawInventoryToolset() {
|
||||
if (ImGui::BeginTable("InventoryToolset", 8, ImGuiTableFlags_SizingFixedFit,
|
||||
ImVec2(0, 0))) {
|
||||
@@ -138,6 +107,329 @@ void ScreenEditor::DrawInventoryToolset() {
|
||||
}
|
||||
}
|
||||
|
||||
absl::Status ScreenEditor::LoadDungeonMaps() {
|
||||
std::vector<std::array<uint8_t, 25>> current_floor_rooms_d;
|
||||
std::vector<std::array<uint8_t, 25>> current_floor_gfx_d;
|
||||
int total_floors_d;
|
||||
uint8_t nbr_floor_d;
|
||||
uint8_t nbr_basement_d;
|
||||
|
||||
for (int d = 0; d < 14; d++) {
|
||||
current_floor_rooms_d.clear();
|
||||
current_floor_gfx_d.clear();
|
||||
ASSIGN_OR_RETURN(int ptr,
|
||||
rom()->ReadWord(zelda3::kDungeonMapRoomsPtr + (d * 2)));
|
||||
ASSIGN_OR_RETURN(int ptrGFX,
|
||||
rom()->ReadWord(zelda3::kDungeonMapRoomsPtr + (d * 2)));
|
||||
ptr |= 0x0A0000; // Add bank to the short ptr
|
||||
ptrGFX |= 0x0A0000; // Add bank to the short ptr
|
||||
int pcPtr = core::SnesToPc(ptr); // Contains data for the next 25 rooms
|
||||
int pcPtrGFX =
|
||||
core::SnesToPc(ptrGFX); // Contains data for the next 25 rooms
|
||||
|
||||
ASSIGN_OR_RETURN(ushort bossRoomD,
|
||||
rom()->ReadWord(zelda3::kDungeonMapBossRooms + (d * 2)));
|
||||
|
||||
ASSIGN_OR_RETURN(nbr_basement_d,
|
||||
rom()->ReadByte(zelda3::kDungeonMapFloors + (d * 2)));
|
||||
nbr_basement_d &= 0x0F;
|
||||
|
||||
ASSIGN_OR_RETURN(nbr_floor_d,
|
||||
rom()->ReadByte(zelda3::kDungeonMapFloors + (d * 2)));
|
||||
nbr_floor_d &= 0xF0;
|
||||
nbr_floor_d = nbr_floor_d >> 4;
|
||||
|
||||
total_floors_d = nbr_basement_d + nbr_floor_d;
|
||||
|
||||
dungeon_map_labels_.emplace_back();
|
||||
|
||||
// for each floor in the dungeon
|
||||
for (int i = 0; i < total_floors_d; i++) {
|
||||
dungeon_map_labels_[d].emplace_back();
|
||||
|
||||
std::array<uint8_t, 25> rdata;
|
||||
std::array<uint8_t, 25> gdata;
|
||||
|
||||
// for each room on the floor
|
||||
for (int j = 0; j < 25; j++) {
|
||||
// rdata[j] = 0x0F;
|
||||
gdata[j] = 0xFF;
|
||||
rdata[j] = rom()->data()[pcPtr + j + (i * 25)]; // Set the rooms
|
||||
|
||||
if (rdata[j] == 0x0F) {
|
||||
gdata[j] = 0xFF;
|
||||
} else {
|
||||
gdata[j] = rom()->data()[pcPtrGFX++];
|
||||
}
|
||||
|
||||
std::string label = core::UppercaseHexByte(rdata[j]);
|
||||
dungeon_map_labels_[d][i][j] = label;
|
||||
}
|
||||
|
||||
current_floor_gfx_d.push_back(gdata); // Add new floor gfx data
|
||||
current_floor_rooms_d.push_back(rdata); // Add new floor data
|
||||
}
|
||||
|
||||
dungeon_maps_.emplace_back(bossRoomD, nbr_floor_d, nbr_basement_d,
|
||||
current_floor_rooms_d, current_floor_gfx_d);
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status ScreenEditor::SaveDungeonMaps() {
|
||||
for (int d = 0; d < 14; d++) {
|
||||
int ptr = zelda3::kDungeonMapRoomsPtr + (d * 2);
|
||||
int ptrGFX = zelda3::kDungeonMapGfxPtr + (d * 2);
|
||||
int pcPtr = core::SnesToPc(ptr);
|
||||
int pcPtrGFX = core::SnesToPc(ptrGFX);
|
||||
|
||||
const int nbr_floors = dungeon_maps_[d].nbr_of_floor;
|
||||
const int nbr_basements = dungeon_maps_[d].nbr_of_basement;
|
||||
for (int i = 0; i < nbr_floors + nbr_basements; i++) {
|
||||
for (int j = 0; j < 25; j++) {
|
||||
// rom()->data()[pcPtr + j + (i * 25)] =
|
||||
// dungeon_maps_[d].floor_rooms[i][j];
|
||||
// rom()->data()[pcPtrGFX++] = dungeon_maps_[d].floor_gfx[i][j];
|
||||
|
||||
RETURN_IF_ERROR(rom()->WriteByte(ptr + j + (i * 25),
|
||||
dungeon_maps_[d].floor_rooms[i][j]));
|
||||
RETURN_IF_ERROR(rom()->WriteByte(ptrGFX + j + (i * 25),
|
||||
dungeon_maps_[d].floor_gfx[i][j]));
|
||||
pcPtrGFX++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status ScreenEditor::LoadDungeonMapTile16() {
|
||||
tile16_sheet_.Init(256, 192, gfx::TileType::Tile16);
|
||||
|
||||
for (int i = 0; i < 186; i++) {
|
||||
int addr = zelda3::kDungeonMapTile16;
|
||||
if (rom()->data()[zelda3::kDungeonMapExpCheck] != 0xB9) {
|
||||
addr = zelda3::kDungeonMapTile16Expanded;
|
||||
}
|
||||
|
||||
ASSIGN_OR_RETURN(auto tl, rom()->ReadWord(addr + (i * 8)));
|
||||
gfx::TileInfo t1 = gfx::WordToTileInfo(tl); // Top left
|
||||
|
||||
ASSIGN_OR_RETURN(auto tr, rom()->ReadWord(addr + 2 + (i * 8)));
|
||||
gfx::TileInfo t2 = gfx::WordToTileInfo(tr); // Top right
|
||||
|
||||
ASSIGN_OR_RETURN(auto bl, rom()->ReadWord(addr + 4 + (i * 8)));
|
||||
gfx::TileInfo t3 = gfx::WordToTileInfo(bl); // Bottom left
|
||||
|
||||
ASSIGN_OR_RETURN(auto br, rom()->ReadWord(addr + 6 + (i * 8)));
|
||||
gfx::TileInfo t4 = gfx::WordToTileInfo(br); // Bottom right
|
||||
|
||||
tile16_sheet_.ComposeTile16(rom()->graphics_buffer(), t1, t2, t3, t4);
|
||||
}
|
||||
|
||||
tile16_sheet_.mutable_bitmap()->ApplyPalette(
|
||||
*rom()->mutable_dungeon_palette(3));
|
||||
rom()->RenderBitmap(&*tile16_sheet_.mutable_bitmap().get());
|
||||
|
||||
for (int i = 0; i < tile16_sheet_.num_tiles(); ++i) {
|
||||
if (tile16_individual_.count(i) == 0) {
|
||||
auto tile = tile16_sheet_.GetTile16(i);
|
||||
tile16_individual_[i] = tile;
|
||||
rom()->RenderBitmap(&tile16_individual_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
void ScreenEditor::DrawDungeonMapsTabs() {
|
||||
auto current_dungeon = dungeon_maps_[selected_dungeon];
|
||||
if (ImGui::BeginTabBar("##DungeonMapTabs")) {
|
||||
auto nbr_floors =
|
||||
current_dungeon.nbr_of_floor + current_dungeon.nbr_of_basement;
|
||||
for (int i = 0; i < nbr_floors; i++) {
|
||||
std::string tab_name = absl::StrFormat("Floor %d", i + 1);
|
||||
if (i >= current_dungeon.nbr_of_floor) {
|
||||
tab_name = absl::StrFormat("Basement %d",
|
||||
i - current_dungeon.nbr_of_floor + 1);
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem(tab_name.c_str())) {
|
||||
floor_number = i;
|
||||
// screen_canvas_.LoadCustomLabels(dungeon_map_labels_[selected_dungeon]);
|
||||
// screen_canvas_.set_current_labels(floor_number);
|
||||
screen_canvas_.DrawBackground(ImVec2(325, 325));
|
||||
screen_canvas_.DrawTileSelector(64.f);
|
||||
|
||||
auto boss_room = current_dungeon.boss_room;
|
||||
for (int j = 0; j < 25; j++) {
|
||||
if (current_dungeon.floor_rooms[floor_number][j] != 0x0F) {
|
||||
int tile16_id = current_dungeon.floor_rooms[floor_number][j];
|
||||
int tile_x = (tile16_id % 16) * 16;
|
||||
int tile_y = (tile16_id / 16) * 16;
|
||||
int posX = ((j % 5) * 32);
|
||||
int posY = ((j / 5) * 32);
|
||||
|
||||
if (tile16_individual_.count(tile16_id) == 0) {
|
||||
auto tile = tile16_sheet_.GetTile16(tile16_id);
|
||||
std::cout << "Tile16: " << tile16_id << std::endl;
|
||||
rom()->RenderBitmap(&tile);
|
||||
tile16_individual_[tile16_id] = tile;
|
||||
}
|
||||
screen_canvas_.DrawBitmap(tile16_individual_[tile16_id], (posX * 2),
|
||||
(posY * 2), 4.0f);
|
||||
|
||||
if (current_dungeon.floor_rooms[floor_number][j] == boss_room) {
|
||||
screen_canvas_.DrawOutlineWithColor((posX * 2), (posY * 2), 64,
|
||||
64, core::kRedPen);
|
||||
}
|
||||
|
||||
std::string label =
|
||||
dungeon_map_labels_[selected_dungeon][floor_number][j];
|
||||
screen_canvas_.DrawText(label, (posX * 2), (posY * 2));
|
||||
// GFX.drawText(
|
||||
// e.Graphics, 16 + ((i % 5) * 32), 20 + ((i / 5) * 32),
|
||||
}
|
||||
|
||||
// if (dungmapSelectedTile == i)
|
||||
// Constants.AzurePen2,
|
||||
// 10 + ((i % 5) * 32), 12 + ((i / 5) * 32), 32, 32));
|
||||
}
|
||||
|
||||
screen_canvas_.DrawGrid(64.f, 5);
|
||||
screen_canvas_.DrawOverlay();
|
||||
|
||||
if (!screen_canvas_.points().empty()) {
|
||||
int x = screen_canvas_.points().front().x / 64;
|
||||
int y = screen_canvas_.points().front().y / 64;
|
||||
selected_room = x + (y * 5);
|
||||
}
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
}
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
|
||||
gui::InputHexByte(
|
||||
"Selected Room",
|
||||
¤t_dungeon.floor_rooms[floor_number].at(selected_room));
|
||||
|
||||
gui::InputHexWord("Boss Room", ¤t_dungeon.boss_room);
|
||||
|
||||
if (ImGui::Button("Copy Floor", ImVec2(100, 0))) {
|
||||
copy_button_pressed = true;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Paste Floor", ImVec2(100, 0))) {
|
||||
paste_button_pressed = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenEditor::DrawDungeonMapsEditor() {
|
||||
if (!dungeon_maps_loaded_) {
|
||||
if (LoadDungeonMaps().ok()) {
|
||||
if (LoadDungeonMapTile16().ok()) {
|
||||
auto bitmap_manager = rom()->mutable_bitmap_manager();
|
||||
sheets_.emplace(0, *bitmap_manager->mutable_bitmap(212));
|
||||
sheets_.emplace(1, *bitmap_manager->mutable_bitmap(213));
|
||||
sheets_.emplace(2, *bitmap_manager->mutable_bitmap(214));
|
||||
sheets_.emplace(3, *bitmap_manager->mutable_bitmap(215));
|
||||
dungeon_maps_loaded_ = true;
|
||||
} else {
|
||||
ImGui::Text("Failed to load dungeon map tile16");
|
||||
}
|
||||
} else {
|
||||
ImGui::Text("Failed to load dungeon maps");
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<std::string> dungeon_names = {
|
||||
"Sewers/Sanctuary", "Hyrule Castle", "Eastern Palace",
|
||||
"Desert Palace", "Tower of Hera", "Agahnim's Tower",
|
||||
"Palace of Darkness", "Swamp Palace", "Skull Woods",
|
||||
"Thieves' Town", "Ice Palace", "Misery Mire",
|
||||
"Turtle Rock", "Ganon's Tower"};
|
||||
|
||||
if (ImGui::BeginTable("DungeonMapsTable", 4, ImGuiTableFlags_Resizable)) {
|
||||
ImGui::TableSetupColumn("Dungeon");
|
||||
ImGui::TableSetupColumn("Map");
|
||||
ImGui::TableSetupColumn("Rooms Gfx");
|
||||
ImGui::TableSetupColumn("Tiles Gfx");
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
// Dungeon column
|
||||
ImGui::TableNextColumn();
|
||||
for (int i = 0; i < dungeon_names.size(); i++) {
|
||||
rom()->resource_label()->SelectableLabelWithNameEdit(
|
||||
selected_dungeon == i, "Dungeon Names", absl::StrFormat("%d", i),
|
||||
dungeon_names[i]);
|
||||
}
|
||||
|
||||
// Map column
|
||||
ImGui::TableNextColumn();
|
||||
DrawDungeonMapsTabs();
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::BeginChild("##DungeonMapTiles", ImVec2(0, 0), true)) {
|
||||
tilesheet_canvas_.DrawBackground(ImVec2((256 * 2) + 2, (192 * 2) + 4));
|
||||
tilesheet_canvas_.DrawContextMenu();
|
||||
tilesheet_canvas_.DrawTileSelector(32.f);
|
||||
tilesheet_canvas_.DrawBitmap(*tile16_sheet_.bitmap(), 2, true);
|
||||
tilesheet_canvas_.DrawGrid(32.f);
|
||||
tilesheet_canvas_.DrawOverlay();
|
||||
|
||||
if (!tilesheet_canvas_.points().empty()) {
|
||||
selected_tile16_ = tilesheet_canvas_.points().front().x / 32 +
|
||||
(tilesheet_canvas_.points().front().y / 32) * 16;
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
tilemap_canvas_.DrawBackground(ImVec2(128 * 2 + 2, (192 * 2) + 4));
|
||||
tilemap_canvas_.DrawContextMenu();
|
||||
tilemap_canvas_.DrawBitmapTable(sheets_);
|
||||
tilemap_canvas_.DrawGrid();
|
||||
tilemap_canvas_.DrawOverlay();
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenEditor::DrawTitleScreenEditor() {
|
||||
TAB_ITEM("Title Screen")
|
||||
END_TAB_ITEM()
|
||||
}
|
||||
void ScreenEditor::DrawNamingScreenEditor() {
|
||||
TAB_ITEM("Naming Screen")
|
||||
END_TAB_ITEM()
|
||||
}
|
||||
void ScreenEditor::DrawOverworldMapEditor() {
|
||||
TAB_ITEM("Overworld Map")
|
||||
END_TAB_ITEM()
|
||||
}
|
||||
|
||||
void ScreenEditor::DrawToolset() {
|
||||
static bool show_bg1 = true;
|
||||
static bool show_bg2 = true;
|
||||
static bool show_bg3 = true;
|
||||
|
||||
static bool drawing_bg1 = true;
|
||||
static bool drawing_bg2 = false;
|
||||
static bool drawing_bg3 = false;
|
||||
|
||||
ImGui::Checkbox("Show BG1", &show_bg1);
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Show BG2", &show_bg2);
|
||||
|
||||
ImGui::Checkbox("Draw BG1", &drawing_bg1);
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Draw BG2", &drawing_bg2);
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Draw BG3", &drawing_bg3);
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
@@ -5,14 +5,17 @@
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "app/core/constants.h"
|
||||
#include "app/gfx/bitmap.h"
|
||||
#include "app/gfx/snes_palette.h"
|
||||
#include "app/gfx/snes_tile.h"
|
||||
#include "app/gfx/tilesheet.h"
|
||||
#include "app/gui/canvas.h"
|
||||
#include "app/gui/color.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/rom.h"
|
||||
#include "app/zelda3/screen/dungeon_map.h"
|
||||
#include "app/zelda3/screen/inventory.h"
|
||||
|
||||
namespace yaze {
|
||||
@@ -24,21 +27,48 @@ class ScreenEditor : public SharedROM {
|
||||
ScreenEditor();
|
||||
void Update();
|
||||
|
||||
absl::Status SaveDungeonMaps();
|
||||
|
||||
private:
|
||||
void DrawTitleScreenEditor();
|
||||
void DrawNamingScreenEditor();
|
||||
void DrawOverworldMapEditor();
|
||||
void DrawDungeonMapsEditor();
|
||||
void DrawInventoryMenuEditor();
|
||||
|
||||
void DrawInventoryMenuEditor();
|
||||
void DrawToolset();
|
||||
void DrawInventoryToolset();
|
||||
|
||||
absl::Status LoadDungeonMaps();
|
||||
absl::Status LoadDungeonMapTile16();
|
||||
void DrawDungeonMapsTabs();
|
||||
void DrawDungeonMapsEditor();
|
||||
|
||||
std::vector<zelda3::DungeonMap> dungeon_maps_;
|
||||
std::vector<std::vector<std::array<std::string, 25>>> dungeon_map_labels_;
|
||||
|
||||
std::unordered_map<int, gfx::Bitmap> tile16_individual_;
|
||||
|
||||
bool dungeon_maps_loaded_ = false;
|
||||
|
||||
int selected_tile16_ = 0;
|
||||
int selected_dungeon = 0;
|
||||
uint8_t selected_room = 0;
|
||||
uint8_t boss_room = 0;
|
||||
int floor_number = 1;
|
||||
|
||||
bool copy_button_pressed = false;
|
||||
bool paste_button_pressed = false;
|
||||
|
||||
Bytes all_gfx_;
|
||||
zelda3::Inventory inventory_;
|
||||
gfx::SNESPalette palette_;
|
||||
gfx::SnesPalette palette_;
|
||||
gui::Canvas screen_canvas_;
|
||||
gui::Canvas tilesheet_canvas_;
|
||||
gui::Canvas tilemap_canvas_;
|
||||
|
||||
gfx::BitmapTable sheets_;
|
||||
|
||||
gfx::Tilesheet tile16_sheet_;
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
|
||||
@@ -4,7 +4,65 @@ namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
absl::Status SpriteEditor::Update() { return absl::OkStatus(); }
|
||||
using ImGui::Button;
|
||||
using ImGui::Separator;
|
||||
using ImGui::TableHeadersRow;
|
||||
using ImGui::TableNextColumn;
|
||||
using ImGui::TableNextRow;
|
||||
using ImGui::TableSetupColumn;
|
||||
using ImGui::Text;
|
||||
|
||||
absl::Status SpriteEditor::Update() {
|
||||
if (rom()->is_loaded() && !sheets_loaded_) {
|
||||
// Load the values for current_sheets_ array
|
||||
|
||||
sheets_loaded_ = true;
|
||||
}
|
||||
|
||||
// if (ImGui::BeginTable({"Canvas", "Graphics"}, 2, nullptr, ImVec2(0, 0))) {
|
||||
// TableSetupColumn("Canvas", ImGuiTableColumnFlags_WidthStretch,
|
||||
// ImGui::GetContentRegionAvail().x);
|
||||
// TableSetupColumn("Tile Selector", ImGuiTableColumnFlags_WidthFixed, 256);
|
||||
// TableHeadersRow();
|
||||
// TableNextRow();
|
||||
// TableNextColumn();
|
||||
// DrawSpriteCanvas();
|
||||
|
||||
// TableNextColumn();
|
||||
// if (sheets_loaded_) {
|
||||
// DrawCurrentSheets();
|
||||
// }
|
||||
|
||||
// ImGui::EndTable();
|
||||
// }
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
void SpriteEditor::DrawEditorTable() {}
|
||||
|
||||
void SpriteEditor::DrawSpriteCanvas() {}
|
||||
|
||||
void SpriteEditor::DrawCurrentSheets() {
|
||||
static gui::Canvas graphics_sheet_canvas;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
|
||||
if (ImGuiID child_id = ImGui::GetID((void *)(intptr_t)7);
|
||||
ImGui::BeginChild(child_id, ImGui::GetContentRegionAvail(), true,
|
||||
ImGuiWindowFlags_AlwaysVerticalScrollbar |
|
||||
ImGuiWindowFlags_AlwaysHorizontalScrollbar)) {
|
||||
graphics_sheet_canvas.DrawBackground(ImVec2(0x200 * 8, 0x200 * 8));
|
||||
ImGui::PopStyleVar(2);
|
||||
graphics_sheet_canvas.DrawContextMenu();
|
||||
graphics_sheet_canvas.DrawBitmap(
|
||||
*rom()->bitmap_manager()[current_sheets_[i]], 2, 2);
|
||||
graphics_sheet_canvas.DrawGrid(64.0f);
|
||||
graphics_sheet_canvas.DrawOverlay();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
|
||||
@@ -2,14 +2,24 @@
|
||||
#define YAZE_APP_EDITOR_SPRITE_EDITOR_H
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "app/gui/canvas.h"
|
||||
#include "app/rom.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
class SpriteEditor {
|
||||
public:
|
||||
absl::Status Update();
|
||||
class SpriteEditor : public SharedROM {
|
||||
public:
|
||||
absl::Status Update();
|
||||
|
||||
private:
|
||||
void DrawEditorTable();
|
||||
void DrawSpriteCanvas();
|
||||
void DrawCurrentSheets();
|
||||
|
||||
uint8_t current_sheets_[8];
|
||||
bool sheets_loaded_ = false;
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
|
||||
Reference in New Issue
Block a user