////////////////////////////////////////////////////////////////////// // This file is part of Remere's Map Editor ////////////////////////////////////////////////////////////////////// // Remere's Map Editor is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Remere's Map Editor is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . ////////////////////////////////////////////////////////////////////// #include "main.h" #include "settings.h" #include "gui.h" #include "brush.h" #include "map_display.h" #include "palette_window.h" #include "palette_brushlist.h" #include "palette_house.h" #include "palette_creature.h" #include "palette_waypoints.h" #include "house_brush.h" #include "map.h" // ============================================================================ // Palette window BEGIN_EVENT_TABLE(PaletteWindow, wxPanel) EVT_CHOICEBOOK_PAGE_CHANGING(PALETTE_CHOICEBOOK, PaletteWindow::OnSwitchingPage) EVT_CHOICEBOOK_PAGE_CHANGED(PALETTE_CHOICEBOOK, PaletteWindow::OnPageChanged) EVT_CLOSE(PaletteWindow::OnClose) EVT_KEY_DOWN(PaletteWindow::OnKey) EVT_TEXT(wxID_ANY, PaletteWindow::OnActionIDChange) EVT_CHECKBOX(wxID_ANY, PaletteWindow::OnActionIDToggle) END_EVENT_TABLE() PaletteWindow::PaletteWindow(wxWindow* parent, const TilesetContainer& tilesets) : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(230, 250)), choicebook(nullptr), terrain_palette(nullptr), doodad_palette(nullptr), item_palette(nullptr), collection_palette(nullptr), creature_palette(nullptr), house_palette(nullptr), waypoint_palette(nullptr), raw_palette(nullptr), action_id_input(nullptr), action_id_checkbox(nullptr), action_id(0), action_id_enabled(false) { // Allow resizing but maintain minimum size SetMinSize(wxSize(225, 250)); // Create main sizer wxSizer* main_sizer = new wxBoxSizer(wxVERTICAL); // Create action ID controls wxSizer* action_id_sizer = new wxBoxSizer(wxHORIZONTAL); action_id_input = new wxTextCtrl(this, wxID_ANY, "0", wxDefaultPosition, wxSize(60, -1)); action_id_input->SetToolTip("Enter action ID (0-65535)"); action_id_checkbox = new wxCheckBox(this, wxID_ANY, "Enable Action ID"); action_id_checkbox->SetToolTip("When enabled, placed items will have this action ID"); action_id_sizer->Add(action_id_input, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 5); action_id_sizer->Add(action_id_checkbox, 0, wxALIGN_CENTER_VERTICAL); main_sizer->Add(action_id_sizer, 0, wxEXPAND | wxALL, 5); // Create choicebook with EXPAND flag to fill available space choicebook = new wxChoicebook(this, PALETTE_CHOICEBOOK, wxDefaultPosition, wxDefaultSize); terrain_palette = static_cast(CreateTerrainPalette(choicebook, tilesets)); choicebook->AddPage(terrain_palette, terrain_palette->GetName()); doodad_palette = static_cast(CreateDoodadPalette(choicebook, tilesets)); choicebook->AddPage(doodad_palette, doodad_palette->GetName()); collection_palette = static_cast(CreateCollectionPalette(choicebook, tilesets)); choicebook->AddPage(collection_palette, collection_palette->GetName()); item_palette = static_cast(CreateItemPalette(choicebook, tilesets)); choicebook->AddPage(item_palette, item_palette->GetName()); house_palette = static_cast(CreateHousePalette(choicebook, tilesets)); choicebook->AddPage(house_palette, house_palette->GetName()); waypoint_palette = static_cast(CreateWaypointPalette(choicebook, tilesets)); choicebook->AddPage(waypoint_palette, waypoint_palette->GetName()); creature_palette = static_cast(CreateCreaturePalette(choicebook, tilesets)); choicebook->AddPage(creature_palette, creature_palette->GetName()); raw_palette = static_cast(CreateRAWPalette(choicebook, tilesets)); choicebook->AddPage(raw_palette, raw_palette->GetName()); // Add choicebook to main sizer main_sizer->Add(choicebook, 1, wxEXPAND | wxALL, 2); SetSizer(main_sizer); // Load first page LoadCurrentContents(); } PaletteWindow::~PaletteWindow() { // Clean up all brushes and caches in each palette panel if (choicebook) { // Ensure each panel type is properly cleaned up if (terrain_palette) { terrain_palette->DestroyAllCaches(); } if (doodad_palette) { doodad_palette->DestroyAllCaches(); } if (item_palette) { item_palette->DestroyAllCaches(); } if (collection_palette) { collection_palette->DestroyAllCaches(); } if (raw_palette) { raw_palette->DestroyAllCaches(); } // Other palette types may need specific cleanup for (size_t iz = 0; iz < choicebook->GetPageCount(); ++iz) { PalettePanel* panel = dynamic_cast(choicebook->GetPage(iz)); if (panel) { panel->InvalidateContents(); } } } } PalettePanel* PaletteWindow::CreateTerrainPalette(wxWindow* parent, const TilesetContainer& tilesets) { BrushPalettePanel* panel = newd BrushPalettePanel(parent, tilesets, TILESET_TERRAIN); panel->SetListType(wxstr(g_settings.getString(Config::PALETTE_TERRAIN_STYLE))); BrushToolPanel* tool_panel = newd BrushToolPanel(panel); tool_panel->SetToolbarIconSize(g_settings.getBoolean(Config::USE_LARGE_TERRAIN_TOOLBAR)); panel->AddToolPanel(tool_panel); BrushSizePanel* size_panel = newd BrushSizePanel(panel); size_panel->SetToolbarIconSize(g_settings.getBoolean(Config::USE_LARGE_TERRAIN_TOOLBAR)); panel->AddToolPanel(size_panel); ZoneBrushPanel* zone_brush_panel = newd ZoneBrushPanel(panel); zone_brush_panel->SetToolbarIconSize(g_settings.getBoolean(Config::USE_LARGE_TERRAIN_TOOLBAR)); panel->AddToolPanel(zone_brush_panel); return panel; } PalettePanel* PaletteWindow::CreateCollectionPalette(wxWindow* parent, const TilesetContainer& tilesets) { BrushPalettePanel* panel = newd BrushPalettePanel(parent, tilesets, TILESET_COLLECTION); panel->SetListType(wxstr(g_settings.getString(Config::PALETTE_COLLECTION_STYLE))); // terrain palette tools BrushToolPanel* tool_panel = newd BrushToolPanel(panel); tool_panel->SetToolbarIconSize(g_settings.getBoolean(Config::USE_LARGE_COLLECTION_TOOLBAR)); panel->AddToolPanel(tool_panel); // brush thickness panel panel->AddToolPanel(newd BrushThicknessPanel(panel)); // brush size tools BrushSizePanel* size_panel = newd BrushSizePanel(panel); size_panel->SetToolbarIconSize(g_settings.getBoolean(Config::USE_LARGE_COLLECTION_TOOLBAR)); panel->AddToolPanel(size_panel); return panel; } PalettePanel* PaletteWindow::CreateDoodadPalette(wxWindow* parent, const TilesetContainer& tilesets) { BrushPalettePanel* panel = newd BrushPalettePanel(parent, tilesets, TILESET_DOODAD); panel->SetListType(wxstr(g_settings.getString(Config::PALETTE_DOODAD_STYLE))); panel->AddToolPanel(newd BrushThicknessPanel(panel)); BrushSizePanel* size_panel = newd BrushSizePanel(panel); size_panel->SetToolbarIconSize(g_settings.getBoolean(Config::USE_LARGE_DOODAD_SIZEBAR)); panel->AddToolPanel(size_panel); return panel; } PalettePanel* PaletteWindow::CreateItemPalette(wxWindow* parent, const TilesetContainer& tilesets) { BrushPalettePanel* panel = newd BrushPalettePanel(parent, tilesets, TILESET_ITEM); panel->SetListType(wxstr(g_settings.getString(Config::PALETTE_ITEM_STYLE))); BrushSizePanel* size_panel = newd BrushSizePanel(panel); size_panel->SetToolbarIconSize(g_settings.getBoolean(Config::USE_LARGE_ITEM_SIZEBAR)); panel->AddToolPanel(size_panel); return panel; } PalettePanel* PaletteWindow::CreateHousePalette(wxWindow* parent, const TilesetContainer& tilesets) { HousePalettePanel* panel = newd HousePalettePanel(parent); BrushSizePanel* size_panel = newd BrushSizePanel(panel); size_panel->SetToolbarIconSize(g_settings.getBoolean(Config::USE_LARGE_HOUSE_SIZEBAR)); panel->AddToolPanel(size_panel); return panel; } PalettePanel* PaletteWindow::CreateWaypointPalette(wxWindow* parent, const TilesetContainer& tilesets) { WaypointPalettePanel* panel = newd WaypointPalettePanel(parent); return panel; } PalettePanel* PaletteWindow::CreateCreaturePalette(wxWindow* parent, const TilesetContainer& tilesets) { CreaturePalettePanel* panel = newd CreaturePalettePanel(parent); return panel; } PalettePanel* PaletteWindow::CreateRAWPalette(wxWindow* parent, const TilesetContainer& tilesets) { BrushPalettePanel* panel = newd BrushPalettePanel(parent, tilesets, TILESET_RAW); panel->SetListType(wxstr(g_settings.getString(Config::PALETTE_RAW_STYLE))); BrushSizePanel* size_panel = newd BrushSizePanel(panel); size_panel->SetToolbarIconSize(g_settings.getBoolean(Config::USE_LARGE_RAW_SIZEBAR)); panel->AddToolPanel(size_panel); return panel; } void PaletteWindow::ReloadSettings(Map* map) { if (terrain_palette) { terrain_palette->SetListType(wxstr(g_settings.getString(Config::PALETTE_TERRAIN_STYLE))); terrain_palette->SetToolbarIconSize(g_settings.getBoolean(Config::USE_LARGE_TERRAIN_TOOLBAR)); } if (doodad_palette) { doodad_palette->SetListType(wxstr(g_settings.getString(Config::PALETTE_DOODAD_STYLE))); doodad_palette->SetToolbarIconSize(g_settings.getBoolean(Config::USE_LARGE_DOODAD_SIZEBAR)); } if (house_palette) { house_palette->SetMap(map); house_palette->SetToolbarIconSize(g_settings.getBoolean(Config::USE_LARGE_HOUSE_SIZEBAR)); } if (waypoint_palette) { waypoint_palette->SetMap(map); } if (item_palette) { item_palette->SetListType(wxstr(g_settings.getString(Config::PALETTE_ITEM_STYLE))); item_palette->SetToolbarIconSize(g_settings.getBoolean(Config::USE_LARGE_ITEM_SIZEBAR)); } if (collection_palette) { collection_palette->SetListType(wxstr(g_settings.getString(Config::PALETTE_COLLECTION_STYLE))); collection_palette->SetToolbarIconSize(g_settings.getBoolean(Config::USE_LARGE_COLLECTION_TOOLBAR)); } if (raw_palette) { raw_palette->SetListType(wxstr(g_settings.getString(Config::PALETTE_RAW_STYLE))); raw_palette->SetToolbarIconSize(g_settings.getBoolean(Config::USE_LARGE_RAW_SIZEBAR)); } InvalidateContents(); } void PaletteWindow::LoadCurrentContents() { if (!choicebook) { return; } PalettePanel* panel = dynamic_cast(choicebook->GetCurrentPage()); panel->LoadCurrentContents(); Fit(); Refresh(); Update(); } void PaletteWindow::InvalidateContents() { if (!choicebook) { return; } for (size_t iz = 0; iz < choicebook->GetPageCount(); ++iz) { PalettePanel* panel = dynamic_cast(choicebook->GetPage(iz)); panel->InvalidateContents(); } LoadCurrentContents(); if (creature_palette) { creature_palette->OnUpdate(); } if (house_palette) { house_palette->OnUpdate(); } if (waypoint_palette) { waypoint_palette->OnUpdate(); } } void PaletteWindow::SelectPage(PaletteType id) { if (!choicebook) { return; } if (id == GetSelectedPage()) { return; } // First notify the current page that it's being switched out PalettePanel* currentPanel = dynamic_cast(choicebook->GetCurrentPage()); if (currentPanel) { currentPanel->OnSwitchOut(); } // Find and select the new page for (size_t iz = 0; iz < choicebook->GetPageCount(); ++iz) { PalettePanel* panel = dynamic_cast(choicebook->GetPage(iz)); if (panel->GetType() == id) { choicebook->SetSelection(iz); panel->OnSwitchIn(); break; } } } Brush* PaletteWindow::GetSelectedBrush() const { if (!choicebook) { return nullptr; } PalettePanel* panel = dynamic_cast(choicebook->GetCurrentPage()); return panel->GetSelectedBrush(); } int PaletteWindow::GetSelectedBrushSize() const { if (!choicebook) { return 0; } PalettePanel* panel = dynamic_cast(choicebook->GetCurrentPage()); return panel->GetSelectedBrushSize(); } PaletteType PaletteWindow::GetSelectedPage() const { if (!choicebook) { return TILESET_UNKNOWN; } PalettePanel* panel = dynamic_cast(choicebook->GetCurrentPage()); ASSERT(panel); return panel->GetType(); } bool PaletteWindow::OnSelectBrush(const Brush* whatbrush, PaletteType primary) { if (!choicebook || !whatbrush) { return false; } if (whatbrush->isHouse() && house_palette) { house_palette->SelectBrush(whatbrush); SelectPage(TILESET_HOUSE); return true; } switch (primary) { case TILESET_TERRAIN: { // This is already searched first break; } case TILESET_DOODAD: { // Ok, search doodad before terrain if (doodad_palette && doodad_palette->SelectBrush(whatbrush)) { SelectPage(TILESET_DOODAD); return true; } break; } case TILESET_COLLECTION: { if (collection_palette && collection_palette->SelectBrush(whatbrush)) { SelectPage(TILESET_COLLECTION); return true; } } case TILESET_ITEM: { if (item_palette && item_palette->SelectBrush(whatbrush)) { SelectPage(TILESET_ITEM); return true; } break; } case TILESET_CREATURE: { if (creature_palette && creature_palette->SelectBrush(whatbrush)) { SelectPage(TILESET_CREATURE); return true; } break; } case TILESET_RAW: { if (raw_palette && raw_palette->SelectBrush(whatbrush)) { SelectPage(TILESET_RAW); return true; } break; } default: break; } // Test if it's a terrain brush if (terrain_palette && terrain_palette->SelectBrush(whatbrush)) { SelectPage(TILESET_TERRAIN); return true; } // Test if it's a doodad brush if (primary != TILESET_DOODAD) { if (doodad_palette && doodad_palette->SelectBrush(whatbrush)) { SelectPage(TILESET_DOODAD); return true; } } // Test if it's an item brush if (primary != TILESET_ITEM) { if (item_palette && item_palette->SelectBrush(whatbrush)) { SelectPage(TILESET_ITEM); return true; } } // Test if it's a creature brush if (primary != TILESET_CREATURE) { if (creature_palette && creature_palette->SelectBrush(whatbrush)) { SelectPage(TILESET_CREATURE); return true; } } // Test if it's a raw brush if (primary != TILESET_RAW) { if (raw_palette && raw_palette->SelectBrush(whatbrush)) { SelectPage(TILESET_RAW); return true; } } return false; } void PaletteWindow::OnSwitchingPage(wxChoicebookEvent& event) { event.Skip(); if (!choicebook) { return; } wxWindow* old_page = choicebook->GetPage(choicebook->GetSelection()); PalettePanel* old_panel = dynamic_cast(old_page); if (old_panel) { old_panel->OnSwitchOut(); } wxWindow* page = choicebook->GetPage(event.GetSelection()); PalettePanel* panel = dynamic_cast(page); if (panel) { panel->OnSwitchIn(); } } void PaletteWindow::OnPageChanged(wxChoicebookEvent& event) { if (!choicebook) { return; } g_gui.SelectBrush(); } void PaletteWindow::OnUpdateBrushSize(BrushShape shape, int size) { if (!choicebook) { return; } PalettePanel* page = dynamic_cast(choicebook->GetCurrentPage()); ASSERT(page); page->OnUpdateBrushSize(shape, size); } void PaletteWindow::OnUpdate(Map* map) { if (creature_palette) { creature_palette->OnUpdate(); } if (house_palette) { house_palette->SetMap(map); } if (waypoint_palette) { waypoint_palette->SetMap(map); waypoint_palette->OnUpdate(); } } void PaletteWindow::OnKey(wxKeyEvent& event) { if (g_gui.GetCurrentTab() != nullptr) { g_gui.GetCurrentMapTab()->GetEventHandler()->AddPendingEvent(event); } } void PaletteWindow::OnClose(wxCloseEvent& event) { if (!event.CanVeto()) { // We can't do anything! This sucks! // (application is closed, we have to destroy ourselves) Destroy(); } else { Show(false); event.Veto(true); } } void PaletteWindow::OnActionIDChange(wxCommandEvent& event) { wxString value = action_id_input->GetValue(); long val; if (value.ToLong(&val)) { if (val >= 0 && val <= 65535) { action_id = static_cast(val); } else { // Reset to previous valid value action_id_input->SetValue(wxString::Format("%d", action_id)); } } else { // Reset to previous valid value action_id_input->SetValue(wxString::Format("%d", action_id)); } } void PaletteWindow::OnActionIDToggle(wxCommandEvent& event) { action_id_enabled = action_id_checkbox->GetValue(); }