Update Dungeon Usage Stats

This commit is contained in:
scawful
2024-01-14 13:33:38 -05:00
parent ea6d8f9636
commit be7276d976
4 changed files with 280 additions and 123 deletions

View File

@@ -61,7 +61,7 @@ absl::Status DungeonEditor::Update() {
} }
TAB_BAR("##DungeonEditorTabBar") TAB_BAR("##DungeonEditorTabBar")
TAB_ITEM("Dungeon Room Editor") TAB_ITEM("Room Editor")
UpdateDungeonRoomView(); UpdateDungeonRoomView();
END_TAB_ITEM() END_TAB_ITEM()
TAB_ITEM("Usage Statistics") TAB_ITEM("Usage Statistics")
@@ -432,19 +432,24 @@ void DungeonEditor::CalculateUsageStats() {
} }
} }
namespace { void DungeonEditor::RenderSetUsage(
template <typename T> const absl::flat_hash_map<uint16_t, int>& usage_map,
void RenderSetUsage(const absl::flat_hash_map<T, int>& usage_map) { uint16_t& selected_set) {
// Sort the usage map by set number // Sort the usage map by set number
std::vector<std::pair<T, int>> sorted_usage(usage_map.begin(), std::vector<std::pair<uint16_t, int>> sorted_usage(usage_map.begin(),
usage_map.end()); usage_map.end());
std::sort(sorted_usage.begin(), sorted_usage.end(), std::sort(sorted_usage.begin(), sorted_usage.end(),
[](const auto& a, const auto& b) { return a.first < b.first; }); [](const auto& a, const auto& b) { return a.first < b.first; });
for (const auto& [set, count] : sorted_usage) { for (const auto& [set, count] : sorted_usage) {
ImGui::Text("%#02x: %d uses", set, count); auto display_str = absl::StrFormat("%#02x: %d", set, 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 // Calculate the unused sets in a usage map
// Range for blocksets 0-0x24 // Range for blocksets 0-0x24
// Range for spritesets 0-0x8F // Range for spritesets 0-0x8F
@@ -465,37 +470,146 @@ void RenderUnusedSets(const absl::flat_hash_map<T, int>& usage_map,
} // namespace } // namespace
void DungeonEditor::DrawUsageStats() { void DungeonEditor::DrawUsageStats() {
if (ImGui::BeginTable("DungeonUsageStatsTable", 6, kDungeonTableFlags, if (ImGui::Button("Refresh")) {
ImVec2(0, 0))) { CalculateUsageStats();
selected_blockset_ = 0xFFFF;
selected_spriteset_ = 0xFFFF;
selected_palette_ = 0xFFFF;
}
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("Blockset Usage");
TableSetupColumn("Unused Blockset"); TableSetupColumn("Unused Blockset");
TableSetupColumn("Palette Usage"); TableSetupColumn("Palette Usage");
TableSetupColumn("Unused Palette"); TableSetupColumn("Unused Palette");
TableSetupColumn("Spriteset Usage"); TableSetupColumn("Spriteset Usage");
TableSetupColumn("Unused Spriteset"); TableSetupColumn("Unused Spriteset");
TableSetupColumn("Usage Grid");
TableSetupColumn("Group Preview");
TableHeadersRow(); TableHeadersRow();
ImGui::PopStyleVar(2);
TableNextColumn(); TableNextColumn();
RenderSetUsage(blockset_usage_); ImGui::BeginChild("BlocksetUsageScroll", ImVec2(0, 0), true,
ImGuiWindowFlags_HorizontalScrollbar);
RenderSetUsage(blockset_usage_, selected_blockset_);
ImGui::EndChild();
TableNextColumn(); TableNextColumn();
ImGui::BeginChild("UnusedBlocksetScroll", ImVec2(0, 0), true,
ImGuiWindowFlags_HorizontalScrollbar);
RenderUnusedSets(blockset_usage_, 0x25); RenderUnusedSets(blockset_usage_, 0x25);
ImGui::EndChild();
TableNextColumn(); TableNextColumn();
RenderSetUsage(palette_usage_); ImGui::BeginChild("PaletteUsageScroll", ImVec2(0, 0), true,
ImGuiWindowFlags_HorizontalScrollbar);
RenderSetUsage(palette_usage_, selected_palette_);
ImGui::EndChild();
TableNextColumn(); TableNextColumn();
ImGui::BeginChild("UnusedPaletteScroll", ImVec2(0, 0), true,
ImGuiWindowFlags_HorizontalScrollbar);
RenderUnusedSets(palette_usage_, 0x48); RenderUnusedSets(palette_usage_, 0x48);
ImGui::EndChild();
TableNextColumn(); TableNextColumn();
RenderSetUsage(spriteset_usage_);
ImGui::BeginChild("SpritesetUsageScroll", ImVec2(0, 0), true,
ImGuiWindowFlags_HorizontalScrollbar);
RenderSetUsage(spriteset_usage_, selected_spriteset_);
ImGui::EndChild();
TableNextColumn(); TableNextColumn();
ImGui::BeginChild("UnusedSpritesetScroll", ImVec2(0, 0), true,
ImGuiWindowFlags_HorizontalScrollbar);
RenderUnusedSets(spriteset_usage_, 0x90); RenderUnusedSets(spriteset_usage_, 0x90);
ImGui::EndChild();
TableNextColumn();
DrawUsageGrid();
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(); 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 = 295;
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];
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
}
// Create a button or selectable for each square
if (ImGui::Button("##square", ImVec2(20, 20))) {
// Handle button click event here
}
// 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::EndTooltip();
}
// Keep squares in the same line
ImGui::SameLine();
}
}
}
} // namespace editor } // namespace editor
} // namespace app } // namespace app
} // namespace yaze } // namespace yaze

