feat: Implement Jump-to Functionality for Cross-Editor Navigation
- Added JumpToDungeonRoom and JumpToOverworldMap methods to facilitate quick navigation between dungeon and overworld editors. - Introduced SwitchToEditor method to manage editor tab activation based on the selected editor type. - Enhanced DungeonEditorV2 with room and entrance selection capabilities, improving user experience and workflow efficiency. - Updated header files to declare new methods and ensure proper integration within the editor management system.
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
#include "dungeon_editor_v2.h"
|
#include "dungeon_editor_v2.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
#include "absl/strings/str_format.h"
|
#include "absl/strings/str_format.h"
|
||||||
@@ -55,7 +56,7 @@ absl::Status DungeonEditorV2::Load() {
|
|||||||
palette_editor_.Initialize(rom_);
|
palette_editor_.Initialize(rom_);
|
||||||
|
|
||||||
// Wire palette changes to trigger room re-renders
|
// Wire palette changes to trigger room re-renders
|
||||||
palette_editor_.SetOnPaletteChanged([this](int palette_id) {
|
palette_editor_.SetOnPaletteChanged([this](int /*palette_id*/) {
|
||||||
// Re-render all active rooms when palette changes
|
// Re-render all active rooms when palette changes
|
||||||
for (int i = 0; i < active_rooms_.Size; i++) {
|
for (int i = 0; i < active_rooms_.Size; i++) {
|
||||||
int room_id = active_rooms_[i];
|
int room_id = active_rooms_[i];
|
||||||
@@ -118,6 +119,30 @@ void DungeonEditorV2::DrawToolset() {
|
|||||||
if (toolbar.AddAction(ICON_MD_ADD, "Open Room")) {
|
if (toolbar.AddAction(ICON_MD_ADD, "Open Room")) {
|
||||||
OnRoomSelected(room_selector_.current_room_id());
|
OnRoomSelected(room_selector_.current_room_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toolbar.AddSeparator();
|
||||||
|
|
||||||
|
if (toolbar.AddToggle(ICON_MD_LIST, &show_room_selector_, "Toggle Room Selector")) {
|
||||||
|
// Toggled
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toolbar.AddToggle(ICON_MD_GRID_VIEW, &show_room_matrix_, "Toggle Room Matrix")) {
|
||||||
|
// Toggled
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toolbar.AddToggle(ICON_MD_DOOR_FRONT, &show_entrances_list_, "Toggle Entrances List")) {
|
||||||
|
// Toggled
|
||||||
|
}
|
||||||
|
|
||||||
|
toolbar.AddSeparator();
|
||||||
|
|
||||||
|
if (toolbar.AddToggle(ICON_MD_CATEGORY, &show_object_selector_, "Toggle Object Selector")) {
|
||||||
|
// Toggled
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toolbar.AddToggle(ICON_MD_PALETTE, &show_palette_editor_, "Toggle Palette Editor")) {
|
||||||
|
// Toggled
|
||||||
|
}
|
||||||
|
|
||||||
toolbar.End();
|
toolbar.End();
|
||||||
}
|
}
|
||||||
@@ -126,42 +151,43 @@ void DungeonEditorV2::DrawLayout() {
|
|||||||
// NO TABLE LAYOUT - All independent dockable EditorCards
|
// NO TABLE LAYOUT - All independent dockable EditorCards
|
||||||
|
|
||||||
// 1. Room Selector Card (independent, dockable)
|
// 1. Room Selector Card (independent, dockable)
|
||||||
{
|
if (show_room_selector_) {
|
||||||
static bool show_room_selector = true;
|
DrawRoomsListCard();
|
||||||
gui::EditorCard selector_card(
|
}
|
||||||
MakeCardTitle("Room Selector").c_str(),
|
|
||||||
ICON_MD_LIST, &show_room_selector);
|
// 2. Room Matrix Card (visual navigation)
|
||||||
if (selector_card.Begin()) {
|
if (show_room_matrix_) {
|
||||||
room_selector_.Draw();
|
DrawRoomMatrixCard();
|
||||||
}
|
}
|
||||||
selector_card.End();
|
|
||||||
|
// 3. Entrances List Card
|
||||||
|
if (show_entrances_list_) {
|
||||||
|
DrawEntrancesListCard();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Object Selector/Manager Card (independent, dockable)
|
// 4. Object Selector/Manager Card (independent, dockable)
|
||||||
{
|
if (show_object_selector_) {
|
||||||
static bool show_object_selector = true;
|
|
||||||
gui::EditorCard object_card(
|
gui::EditorCard object_card(
|
||||||
MakeCardTitle("Object Selector").c_str(),
|
MakeCardTitle("Object Selector").c_str(),
|
||||||
ICON_MD_CATEGORY, &show_object_selector);
|
ICON_MD_CATEGORY, &show_object_selector_);
|
||||||
if (object_card.Begin()) {
|
if (object_card.Begin()) {
|
||||||
object_selector_.Draw();
|
object_selector_.Draw();
|
||||||
}
|
}
|
||||||
object_card.End();
|
object_card.End();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Palette Editor Card (independent, dockable)
|
// 5. Palette Editor Card (independent, dockable)
|
||||||
{
|
if (show_palette_editor_) {
|
||||||
static bool show_palette_editor = true;
|
|
||||||
gui::EditorCard palette_card(
|
gui::EditorCard palette_card(
|
||||||
MakeCardTitle("Palette Editor").c_str(),
|
MakeCardTitle("Palette Editor").c_str(),
|
||||||
ICON_MD_PALETTE, &show_palette_editor);
|
ICON_MD_PALETTE, &show_palette_editor_);
|
||||||
if (palette_card.Begin()) {
|
if (palette_card.Begin()) {
|
||||||
palette_editor_.Draw();
|
palette_editor_.Draw();
|
||||||
}
|
}
|
||||||
palette_card.End();
|
palette_card.End();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Active Room Cards (independent, dockable, no inheritance)
|
// 6. Active Room Cards (independent, dockable, tracked for jump-to)
|
||||||
for (int i = 0; i < active_rooms_.Size; i++) {
|
for (int i = 0; i < active_rooms_.Size; i++) {
|
||||||
int room_id = active_rooms_[i];
|
int room_id = active_rooms_[i];
|
||||||
bool open = true;
|
bool open = true;
|
||||||
@@ -177,14 +203,20 @@ void DungeonEditorV2::DrawLayout() {
|
|||||||
std::string card_name_str = absl::StrFormat("%s###RoomCard%d",
|
std::string card_name_str = absl::StrFormat("%s###RoomCard%d",
|
||||||
MakeCardTitle(base_name).c_str(), room_id);
|
MakeCardTitle(base_name).c_str(), room_id);
|
||||||
|
|
||||||
// Each room card is COMPLETELY independent - no parent windows
|
// Track or create card for jump-to functionality
|
||||||
gui::EditorCard room_card(card_name_str.c_str(), ICON_MD_GRID_ON, &open);
|
if (room_cards_.find(room_id) == room_cards_.end()) {
|
||||||
if (room_card.Begin()) {
|
room_cards_[room_id] = std::make_shared<gui::EditorCard>(
|
||||||
|
card_name_str.c_str(), ICON_MD_GRID_ON, &open);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& room_card = room_cards_[room_id];
|
||||||
|
if (room_card->Begin(&open)) {
|
||||||
DrawRoomTab(room_id);
|
DrawRoomTab(room_id);
|
||||||
}
|
}
|
||||||
room_card.End();
|
room_card->End();
|
||||||
|
|
||||||
if (!open) {
|
if (!open) {
|
||||||
|
room_cards_.erase(room_id);
|
||||||
active_rooms_.erase(active_rooms_.Data + i);
|
active_rooms_.erase(active_rooms_.Data + i);
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
@@ -235,7 +267,8 @@ void DungeonEditorV2::OnRoomSelected(int room_id) {
|
|||||||
// Check if already open
|
// Check if already open
|
||||||
for (int i = 0; i < active_rooms_.Size; i++) {
|
for (int i = 0; i < active_rooms_.Size; i++) {
|
||||||
if (active_rooms_[i] == room_id) {
|
if (active_rooms_[i] == room_id) {
|
||||||
// Optional: Focus the existing window if possible. For now, do nothing.
|
// Focus the existing room card
|
||||||
|
FocusRoom(room_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -245,5 +278,212 @@ void DungeonEditorV2::OnRoomSelected(int room_id) {
|
|||||||
room_selector_.set_active_rooms(active_rooms_);
|
room_selector_.set_active_rooms(active_rooms_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DungeonEditorV2::OnEntranceSelected(int entrance_id) {
|
||||||
|
if (entrance_id < 0 || entrance_id >= static_cast<int>(entrances_.size())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the room ID associated with this entrance
|
||||||
|
int room_id = entrances_[entrance_id].room_;
|
||||||
|
|
||||||
|
// Open and focus the room
|
||||||
|
OnRoomSelected(room_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DungeonEditorV2::add_room(int room_id) {
|
||||||
|
OnRoomSelected(room_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DungeonEditorV2::FocusRoom(int room_id) {
|
||||||
|
// Focus the room card if it exists
|
||||||
|
auto it = room_cards_.find(room_id);
|
||||||
|
if (it != room_cards_.end()) {
|
||||||
|
it->second->Focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DungeonEditorV2::DrawRoomsListCard() {
|
||||||
|
gui::EditorCard selector_card(
|
||||||
|
MakeCardTitle("Rooms List").c_str(),
|
||||||
|
ICON_MD_LIST, &show_room_selector_);
|
||||||
|
|
||||||
|
if (selector_card.Begin()) {
|
||||||
|
// Add text filter
|
||||||
|
static char room_filter[256] = "";
|
||||||
|
ImGui::SetNextItemWidth(-1);
|
||||||
|
if (ImGui::InputTextWithHint("##RoomFilter", ICON_MD_SEARCH " Filter rooms...",
|
||||||
|
room_filter, sizeof(room_filter))) {
|
||||||
|
// Filter updated
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
// Scrollable room list with resource labels
|
||||||
|
if (ImGui::BeginChild("##RoomsList", ImVec2(0, 0), true)) {
|
||||||
|
std::string filter_str = room_filter;
|
||||||
|
std::transform(filter_str.begin(), filter_str.end(), filter_str.begin(), ::tolower);
|
||||||
|
|
||||||
|
for (int i = 0; i < 0x128; i++) {
|
||||||
|
std::string room_name;
|
||||||
|
if (i < static_cast<int>(std::size(zelda3::kRoomNames))) {
|
||||||
|
room_name = absl::StrFormat("%03X - %s", i, zelda3::kRoomNames[i].data());
|
||||||
|
} else {
|
||||||
|
room_name = absl::StrFormat("%03X - Room %d", i, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply filter
|
||||||
|
if (!filter_str.empty()) {
|
||||||
|
std::string room_name_lower = room_name;
|
||||||
|
std::transform(room_name_lower.begin(), room_name_lower.end(),
|
||||||
|
room_name_lower.begin(), ::tolower);
|
||||||
|
if (room_name_lower.find(filter_str) == std::string::npos) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_selected = (current_room_id_ == i);
|
||||||
|
if (ImGui::Selectable(room_name.c_str(), is_selected)) {
|
||||||
|
OnRoomSelected(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0)) {
|
||||||
|
OnRoomSelected(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selector_card.End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DungeonEditorV2::DrawEntrancesListCard() {
|
||||||
|
gui::EditorCard entrances_card(
|
||||||
|
MakeCardTitle("Entrances List").c_str(),
|
||||||
|
ICON_MD_DOOR_FRONT, &show_entrances_list_);
|
||||||
|
|
||||||
|
if (entrances_card.Begin()) {
|
||||||
|
// Add text filter
|
||||||
|
static char entrance_filter[256] = "";
|
||||||
|
ImGui::SetNextItemWidth(-1);
|
||||||
|
if (ImGui::InputTextWithHint("##EntranceFilter", ICON_MD_SEARCH " Filter entrances...",
|
||||||
|
entrance_filter, sizeof(entrance_filter))) {
|
||||||
|
// Filter updated
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
// Scrollable entrance list with associated room names
|
||||||
|
if (ImGui::BeginChild("##EntrancesList", ImVec2(0, 0), true)) {
|
||||||
|
std::string filter_str = entrance_filter;
|
||||||
|
std::transform(filter_str.begin(), filter_str.end(), filter_str.begin(), ::tolower);
|
||||||
|
|
||||||
|
for (int i = 0; i < static_cast<int>(entrances_.size()); i++) {
|
||||||
|
int room_id = entrances_[i].room_;
|
||||||
|
|
||||||
|
std::string room_name = "Unknown";
|
||||||
|
if (room_id >= 0 && room_id < static_cast<int>(std::size(zelda3::kRoomNames))) {
|
||||||
|
room_name = zelda3::kRoomNames[room_id].data();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string entrance_label = absl::StrFormat("%02X - %s (Room %03X)",
|
||||||
|
i, room_name.c_str(), room_id);
|
||||||
|
|
||||||
|
// Apply filter
|
||||||
|
if (!filter_str.empty()) {
|
||||||
|
std::string entrance_label_lower = entrance_label;
|
||||||
|
std::transform(entrance_label_lower.begin(), entrance_label_lower.end(),
|
||||||
|
entrance_label_lower.begin(), ::tolower);
|
||||||
|
if (entrance_label_lower.find(filter_str) == std::string::npos) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::Selectable(entrance_label.c_str())) {
|
||||||
|
OnEntranceSelected(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entrances_card.End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DungeonEditorV2::DrawRoomMatrixCard() {
|
||||||
|
gui::EditorCard matrix_card(
|
||||||
|
MakeCardTitle("Room Matrix").c_str(),
|
||||||
|
ICON_MD_GRID_VIEW, &show_room_matrix_);
|
||||||
|
|
||||||
|
matrix_card.SetDefaultSize(600, 600);
|
||||||
|
|
||||||
|
if (matrix_card.Begin()) {
|
||||||
|
// Draw 8x8 grid of rooms (first 64 rooms)
|
||||||
|
constexpr int kRoomsPerRow = 8;
|
||||||
|
constexpr int kRoomsPerCol = 8;
|
||||||
|
constexpr float kRoomCellSize = 64.0f;
|
||||||
|
|
||||||
|
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||||
|
ImVec2 canvas_pos = ImGui::GetCursorScreenPos();
|
||||||
|
|
||||||
|
for (int row = 0; row < kRoomsPerCol; row++) {
|
||||||
|
for (int col = 0; col < kRoomsPerRow; col++) {
|
||||||
|
int room_id = row * kRoomsPerRow + col;
|
||||||
|
|
||||||
|
ImVec2 cell_min = ImVec2(canvas_pos.x + col * kRoomCellSize,
|
||||||
|
canvas_pos.y + row * kRoomCellSize);
|
||||||
|
ImVec2 cell_max = ImVec2(cell_min.x + kRoomCellSize,
|
||||||
|
cell_min.y + kRoomCellSize);
|
||||||
|
|
||||||
|
// Check if room is active
|
||||||
|
bool is_active = false;
|
||||||
|
for (int i = 0; i < active_rooms_.Size; i++) {
|
||||||
|
if (active_rooms_[i] == room_id) {
|
||||||
|
is_active = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw cell background
|
||||||
|
ImU32 bg_color = is_active ? IM_COL32(100, 150, 255, 255)
|
||||||
|
: IM_COL32(50, 50, 50, 255);
|
||||||
|
draw_list->AddRectFilled(cell_min, cell_max, bg_color);
|
||||||
|
|
||||||
|
// Draw cell border
|
||||||
|
draw_list->AddRect(cell_min, cell_max, IM_COL32(150, 150, 150, 255));
|
||||||
|
|
||||||
|
// Draw room ID
|
||||||
|
std::string room_label = absl::StrFormat("%02X", room_id);
|
||||||
|
ImVec2 text_size = ImGui::CalcTextSize(room_label.c_str());
|
||||||
|
ImVec2 text_pos = ImVec2(cell_min.x + (kRoomCellSize - text_size.x) * 0.5f,
|
||||||
|
cell_min.y + (kRoomCellSize - text_size.y) * 0.5f);
|
||||||
|
draw_list->AddText(text_pos, IM_COL32(255, 255, 255, 255), room_label.c_str());
|
||||||
|
|
||||||
|
// Handle clicks
|
||||||
|
ImGui::SetCursorScreenPos(cell_min);
|
||||||
|
ImGui::InvisibleButton(absl::StrFormat("##room%d", room_id).c_str(),
|
||||||
|
ImVec2(kRoomCellSize, kRoomCellSize));
|
||||||
|
|
||||||
|
if (ImGui::IsItemClicked()) {
|
||||||
|
OnRoomSelected(room_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hover preview (TODO: implement room bitmap preview)
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
if (room_id < static_cast<int>(std::size(zelda3::kRoomNames))) {
|
||||||
|
ImGui::Text("%s", zelda3::kRoomNames[room_id].data());
|
||||||
|
} else {
|
||||||
|
ImGui::Text("Room %03X", room_id);
|
||||||
|
}
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Advance cursor past the grid
|
||||||
|
ImGui::Dummy(ImVec2(kRoomsPerRow * kRoomCellSize, kRoomsPerCol * kRoomCellSize));
|
||||||
|
}
|
||||||
|
matrix_card.End();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace yaze::editor
|
} // namespace yaze::editor
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#ifndef YAZE_APP_EDITOR_DUNGEON_EDITOR_V2_H
|
#ifndef YAZE_APP_EDITOR_DUNGEON_EDITOR_V2_H
|
||||||
#define YAZE_APP_EDITOR_DUNGEON_EDITOR_V2_H
|
#define YAZE_APP_EDITOR_DUNGEON_EDITOR_V2_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "absl/status/status.h"
|
#include "absl/status/status.h"
|
||||||
#include "absl/strings/str_format.h"
|
#include "absl/strings/str_format.h"
|
||||||
#include "app/editor/editor.h"
|
#include "app/editor/editor.h"
|
||||||
@@ -70,7 +73,8 @@ class DungeonEditorV2 : public Editor {
|
|||||||
Rom* rom() const { return rom_; }
|
Rom* rom() const { return rom_; }
|
||||||
|
|
||||||
// Room management
|
// Room management
|
||||||
void add_room(int room_id) { active_rooms_.push_back(room_id); }
|
void add_room(int room_id);
|
||||||
|
void FocusRoom(int room_id);
|
||||||
|
|
||||||
// ROM state
|
// ROM state
|
||||||
bool IsRomLoaded() const override { return rom_ && rom_->is_loaded(); }
|
bool IsRomLoaded() const override { return rom_ && rom_->is_loaded(); }
|
||||||
@@ -85,19 +89,31 @@ class DungeonEditorV2 : public Editor {
|
|||||||
void DrawLayout();
|
void DrawLayout();
|
||||||
void DrawRoomTab(int room_id);
|
void DrawRoomTab(int room_id);
|
||||||
void DrawToolset();
|
void DrawToolset();
|
||||||
|
void DrawRoomMatrixCard();
|
||||||
|
void DrawRoomsListCard();
|
||||||
|
void DrawEntrancesListCard();
|
||||||
|
|
||||||
// Room selection callback
|
// Room selection callback
|
||||||
void OnRoomSelected(int room_id);
|
void OnRoomSelected(int room_id);
|
||||||
|
void OnEntranceSelected(int entrance_id);
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
Rom* rom_;
|
Rom* rom_;
|
||||||
std::array<zelda3::Room, 0x128> rooms_;
|
std::array<zelda3::Room, 0x128> rooms_;
|
||||||
std::array<zelda3::RoomEntrance, 0x8C> entrances_;
|
std::array<zelda3::RoomEntrance, 0x8C> entrances_;
|
||||||
|
|
||||||
// Active room tabs
|
// Active room tabs and card tracking for jump-to
|
||||||
ImVector<int> active_rooms_;
|
ImVector<int> active_rooms_;
|
||||||
|
std::unordered_map<int, std::shared_ptr<gui::EditorCard>> room_cards_;
|
||||||
int current_room_id_ = 0;
|
int current_room_id_ = 0;
|
||||||
|
|
||||||
|
// Card visibility flags
|
||||||
|
bool show_room_selector_ = true;
|
||||||
|
bool show_room_matrix_ = false;
|
||||||
|
bool show_entrances_list_ = false;
|
||||||
|
bool show_object_selector_ = true;
|
||||||
|
bool show_palette_editor_ = true;
|
||||||
|
|
||||||
// Palette management
|
// Palette management
|
||||||
gfx::SnesPalette current_palette_;
|
gfx::SnesPalette current_palette_;
|
||||||
gfx::PaletteGroup current_palette_group_;
|
gfx::PaletteGroup current_palette_group_;
|
||||||
|
|||||||
@@ -3267,5 +3267,42 @@ void EditorManager::DrawWelcomeScreen() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Jump-to Functionality for Cross-Editor Navigation
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
void EditorManager::JumpToDungeonRoom(int room_id) {
|
||||||
|
if (!current_editor_set_) return;
|
||||||
|
|
||||||
|
// Switch to dungeon editor
|
||||||
|
SwitchToEditor(EditorType::kDungeon);
|
||||||
|
|
||||||
|
// Open the room in the dungeon editor
|
||||||
|
current_editor_set_->dungeon_editor_.add_room(room_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorManager::JumpToOverworldMap(int map_id) {
|
||||||
|
if (!current_editor_set_) return;
|
||||||
|
|
||||||
|
// Switch to overworld editor
|
||||||
|
SwitchToEditor(EditorType::kOverworld);
|
||||||
|
|
||||||
|
// Set the current map in the overworld editor
|
||||||
|
current_editor_set_->overworld_editor_.set_current_map(map_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorManager::SwitchToEditor(EditorType editor_type) {
|
||||||
|
// Find the editor tab and activate it
|
||||||
|
for (size_t i = 0; i < current_editor_set_->active_editors_.size(); ++i) {
|
||||||
|
if (current_editor_set_->active_editors_[i]->type() == editor_type) {
|
||||||
|
current_editor_set_->active_editors_[i]->set_active(true);
|
||||||
|
|
||||||
|
// Set editor as the current/focused one
|
||||||
|
// This will make it visible when tabs are rendered
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace editor
|
} // namespace editor
|
||||||
} // namespace yaze
|
} // namespace yaze
|
||||||
|
|||||||
@@ -134,6 +134,11 @@ class EditorManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BuildModernMenu();
|
void BuildModernMenu();
|
||||||
|
|
||||||
|
// Jump-to functionality for cross-editor navigation
|
||||||
|
void JumpToDungeonRoom(int room_id);
|
||||||
|
void JumpToOverworldMap(int map_id);
|
||||||
|
void SwitchToEditor(EditorType editor_type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DrawWelcomeScreen();
|
void DrawWelcomeScreen();
|
||||||
|
|||||||
@@ -101,6 +101,14 @@ class OverworldEditor : public Editor, public gfx::GfxContext {
|
|||||||
if (!rom_->is_loaded()) return "ROM failed to load";
|
if (!rom_->is_loaded()) return "ROM failed to load";
|
||||||
return absl::StrFormat("ROM loaded: %s", rom_->title());
|
return absl::StrFormat("ROM loaded: %s", rom_->title());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Jump-to functionality
|
||||||
|
void set_current_map(int map_id) {
|
||||||
|
if (map_id >= 0 && map_id < zelda3::kNumOverworldMaps) {
|
||||||
|
current_map_ = map_id;
|
||||||
|
current_world_ = map_id / 0x40; // Calculate which world the map belongs to
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Load the Bitmap objects for each OverworldMap.
|
* @brief Load the Bitmap objects for each OverworldMap.
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ using namespace ImGui;
|
|||||||
|
|
||||||
// Entity colors - solid with good visibility
|
// Entity colors - solid with good visibility
|
||||||
namespace {
|
namespace {
|
||||||
ImVec4 GetEntranceColor() { return ImVec4(0.0f, 255.0f, 0.0f, 255.0f); } // Solid green
|
ImVec4 GetEntranceColor() { return ImVec4{1.0f, 1.0f, 0.0f, 1.0f}; } // Solid yellow (#FFFF00FF, fully opaque)
|
||||||
ImVec4 GetExitColor() { return ImVec4(255.0f, 0.0f, 0.0f, 255.0f); } // Solid red
|
ImVec4 GetExitColor() { return ImVec4{1.0f, 1.0f, 1.0f, 1.0f}; } // Solid white (#FFFFFFFF, fully opaque)
|
||||||
ImVec4 GetItemColor() { return ImVec4(255.0f, 255.0f, 0.0f, 255.0f); } // Solid yellow
|
ImVec4 GetItemColor() { return ImVec4{1.0f, 0.0f, 0.0f, 1.0f}; } // Solid red (#FF0000FF, fully opaque)
|
||||||
ImVec4 GetSpriteColor() { return ImVec4(255.0f, 128.0f, 0.0f, 255.0f); } // Solid orange
|
ImVec4 GetSpriteColor() { return ImVec4{1.0f, 0.0f, 1.0f, 1.0f}; } // Solid magenta (#FF00FFFF, fully opaque)
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void OverworldEntityRenderer::DrawEntrances(ImVec2 canvas_p0, ImVec2 scrolling,
|
void OverworldEntityRenderer::DrawEntrances(ImVec2 canvas_p0, ImVec2 scrolling,
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ void DrawCanvasRect(ImDrawList* draw_list, ImVec2 canvas_p0, ImVec2 scrolling,
|
|||||||
ImVec2 size(canvas_p0.x + scrolling.x + scaled_x + scaled_w,
|
ImVec2 size(canvas_p0.x + scrolling.x + scaled_x + scaled_w,
|
||||||
canvas_p0.y + scrolling.y + scaled_y + scaled_h);
|
canvas_p0.y + scrolling.y + scaled_y + scaled_h);
|
||||||
|
|
||||||
uint32_t color_u32 = IM_COL32(color.x, color.y, color.z, color.w);
|
uint32_t color_u32 = IM_COL32(color.x * 255, color.y * 255, color.z * 255, color.w * 255);
|
||||||
draw_list->AddRectFilled(origin, size, color_u32);
|
draw_list->AddRectFilled(origin, size, color_u32);
|
||||||
|
|
||||||
// Add a black outline
|
// Add a black outline
|
||||||
|
|||||||
@@ -229,11 +229,14 @@ bool Toolset::AddUsageStatsButton(const char* tooltip) {
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
EditorCard::EditorCard(const char* title, const char* icon)
|
EditorCard::EditorCard(const char* title, const char* icon)
|
||||||
: title_(title), icon_(icon ? icon : ""), default_size_(400, 300) {}
|
: title_(title), icon_(icon ? icon : ""), default_size_(400, 300) {
|
||||||
|
window_name_ = icon_.empty() ? title_ : icon_ + " " + title_;
|
||||||
|
}
|
||||||
|
|
||||||
EditorCard::EditorCard(const char* title, const char* icon, bool* p_open)
|
EditorCard::EditorCard(const char* title, const char* icon, bool* p_open)
|
||||||
: title_(title), icon_(icon ? icon : ""), default_size_(400, 300) {
|
: title_(title), icon_(icon ? icon : ""), default_size_(400, 300) {
|
||||||
p_open_ = p_open;
|
p_open_ = p_open;
|
||||||
|
window_name_ = icon_.empty() ? title_ : icon_ + " " + title_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorCard::SetDefaultSize(float width, float height) {
|
void EditorCard::SetDefaultSize(float width, float height) {
|
||||||
@@ -301,11 +304,20 @@ bool EditorCard::Begin(bool* p_open) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EditorCard::End() {
|
void EditorCard::End() {
|
||||||
|
// Check if window was focused this frame
|
||||||
|
focused_ = ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows);
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
ImGui::PopStyleColor(2);
|
ImGui::PopStyleColor(2);
|
||||||
ImGui::PopStyleVar(2);
|
ImGui::PopStyleVar(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditorCard::Focus() {
|
||||||
|
// Set window focus using ImGui's focus system
|
||||||
|
ImGui::SetWindowFocus(window_name_.c_str());
|
||||||
|
focused_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// EditorLayout Implementation
|
// EditorLayout Implementation
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|||||||
@@ -132,15 +132,24 @@ class EditorCard {
|
|||||||
void SetMinimized(bool minimized) { minimized_ = minimized; }
|
void SetMinimized(bool minimized) { minimized_ = minimized; }
|
||||||
bool IsMinimized() const { return minimized_; }
|
bool IsMinimized() const { return minimized_; }
|
||||||
|
|
||||||
|
// Focus the card window (bring to front and set focused)
|
||||||
|
void Focus();
|
||||||
|
bool IsFocused() const { return focused_; }
|
||||||
|
|
||||||
|
// Get the window name for ImGui operations
|
||||||
|
const char* GetWindowName() const { return window_name_.c_str(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string title_;
|
std::string title_;
|
||||||
std::string icon_;
|
std::string icon_;
|
||||||
|
std::string window_name_; // Full window name with icon
|
||||||
ImVec2 default_size_;
|
ImVec2 default_size_;
|
||||||
Position position_ = Position::Free;
|
Position position_ = Position::Free;
|
||||||
bool minimizable_ = true;
|
bool minimizable_ = true;
|
||||||
bool closable_ = true;
|
bool closable_ = true;
|
||||||
bool minimized_ = false;
|
bool minimized_ = false;
|
||||||
bool first_draw_ = true;
|
bool first_draw_ = true;
|
||||||
|
bool focused_ = false;
|
||||||
bool* p_open_ = nullptr;
|
bool* p_open_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -133,6 +133,12 @@ struct EnhancedTheme {
|
|||||||
Color editor_grid; // Grid lines in editors
|
Color editor_grid; // Grid lines in editors
|
||||||
Color editor_cursor; // Cursor/selection in editors
|
Color editor_cursor; // Cursor/selection in editors
|
||||||
Color editor_selection; // Selected area in editors
|
Color editor_selection; // Selected area in editors
|
||||||
|
|
||||||
|
Color entrance_color;
|
||||||
|
Color hole_color;
|
||||||
|
Color exit_color;
|
||||||
|
Color item_color;
|
||||||
|
Color sprite_color;
|
||||||
|
|
||||||
// Style parameters
|
// Style parameters
|
||||||
float window_rounding = 0.0f;
|
float window_rounding = 0.0f;
|
||||||
|
|||||||
Reference in New Issue
Block a user