#ifndef YAZE_APP_ZELDA3_DUNGEON_DUNGEON_EDITOR_SYSTEM_H #define YAZE_APP_ZELDA3_DUNGEON_DUNGEON_EDITOR_SYSTEM_H #include #include #include #include #include #include "absl/status/status.h" #include "absl/status/statusor.h" #include "app/core/window.h" #include "app/gfx/bitmap.h" #include "app/gfx/snes_palette.h" #include "app/rom.h" #include "zelda3/dungeon/room_object.h" #include "zelda3/dungeon/room.h" #include "zelda3/sprite/sprite.h" #include "dungeon_object_editor.h" namespace yaze { namespace zelda3 { /** * @brief Comprehensive dungeon editing system * * This class provides a complete dungeon editing solution including: * - Object editing (walls, floors, decorations) * - Sprite management (enemies, NPCs, interactive elements) * - Item placement and management * - Entrance/exit data editing * - Door configuration * - Chest and treasure management * - Room properties and metadata * - Dungeon-wide settings */ class DungeonEditorSystem { public: // Editor modes enum class EditorMode { kObjects, // Object editing mode kSprites, // Sprite editing mode kItems, // Item placement mode kEntrances, // Entrance/exit editing mode kDoors, // Door configuration mode kChests, // Chest management mode kProperties, // Room properties mode kGlobal // Dungeon-wide settings mode }; // Sprite types and categories enum class SpriteType { kEnemy, // Hostile entities kNPC, // Non-player characters kInteractive, // Interactive objects kDecoration, // Decorative sprites kBoss, // Boss entities kSpecial // Special purpose sprites }; // Item types enum class ItemType { kWeapon, // Swords, bows, etc. kTool, // Hookshot, bombs, etc. kKey, // Keys and key items kHeart, // Heart containers and pieces kRupee, // Currency kBottle, // Bottles and contents kUpgrade, // Capacity upgrades kSpecial // Special items }; // Entrance/exit types enum class EntranceType { kNormal, // Standard room entrance kStairs, // Staircase connection kDoor, // Door connection kCave, // Cave entrance kWarp, // Warp/teleport kBoss, // Boss room entrance kSpecial // Special entrance type }; // Editor state struct EditorState { EditorMode current_mode = EditorMode::kObjects; int current_room_id = 0; bool is_dirty = false; // Has unsaved changes bool auto_save_enabled = true; std::chrono::steady_clock::time_point last_save_time; }; // Sprite editing data struct SpriteData { int sprite_id; std::string name; DungeonEditorSystem::SpriteType type; int x, y; int layer; std::unordered_map properties; bool is_active = true; }; // Item placement data struct ItemData { int item_id; DungeonEditorSystem::ItemType type; std::string name; int x, y; int room_id; bool is_hidden = false; std::unordered_map properties; }; // Entrance/exit data struct EntranceData { int entrance_id; DungeonEditorSystem::EntranceType type; std::string name; int source_room_id; int target_room_id; int source_x, source_y; int target_x, target_y; bool is_bidirectional = true; std::unordered_map properties; }; // Door configuration data struct DoorData { int door_id; std::string name; int room_id; int x, y; int direction; // 0=up, 1=right, 2=down, 3=left int target_room_id; int target_x, target_y; bool requires_key = false; int key_type = 0; bool is_locked = false; std::unordered_map properties; }; // Chest data struct ChestData { int chest_id; int room_id; int x, y; bool is_big_chest = false; int item_id; int item_quantity = 1; bool is_opened = false; std::unordered_map properties; }; explicit DungeonEditorSystem(Rom* rom); ~DungeonEditorSystem() = default; // System initialization and management absl::Status Initialize(); absl::Status LoadDungeon(int dungeon_id); absl::Status SaveDungeon(); absl::Status SaveRoom(int room_id); absl::Status ReloadRoom(int room_id); // Mode management void SetEditorMode(EditorMode mode); EditorMode GetEditorMode() const; // Room management absl::Status SetCurrentRoom(int room_id); int GetCurrentRoom() const; absl::StatusOr GetRoom(int room_id); absl::Status CreateRoom(int room_id, const std::string& name = ""); absl::Status DeleteRoom(int room_id); absl::Status DuplicateRoom(int source_room_id, int target_room_id); // Object editing (delegated to DungeonObjectEditor) std::shared_ptr GetObjectEditor(); absl::Status SetObjectEditorMode(); // Sprite management absl::Status AddSprite(const SpriteData& sprite_data); absl::Status RemoveSprite(int sprite_id); absl::Status UpdateSprite(int sprite_id, const SpriteData& sprite_data); absl::StatusOr GetSprite(int sprite_id); absl::StatusOr> GetSpritesByRoom(int room_id); absl::StatusOr> GetSpritesByType(DungeonEditorSystem::SpriteType type); absl::Status MoveSprite(int sprite_id, int new_x, int new_y); absl::Status SetSpriteActive(int sprite_id, bool active); // Item management absl::Status AddItem(const ItemData& item_data); absl::Status RemoveItem(int item_id); absl::Status UpdateItem(int item_id, const ItemData& item_data); absl::StatusOr GetItem(int item_id); absl::StatusOr> GetItemsByRoom(int room_id); absl::StatusOr> GetItemsByType(DungeonEditorSystem::ItemType type); absl::Status MoveItem(int item_id, int new_x, int new_y); absl::Status SetItemHidden(int item_id, bool hidden); // Entrance/exit management absl::Status AddEntrance(const EntranceData& entrance_data); absl::Status RemoveEntrance(int entrance_id); absl::Status UpdateEntrance(int entrance_id, const EntranceData& entrance_data); absl::StatusOr GetEntrance(int entrance_id); absl::StatusOr> GetEntrancesByRoom(int room_id); absl::StatusOr> GetEntrancesByType(DungeonEditorSystem::EntranceType type); absl::Status ConnectRooms(int room1_id, int room2_id, int x1, int y1, int x2, int y2); absl::Status DisconnectRooms(int room1_id, int room2_id); // Door management absl::Status AddDoor(const DoorData& door_data); absl::Status RemoveDoor(int door_id); absl::Status UpdateDoor(int door_id, const DoorData& door_data); absl::StatusOr GetDoor(int door_id); absl::StatusOr> GetDoorsByRoom(int room_id); absl::Status SetDoorLocked(int door_id, bool locked); absl::Status SetDoorKeyRequirement(int door_id, bool requires_key, int key_type); // Chest management absl::Status AddChest(const ChestData& chest_data); absl::Status RemoveChest(int chest_id); absl::Status UpdateChest(int chest_id, const ChestData& chest_data); absl::StatusOr GetChest(int chest_id); absl::StatusOr> GetChestsByRoom(int room_id); absl::Status SetChestItem(int chest_id, int item_id, int quantity); absl::Status SetChestOpened(int chest_id, bool opened); // Room properties and metadata struct RoomProperties { int room_id; std::string name; std::string description; int dungeon_id; int floor_level; bool is_boss_room = false; bool is_save_room = false; bool is_shop_room = false; int music_id = 0; int ambient_sound_id = 0; std::unordered_map custom_properties; }; absl::Status SetRoomProperties(int room_id, const RoomProperties& properties); absl::StatusOr GetRoomProperties(int room_id); // Dungeon-wide settings struct DungeonSettings { int dungeon_id; std::string name; std::string description; int total_rooms; int starting_room_id; int boss_room_id; int music_theme_id; int color_palette_id; bool has_map = true; bool has_compass = true; bool has_big_key = true; std::unordered_map custom_settings; }; absl::Status SetDungeonSettings(const DungeonSettings& settings); absl::StatusOr GetDungeonSettings(); // Validation and error checking absl::Status ValidateRoom(int room_id); absl::Status ValidateDungeon(); std::vector GetValidationErrors(int room_id); std::vector GetDungeonValidationErrors(); // Rendering and preview absl::StatusOr RenderRoom(int room_id); absl::StatusOr RenderRoomPreview(int room_id, EditorMode mode); absl::StatusOr RenderDungeonMap(); // Import/Export functionality absl::Status ImportRoomFromFile(const std::string& file_path, int room_id); absl::Status ExportRoomToFile(int room_id, const std::string& file_path); absl::Status ImportDungeonFromFile(const std::string& file_path); absl::Status ExportDungeonToFile(const std::string& file_path); // Undo/Redo system absl::Status Undo(); absl::Status Redo(); bool CanUndo() const; bool CanRedo() const; void ClearHistory(); // Event callbacks using RoomChangedCallback = std::function; using SpriteChangedCallback = std::function; using ItemChangedCallback = std::function; using EntranceChangedCallback = std::function; using DoorChangedCallback = std::function; using ChestChangedCallback = std::function; using ModeChangedCallback = std::function; using ValidationCallback = std::function& errors)>; void SetRoomChangedCallback(RoomChangedCallback callback); void SetSpriteChangedCallback(SpriteChangedCallback callback); void SetItemChangedCallback(ItemChangedCallback callback); void SetEntranceChangedCallback(EntranceChangedCallback callback); void SetDoorChangedCallback(DoorChangedCallback callback); void SetChestChangedCallback(ChestChangedCallback callback); void SetModeChangedCallback(ModeChangedCallback callback); void SetValidationCallback(ValidationCallback callback); // Getters EditorState GetEditorState() const; Rom* GetROM() const; bool IsDirty() const; bool HasUnsavedChanges() const; // ROM management void SetROM(Rom* rom); private: // Internal helper methods absl::Status InitializeObjectEditor(); absl::Status InitializeSpriteSystem(); absl::Status InitializeItemSystem(); absl::Status InitializeEntranceSystem(); absl::Status InitializeDoorSystem(); absl::Status InitializeChestSystem(); // Data management absl::Status LoadRoomData(int room_id); absl::Status SaveRoomData(int room_id); absl::Status LoadSpriteData(); absl::Status SaveSpriteData(); absl::Status LoadItemData(); absl::Status SaveItemData(); absl::Status LoadEntranceData(); absl::Status SaveEntranceData(); absl::Status LoadDoorData(); absl::Status SaveDoorData(); absl::Status LoadChestData(); absl::Status SaveChestData(); // Validation helpers absl::Status ValidateSprite(const SpriteData& sprite); absl::Status ValidateItem(const ItemData& item); absl::Status ValidateEntrance(const EntranceData& entrance); absl::Status ValidateDoor(const DoorData& door); absl::Status ValidateChest(const ChestData& chest); // ID generation int GenerateSpriteId(); int GenerateItemId(); int GenerateEntranceId(); int GenerateDoorId(); int GenerateChestId(); // Member variables Rom* rom_; std::shared_ptr object_editor_; EditorState editor_state_; DungeonSettings dungeon_settings_; // Data storage std::unordered_map rooms_; std::unordered_map sprites_; std::unordered_map items_; std::unordered_map entrances_; std::unordered_map doors_; std::unordered_map chests_; std::unordered_map room_properties_; // ID counters int next_sprite_id_ = 1; int next_item_id_ = 1; int next_entrance_id_ = 1; int next_door_id_ = 1; int next_chest_id_ = 1; // Event callbacks RoomChangedCallback room_changed_callback_; SpriteChangedCallback sprite_changed_callback_; ItemChangedCallback item_changed_callback_; EntranceChangedCallback entrance_changed_callback_; DoorChangedCallback door_changed_callback_; ChestChangedCallback chest_changed_callback_; ModeChangedCallback mode_changed_callback_; ValidationCallback validation_callback_; // Undo/Redo system struct UndoPoint { EditorState state; std::unordered_map rooms; std::unordered_map sprites; std::unordered_map items; std::unordered_map entrances; std::unordered_map doors; std::unordered_map chests; std::chrono::steady_clock::time_point timestamp; }; std::vector undo_history_; std::vector redo_history_; static constexpr size_t kMaxUndoHistory = 100; }; /** * @brief Factory function to create dungeon editor system */ std::unique_ptr CreateDungeonEditorSystem(Rom* rom); /** * @brief Sprite type utilities */ namespace SpriteTypes { /** * @brief Get sprite information by ID */ struct SpriteInfo { int id; std::string name; DungeonEditorSystem::SpriteType type; std::string description; int default_layer; std::vector> default_properties; bool is_interactive; bool is_hostile; int difficulty_rating; }; absl::StatusOr GetSpriteInfo(int sprite_id); std::vector GetAllSpriteInfos(); std::vector GetSpritesByType(DungeonEditorSystem::SpriteType type); absl::StatusOr GetSpriteCategory(int sprite_id); } // namespace SpriteTypes /** * @brief Item type utilities */ namespace ItemTypes { /** * @brief Get item information by ID */ struct ItemInfo { int id; std::string name; DungeonEditorSystem::ItemType type; std::string description; int rarity; int value; std::vector> default_properties; bool is_stackable; int max_stack_size; }; absl::StatusOr GetItemInfo(int item_id); std::vector GetAllItemInfos(); std::vector GetItemsByType(DungeonEditorSystem::ItemType type); absl::StatusOr GetItemCategory(int item_id); } // namespace ItemTypes /** * @brief Entrance type utilities */ namespace EntranceTypes { /** * @brief Get entrance information by ID */ struct EntranceInfo { int id; std::string name; DungeonEditorSystem::EntranceType type; std::string description; std::vector> default_properties; bool requires_key; int key_type; bool is_bidirectional; }; absl::StatusOr GetEntranceInfo(int entrance_id); std::vector GetAllEntranceInfos(); std::vector GetEntrancesByType(DungeonEditorSystem::EntranceType type); } // namespace EntranceTypes } // namespace zelda3 } // namespace yaze #endif // YAZE_APP_ZELDA3_DUNGEON_DUNGEON_EDITOR_SYSTEM_H