View File

@@ -5,6 +5,7 @@
#include "app/core/common.h" #include "app/core/common.h"
#include "app/core/editor.h" #include "app/core/editor.h"
#include "app/editor/modules/gfx_group_editor.h"
#include "app/editor/modules/palette_editor.h" #include "app/editor/modules/palette_editor.h"
#include "app/gui/canvas.h" #include "app/gui/canvas.h"
#include "app/gui/icons.h" #include "app/gui/icons.h"
@@ -41,7 +42,6 @@ class DungeonEditor : public Editor,
absl::Status Redo() override { return absl::OkStatus(); } absl::Status Redo() override { return absl::OkStatus(); }
private: private:
void UpdateDungeonRoomView(); void UpdateDungeonRoomView();
void DrawToolset(); void DrawToolset();
@@ -56,6 +56,9 @@ class DungeonEditor : public Editor,
void CalculateUsageStats(); void CalculateUsageStats();
void DrawUsageStats(); void DrawUsageStats();
void DrawUsageGrid();
void RenderSetUsage(const absl::flat_hash_map<uint16_t, int>& usage_map,
uint16_t& selected_set);
enum BackgroundType { enum BackgroundType {
kNoBackground, kNoBackground,
@@ -82,6 +85,7 @@ class DungeonEditor : public Editor,
ImVector<int> active_rooms_; ImVector<int> active_rooms_;
GfxGroupEditor gfx_group_editor_;
PaletteEditor palette_editor_; PaletteEditor palette_editor_;
gfx::SNESPalette current_palette_; gfx::SNESPalette current_palette_;
gfx::SNESPalette full_palette_; gfx::SNESPalette full_palette_;
@@ -102,6 +106,11 @@ class DungeonEditor : public Editor,
absl::flat_hash_map<uint16_t, int> spriteset_usage_; 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> blockset_usage_;
absl::flat_hash_map<uint16_t, int> palette_usage_; absl::flat_hash_map<uint16_t, int> palette_usage_;
// Add member variables to track the selected set
uint16_t selected_blockset_ = 0xFFFF; // 0xFFFF indicates no selection
uint16_t selected_spriteset_ = 0xFFFF;
uint16_t selected_palette_ = 0xFFFF;
}; };
} // namespace editor } // namespace editor

View File

@@ -33,14 +33,52 @@ absl::Status GfxGroupEditor::Update() {
if (ImGui::BeginTabBar("GfxGroupEditor")) { if (ImGui::BeginTabBar("GfxGroupEditor")) {
if (ImGui::BeginTabItem("Main")) { if (ImGui::BeginTabItem("Main")) {
gui::InputHexByte("Selected Blockset", &selected_blockset_); gui::InputHexByte("Selected Blockset", &selected_blockset_);
DrawBlocksetViewer();
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Rooms")) {
gui::InputHexByte("Selected Blockset", &selected_roomset_);
DrawRoomsetViewer();
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Sprites")) {
gui::InputHexByte("Selected Spriteset", &selected_spriteset_);
ImGui::Text("Values"); ImGui::Text("Values");
if (ImGui::BeginTable("##BlocksetTable", 2, ImGuiTableFlags_Borders, DrawSpritesetViewer();
ImVec2(0, 0))) { ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Palettes")) {
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
ImGui::Separator();
ImGui::Text("Palette: ");
ImGui::InputInt("##PreviewPaletteID", &preview_palette_id_);
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, TableSetupColumn("Inputs", ImGuiTableColumnFlags_WidthStretch,
ImGui::GetContentRegionAvail().x); ImGui::GetContentRegionAvail().x);
}
TableSetupColumn("Sheets", ImGuiTableColumnFlags_WidthFixed, 256); TableSetupColumn("Sheets", ImGuiTableColumnFlags_WidthFixed, 256);
TableHeadersRow(); TableHeadersRow();
TableNextRow(); TableNextRow();
if (!sheet_only) {
TableNextColumn(); TableNextColumn();
{ {
ImGui::BeginGroup(); ImGui::BeginGroup();
@@ -54,6 +92,7 @@ absl::Status GfxGroupEditor::Update() {
} }
ImGui::EndGroup(); ImGui::EndGroup();
} }
}
TableNextColumn(); TableNextColumn();
{ {
ImGui::BeginGroup(); ImGui::BeginGroup();
@@ -74,13 +113,9 @@ absl::Status GfxGroupEditor::Update() {
} }
ImGui::EndTable(); ImGui::EndTable();
} }
}
ImGui::EndTabItem(); void GfxGroupEditor::DrawRoomsetViewer() {
}
if (ImGui::BeginTabItem("Rooms")) {
gui::InputHexByte("Selected Blockset", &selected_roomset_);
ImGui::Text("Values - Overwrites 4 of main blockset"); ImGui::Text("Values - Overwrites 4 of main blockset");
if (ImGui::BeginTable("##Roomstable", 2, ImGuiTableFlags_Borders, if (ImGui::BeginTable("##Roomstable", 2, ImGuiTableFlags_Borders,
ImVec2(0, 0))) { ImVec2(0, 0))) {
@@ -115,21 +150,19 @@ absl::Status GfxGroupEditor::Update() {
} }
ImGui::EndTable(); ImGui::EndTable();
} }
}
ImGui::EndTabItem(); void GfxGroupEditor::DrawSpritesetViewer(bool sheet_only) {
} if (ImGui::BeginTable("##SpritesTable", sheet_only ? 1 : 2,
ImGuiTableFlags_Borders, ImVec2(0, 0))) {
if (ImGui::BeginTabItem("Sprites")) { if (!sheet_only) {
gui::InputHexByte("Selected Spriteset", &selected_spriteset_);
ImGui::Text("Values");
if (ImGui::BeginTable("##SpritesTable", 2, ImGuiTableFlags_Borders,
ImVec2(0, 0))) {
TableSetupColumn("Inputs", ImGuiTableColumnFlags_WidthStretch, TableSetupColumn("Inputs", ImGuiTableColumnFlags_WidthStretch,
ImGui::GetContentRegionAvail().x); ImGui::GetContentRegionAvail().x);
}
TableSetupColumn("Sheets", ImGuiTableColumnFlags_WidthFixed, 256); TableSetupColumn("Sheets", ImGuiTableColumnFlags_WidthFixed, 256);
TableHeadersRow(); TableHeadersRow();
TableNextRow(); TableNextRow();
if (!sheet_only) {
TableNextColumn(); TableNextColumn();
{ {
ImGui::BeginGroup(); ImGui::BeginGroup();
@@ -143,34 +176,24 @@ absl::Status GfxGroupEditor::Update() {
} }
ImGui::EndGroup(); ImGui::EndGroup();
} }
}
TableNextColumn(); TableNextColumn();
{ {
ImGui::BeginGroup(); ImGui::BeginGroup();
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
int sheet_id = rom()->spriteset_ids[selected_spriteset_][i]; int sheet_id = rom()->spriteset_ids[selected_spriteset_][i];
auto sheet = *rom()->bitmap_manager()[sheet_id]; auto sheet = *rom()->bitmap_manager()[115 + sheet_id];
gui::BitmapCanvasPipeline(spriteset_canvas_, sheet, 256, gui::BitmapCanvasPipeline(spriteset_canvas_, sheet, 256, 0x10 * 0x04,
0x10 * 0x04, 0x20, true, false, 24); 0x20, true, false, 24);
} }
ImGui::EndGroup(); ImGui::EndGroup();
} }
ImGui::EndTable(); ImGui::EndTable();
} }
ImGui::EndTabItem(); }
}
if (ImGui::BeginTabItem("Palettes")) { void GfxGroupEditor::DrawPaletteViewer() {
ImGui::EndTabItem(); // TODO: Implement palette viewer
}
ImGui::EndTabBar();
}
ImGui::Separator();
ImGui::Text("Palette: ");
ImGui::InputInt("##PreviewPaletteID", &preview_palette_id_);
return absl::OkStatus();
} }
void GfxGroupEditor::InitBlockset(gfx::Bitmap tile16_blockset) { void GfxGroupEditor::InitBlockset(gfx::Bitmap tile16_blockset) {

View File

@@ -8,13 +8,13 @@
#include "absl/status/status.h" #include "absl/status/status.h"
#include "absl/status/statusor.h" #include "absl/status/statusor.h"
#include "app/core/editor.h" #include "app/core/editor.h"
#include "app/gui/pipeline.h"
#include "app/editor/modules/palette_editor.h" #include "app/editor/modules/palette_editor.h"
#include "app/gfx/bitmap.h" #include "app/gfx/bitmap.h"
#include "app/gfx/snes_palette.h" #include "app/gfx/snes_palette.h"
#include "app/gfx/snes_tile.h" #include "app/gfx/snes_tile.h"
#include "app/gui/canvas.h" #include "app/gui/canvas.h"
#include "app/gui/icons.h" #include "app/gui/icons.h"
#include "app/gui/pipeline.h"
#include "app/gui/widgets.h" #include "app/gui/widgets.h"
#include "app/rom.h" #include "app/rom.h"
#include "app/zelda3/overworld.h" #include "app/zelda3/overworld.h"
@@ -27,6 +27,17 @@ class GfxGroupEditor : public SharedROM {
public: public:
absl::Status Update(); 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); void InitBlockset(gfx::Bitmap tile16_blockset);
private: private: