Map Editor

RD Core / Commit #3

Commit Map Editor

Alex Alex committed 18/10/2026 23:40 main Patch
436 files +250,791 -0
A RD_Map_Editor/source/common_windows.h +374-0 View file
@@ -0,0 +1,374 @@
1+//////////////////////////////////////////////////////////////////////
2+// This file is part of Remere's Map Editor
3+//////////////////////////////////////////////////////////////////////
4+// Remere's Map Editor is free software: you can redistribute it and/or modify
5+// it under the terms of the GNU General Public License as published by
6+// the Free Software Foundation, either version 3 of the License, or
7+// (at your option) any later version.
8+//
9+// Remere's Map Editor is distributed in the hope that it will be useful,
10+// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+// GNU General Public License for more details.
13+//
14+// You should have received a copy of the GNU General Public License
15+// along with this program. If not, see <http://www.gnu.org/licenses/>.
16+//////////////////////////////////////////////////////////////////////
17+
18+#ifndef RME_MAP_WINDOWS_H_
19+#define RME_MAP_WINDOWS_H_
20+
21+#include "main.h"
22+
23+#include "dcbutton.h"
24+#include "positionctrl.h"
25+
26+class GameSprite;
27+class MapTab;
28+
29+/**
30+ * A toggle button with an item on it.
31+ */
32+class ItemToggleButton : public DCButton {
33+public:
34+ ItemToggleButton(wxWindow* parent, RenderSize size, int lookid, wxWindowID id = wxID_ANY) :
35+ DCButton(parent, id, wxDefaultPosition, DC_BTN_TOGGLE, size, lookid) { }
36+ virtual ~ItemToggleButton() { }
37+};
38+
39+/**
40+ * A button with an item on it.
41+ */
42+class ItemButton : public DCButton {
43+public:
44+ ItemButton(wxWindow* parent, RenderSize size, uint16_t lookid, wxWindowID id = wxID_ANY) :
45+ DCButton(parent, id, wxDefaultPosition, DC_BTN_NORMAL, size, lookid) { }
46+ virtual ~ItemButton() { }
47+};
48+
49+/**
50+ * The map properties window
51+ * Change map size, protocol etc.
52+ */
53+class MapPropertiesWindow : public wxDialog {
54+public:
55+ MapPropertiesWindow(wxWindow* parent, MapTab* tab, Editor& editor);
56+ virtual ~MapPropertiesWindow();
57+
58+ void OnChangeVersion(wxCommandEvent&);
59+ void OnClientVersionChange(wxCommandEvent&);
60+ void OnClickOK(wxCommandEvent&);
61+ void OnClickCancel(wxCommandEvent&);
62+
63+protected:
64+ void UpdateProtocolList();
65+
66+ MapTab* view;
67+ Editor& editor;
68+ wxSpinCtrl* height_spin;
69+ wxSpinCtrl* width_spin;
70+ wxChoice* version_choice;
71+ wxChoice* protocol_choice;
72+ wxTextCtrl* description_ctrl;
73+ wxTextCtrl* house_filename_ctrl;
74+ wxTextCtrl* spawn_filename_ctrl;
75+ wxCheckBox* auto_update_checkbox;
76+
77+ DECLARE_EVENT_TABLE();
78+};
79+
80+/**
81+ * The import map dialog
82+ * Allows selection of file path, offset and some weird options.
83+ */
84+class ImportMapWindow : public wxDialog {
85+public:
86+ ImportMapWindow(wxWindow* parent, Editor& editor);
87+ virtual ~ImportMapWindow();
88+
89+ void OnClickBrowse(wxCommandEvent&);
90+ void OnClickOK(wxCommandEvent&);
91+ void OnClickCancel(wxCommandEvent&);
92+
93+protected:
94+ Editor& editor;
95+
96+ wxTextCtrl* file_text_field;
97+ wxSpinCtrl* x_offset_ctrl;
98+ wxSpinCtrl* y_offset_ctrl;
99+
100+ wxChoice* house_options;
101+ wxChoice* spawn_options;
102+
103+ DECLARE_EVENT_TABLE();
104+};
105+
106+/**
107+ * The export minimap dialog, select output path and what floors to export.
108+ */
109+class ExportMiniMapWindow : public wxDialog {
110+public:
111+ ExportMiniMapWindow(wxWindow* parent, Editor& editor);
112+ virtual ~ExportMiniMapWindow();
113+
114+ void OnClickBrowse(wxCommandEvent&);
115+ void OnDirectoryChanged(wxKeyEvent&);
116+ void OnFileNameChanged(wxKeyEvent&);
117+ void OnClickOK(wxCommandEvent&);
118+ void OnClickCancel(wxCommandEvent&);
119+ void OnExportTypeChange(wxCommandEvent&);
120+
121+protected:
122+ void CheckValues();
123+
124+ Editor& editor;
125+
126+ wxStaticText* error_field;
127+ wxTextCtrl* directory_text_field;
128+ wxTextCtrl* file_name_text_field;
129+ wxChoice* floor_options;
130+ wxSpinCtrl* floor_number;
131+ wxButton* ok_button;
132+
133+ DECLARE_EVENT_TABLE();
134+};
135+
136+/**
137+ * The export tilesets dialog, select output path.
138+ */
139+class ExportTilesetsWindow : public wxDialog {
140+public:
141+ ExportTilesetsWindow(wxWindow* parent, Editor& editor);
142+ virtual ~ExportTilesetsWindow();
143+
144+ void OnClickBrowse(wxCommandEvent&);
145+ void OnDirectoryChanged(wxKeyEvent&);
146+ void OnFileNameChanged(wxKeyEvent&);
147+ void OnClickOK(wxCommandEvent&);
148+ void OnClickCancel(wxCommandEvent&);
149+
150+protected:
151+ void CheckValues();
152+
153+ Editor& editor;
154+
155+ wxStaticText* error_field;
156+ wxTextCtrl* directory_text_field;
157+ wxTextCtrl* file_name_text_field;
158+ wxButton* ok_button;
159+
160+ DECLARE_EVENT_TABLE();
161+};
162+
163+/**
164+ * Text control that will forward up/down pgup / pgdown keys to parent window
165+ */
166+class KeyForwardingTextCtrl : public wxTextCtrl {
167+public:
168+ KeyForwardingTextCtrl(wxWindow* parent, wxWindowID id, const wxString& value = "", const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxValidator& validator = wxDefaultValidator, const wxString& name = wxTextCtrlNameStr) :
169+ wxTextCtrl(parent, id, value, pos, size, style, validator, name) { }
170+ ~KeyForwardingTextCtrl() { }
171+
172+ void OnKeyDown(wxKeyEvent&);
173+
174+ DECLARE_EVENT_TABLE()
175+};
176+
177+/**
178+ * The list inside a find dialog
179+ * Presents a list of brushes
180+ */
181+class FindDialogListBox : public wxVListBox {
182+public:
183+ FindDialogListBox(wxWindow* parent, wxWindowID id);
184+ ~FindDialogListBox();
185+
186+ void Clear();
187+ void SetNoMatches();
188+ void AddBrush(Brush*);
189+ Brush* GetSelectedBrush();
190+
191+ void OnDrawItem(wxDC& dc, const wxRect& rect, size_t index) const;
192+ wxCoord OnMeasureItem(size_t index) const;
193+
194+protected:
195+ bool cleared;
196+ bool no_matches;
197+ std::vector<Brush*> brushlist;
198+};
199+
200+/**
201+ * A wxListBox that can be sorted without using style wxLB_SORT.
202+ * wxLB_SORT does not work properly on Windows and causes errors on macOS.
203+ */
204+class SortableListBox : public wxListBox {
205+public:
206+ SortableListBox(wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize);
207+ SortableListBox(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, int n, const wxString choices[], long style);
208+ ~SortableListBox();
209+ void Sort();
210+
211+private:
212+ void DoSort();
213+};
214+
215+/**
216+ * A generic find dialog
217+ * ShowModal will return 0 or the item id for item dialogs
218+ * 0 or 1 for brush dialogs
219+ */
220+class FindDialog : public wxDialog {
221+public:
222+ FindDialog(wxWindow* parent, wxString title);
223+ virtual ~FindDialog();
224+
225+ void OnKeyDown(wxKeyEvent&);
226+ void OnTextChange(wxCommandEvent&);
227+ void OnTextIdle(wxTimerEvent&);
228+ void OnClickList(wxCommandEvent&);
229+ void OnClickOK(wxCommandEvent&);
230+ void OnClickCancel(wxCommandEvent&);
231+
232+ void RefreshContents();
233+ virtual const Brush* getResult() const {
234+ return result_brush;
235+ }
236+ virtual int getResultID() const {
237+ return result_id;
238+ }
239+
240+protected:
241+ virtual void RefreshContentsInternal() = 0;
242+ virtual void OnClickListInternal(wxCommandEvent&) = 0;
243+ virtual void OnClickOKInternal() = 0;
244+
245+ FindDialogListBox* item_list;
246+ KeyForwardingTextCtrl* search_field;
247+ wxTimer idle_input_timer;
248+ const Brush* result_brush;
249+ int result_id;
250+
251+ DECLARE_EVENT_TABLE()
252+};
253+
254+/**
255+ * Find a brush dialog
256+ * Find out what brush was returned through GetResult
257+ */
258+class FindBrushDialog : public FindDialog {
259+public:
260+ FindBrushDialog(wxWindow* parent, wxString title = "Jump to Brush");
261+ virtual ~FindBrushDialog();
262+
263+ virtual void RefreshContentsInternal();
264+ virtual void OnClickListInternal(wxCommandEvent&);
265+ virtual void OnClickOKInternal();
266+};
267+
268+/**
269+ * Go to position dialog
270+ * Allows entry of 3 coordinates and goes there instantly
271+ */
272+class GotoPositionDialog : public wxDialog {
273+public:
274+ GotoPositionDialog(wxWindow* parent, Editor& editor);
275+ ~GotoPositionDialog() { }
276+
277+ void OnClickOK(wxCommandEvent&);
278+ void OnClickCancel(wxCommandEvent&);
279+
280+protected:
281+ Editor& editor;
282+ PositionCtrl* posctrl;
283+ wxTextCtrl* position_field;
284+
285+ DECLARE_EVENT_TABLE();
286+};
287+
288+/**
289+ * Base for the item properties dialogs
290+ * There are two versions, one for otbmv4 maps and one for the old maps.
291+ * They are declared in old_properties_window / properties_window
292+ */
293+class ObjectPropertiesWindowBase : public wxDialog {
294+public:
295+ ObjectPropertiesWindowBase(
296+ wxWindow* parent, wxString title,
297+ const Map* map, const Tile* tile, Item* item,
298+ wxPoint position = wxDefaultPosition
299+ );
300+ ObjectPropertiesWindowBase(
301+ wxWindow* parent, wxString title,
302+ const Map* map, const Tile* tile, Spawn* spawn,
303+ wxPoint position = wxDefaultPosition
304+ );
305+ ObjectPropertiesWindowBase(
306+ wxWindow* parent, wxString title,
307+ const Map* map, const Tile* tile, Creature* creature,
308+ wxPoint position = wxDefaultPosition
309+ );
310+ ObjectPropertiesWindowBase(
311+ wxWindow* parent, wxString title, wxPoint position = wxDefaultPosition
312+ );
313+
314+ Item* getItemBeingEdited();
315+ Creature* getCreatureBeingEdited();
316+ Spawn* getSpawnBeingEdited();
317+
318+protected:
319+ const Map* edit_map;
320+ const Tile* edit_tile;
321+ Item* edit_item;
322+ Creature* edit_creature;
323+ Spawn* edit_spawn;
324+};
325+
326+/**
327+ * The edit towns dialog, ugly as sin.
328+ */
329+class EditTownsDialog : public wxDialog {
330+public:
331+ EditTownsDialog(wxWindow* parent, Editor& editor);
332+ virtual ~EditTownsDialog();
333+
334+ void OnListBoxChange(wxCommandEvent&);
335+ void OnClickSelectTemplePosition(wxCommandEvent&);
336+ void OnClickAdd(wxCommandEvent&);
337+ void OnClickRemove(wxCommandEvent&);
338+ void OnClickOK(wxCommandEvent&);
339+ void OnClickCancel(wxCommandEvent&);
340+ void OnPasteTempleText(wxCommandEvent&);
341+ void OnClickImport(wxCommandEvent&);
342+ void OnClickExport(wxCommandEvent&);
343+
344+protected:
345+ void BuildListBox(bool doselect);
346+ void UpdateSelection(int new_selection);
347+ void ExportTownsToXML(const wxString& path);
348+ void ImportTownsFromXML(const wxString& path);
349+ void ExportTownToXML(const wxString& path, Town* town);
350+ void ImportTownFromXML(const wxString& path);
351+
352+ Editor& editor;
353+
354+ std::vector<Town*> town_list;
355+ uint32_t max_town_id;
356+
357+ wxListBox* town_listbox;
358+ wxString town_name, town_id;
359+
360+ wxTextCtrl* name_field;
361+ wxTextCtrl* id_field;
362+
363+ PositionCtrl* temple_position;
364+ wxButton* remove_button;
365+ wxButton* select_position_button;
366+
367+ wxTextCtrl* paste_temple_field;
368+
369+ DECLARE_EVENT_TABLE();
370+};
371+
372+
373+
374+#endif
A RD_Map_Editor/source/complexitem.cpp +115-0 View file
@@ -0,0 +1,115 @@
1+//////////////////////////////////////////////////////////////////////
2+// This file is part of Remere's Map Editor
3+//////////////////////////////////////////////////////////////////////
4+// Remere's Map Editor is free software: you can redistribute it and/or modify
5+// it under the terms of the GNU General Public License as published by
6+// the Free Software Foundation, either version 3 of the License, or
7+// (at your option) any later version.
8+//
9+// Remere's Map Editor is distributed in the hope that it will be useful,
10+// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+// GNU General Public License for more details.
13+//
14+// You should have received a copy of the GNU General Public License
15+// along with this program. If not, see <http://www.gnu.org/licenses/>.
16+//////////////////////////////////////////////////////////////////////
17+
18+#include "main.h"
19+
20+#include "complexitem.h"
21+
22+#include "iomap.h"
23+
24+// Container
25+Container::Container(const uint16_t type) :
26+ Item(type, 0) {
27+ ////
28+}
29+
30+Container::~Container() {
31+ for (Item* item : contents) {
32+ delete item;
33+ }
34+}
35+
36+Item* Container::deepCopy() const {
37+ Item* copy = Item::deepCopy();
38+ Container* copyContainer = dynamic_cast<Container*>(copy);
39+ if (copyContainer) {
40+ for (Item* item : contents) {
41+ copyContainer->contents.push_back(item->deepCopy());
42+ }
43+ }
44+ return copy;
45+}
46+
47+Item* Container::getItem(size_t index) const {
48+ if (index < contents.size()) {
49+ return contents[index];
50+ }
51+ return nullptr;
52+}
53+
54+double Container::getWeight() {
55+ return g_items[id].weight;
56+}
57+
58+// Teleport
59+Teleport::Teleport(const uint16_t type) :
60+ Item(type, 0),
61+ destination(0, 0, 0) {
62+ ////
63+}
64+
65+Item* Teleport::deepCopy() const {
66+ Teleport* copy = static_cast<Teleport*>(Item::deepCopy());
67+ copy->destination = destination;
68+ return copy;
69+}
70+
71+// Door
72+Door::Door(const uint16_t type) :
73+ Item(type, 0),
74+ doorId(0) {
75+ ////
76+}
77+
78+Item* Door::deepCopy() const {
79+ Door* copy = static_cast<Door*>(Item::deepCopy());
80+ copy->doorId = doorId;
81+ return copy;
82+}
83+
84+// Depot
85+Depot::Depot(const uint16_t type) :
86+ Item(type, 0),
87+ depotId(0) {
88+ ////
89+}
90+
91+Item* Depot::deepCopy() const {
92+ Item* copy = Item::deepCopy();
93+ Depot* copy_depot = dynamic_cast<Depot*>(copy);
94+ if (copy_depot) {
95+ copy_depot->depotId = depotId;
96+ }
97+ return copy;
98+}
99+
100+// Podium
101+Podium::Podium(const uint16_t type) :
102+ Item(type, 0),
103+ outfit(Outfit()), showOutfit(true), showMount(true), showPlatform(true), direction(0) {
104+ ////
105+}
106+
107+Item* Podium::deepCopy() const {
108+ Podium* copy = static_cast<Podium*>(Item::deepCopy());
109+ copy->outfit = outfit;
110+ copy->showOutfit = showOutfit;
111+ copy->showMount = showMount;
112+ copy->showPlatform = showPlatform;
113+ copy->direction = direction;
114+ return copy;
115+}
A RD_Map_Editor/source/complexitem.h +196-0 View file
@@ -0,0 +1,196 @@
1+//////////////////////////////////////////////////////////////////////
2+// This file is part of Remere's Map Editor
3+//////////////////////////////////////////////////////////////////////
4+// Remere's Map Editor is free software: you can redistribute it and/or modify
5+// it under the terms of the GNU General Public License as published by
6+// the Free Software Foundation, either version 3 of the License, or
7+// (at your option) any later version.
8+//
9+// Remere's Map Editor is distributed in the hope that it will be useful,
10+// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+// GNU General Public License for more details.
13+//
14+// You should have received a copy of the GNU General Public License
15+// along with this program. If not, see <http://www.gnu.org/licenses/>.
16+//////////////////////////////////////////////////////////////////////
17+
18+#ifndef RME_CONTAINER_H_
19+#define RME_CONTAINER_H_
20+
21+#include "position.h"
22+#include "item.h"
23+#include "outfit.h"
24+
25+#pragma pack(1)
26+
27+struct OTBM_TeleportDestination {
28+ uint16_t x;
29+ uint16_t y;
30+ uint8_t z;
31+};
32+
33+#pragma pack()
34+
35+class Container : public Item {
36+public:
37+ Container(const uint16_t type);
38+ ~Container();
39+
40+ Item* deepCopy() const;
41+ Item* getItem(size_t index) const;
42+
43+ size_t getItemCount() const {
44+ return contents.size();
45+ }
46+ size_t getVolume() const {
47+ return g_items[id].volume;
48+ }
49+
50+ ItemVector& getVector() {
51+ return contents;
52+ }
53+ double getWeight();
54+
55+ virtual bool unserializeItemNode_OTBM(const IOMap& maphandle, BinaryNode* node);
56+ virtual bool serializeItemNode_OTBM(const IOMap& maphandle, NodeFileWriteHandle& f) const;
57+ // virtual bool unserializeItemNode_OTMM(const IOMap& maphandle, BinaryNode* node);
58+ // virtual bool serializeItemNode_OTMM(const IOMap& maphandle, NodeFileWriteHandle& f) const;
59+
60+protected:
61+ ItemVector contents;
62+};
63+
64+class Teleport : public Item {
65+public:
66+ Teleport(const uint16_t type);
67+
68+ Item* deepCopy() const;
69+
70+ virtual void serializeItemAttributes_OTBM(const IOMap& maphandle, NodeFileWriteHandle& f) const;
71+ virtual bool readItemAttribute_OTBM(const IOMap& maphandle, OTBM_ItemAttribute attr, BinaryNode* node);
72+ // virtual void serializeItemAttributes_OTMM(const IOMap& maphandle, NodeFileWriteHandle& f) const;
73+ // virtual bool readItemAttribute_OTMM(const IOMap& maphandle, OTMM_ItemAttribute attr, BinaryNode* node);
74+
75+ int32_t getX() const {
76+ return destination.x;
77+ }
78+ int32_t getY() const {
79+ return destination.y;
80+ }
81+ int32_t getZ() const {
82+ return destination.z;
83+ }
84+
85+ Position getDestination() const {
86+ return destination;
87+ }
88+ void setDestination(const Position& position) {
89+ destination = position;
90+ }
91+
92+ bool hasDestination() const {
93+ return destination != Position();
94+ }
95+
96+protected:
97+ // We could've made this public and skip the functions, but that would
98+ // make the handling of aid/uid/text different from handling teleports,
99+ // which would be weird.
100+ Position destination;
101+};
102+
103+class Door : public Item {
104+public:
105+ Door(const uint16_t type);
106+
107+ Item* deepCopy() const;
108+
109+ uint8_t getDoorID() const;
110+ void setDoorID(uint8_t id);
111+
112+ virtual void serializeItemAttributes_OTBM(const IOMap& maphandle, NodeFileWriteHandle& f) const;
113+ virtual bool readItemAttribute_OTBM(const IOMap& maphandle, OTBM_ItemAttribute attr, BinaryNode* node);
114+ // virtual void serializeItemAttributes_OTMM(const IOMap& maphandle, NodeFileWriteHandle& f) const;
115+ // virtual bool readItemAttribute_OTMM(const IOMap& maphandle, OTMM_ItemAttribute attr, BinaryNode* node);
116+
117+ DoorType getDoorType() const;
118+ bool isRealDoor() const;
119+
120+protected:
121+ uint8_t doorId;
122+};
123+
124+class Depot : public Item {
125+public:
126+ Depot(const uint16_t _type);
127+
128+ Item* deepCopy() const;
129+
130+ uint8_t getDepotID() const {
131+ return depotId;
132+ }
133+ void setDepotID(uint8_t id) {
134+ depotId = id;
135+ }
136+
137+ virtual void serializeItemAttributes_OTBM(const IOMap& maphandle, NodeFileWriteHandle& f) const;
138+ virtual bool readItemAttribute_OTBM(const IOMap& maphandle, OTBM_ItemAttribute attr, BinaryNode* node);
139+ // virtual void serializeItemAttributes_OTMM(const IOMap& maphandle, NodeFileWriteHandle& f) const;
140+ // virtual bool readItemAttribute_OTMM(const IOMap& maphandle, OTMM_ItemAttribute attr, BinaryNode* node);
141+
142+protected:
143+ uint8_t depotId;
144+};
145+
146+class Podium : public Item {
147+public:
148+ Podium(const uint16_t _type);
149+
150+ Item* deepCopy() const;
151+
152+ const Outfit& getOutfit() const {
153+ return outfit;
154+ }
155+ void setOutfit(Outfit& newOutfit) {
156+ outfit = newOutfit;
157+ }
158+
159+ const uint8_t getDirection() {
160+ return direction;
161+ }
162+ void setDirection(uint8_t newDirection) {
163+ direction = newDirection;
164+ }
165+
166+ bool hasShowOutfit() {
167+ return showOutfit && outfit.lookType != 0;
168+ }
169+ bool hasShowMount() {
170+ return showMount && outfit.lookMount != 0;
171+ }
172+ bool hasShowPlatform() {
173+ return showPlatform;
174+ }
175+
176+ void setShowOutfit(bool newState) {
177+ showOutfit = newState;
178+ }
179+ void setShowMount(bool newState) {
180+ showMount = newState;
181+ }
182+ void setShowPlatform(bool newState) {
183+ showPlatform = newState;
184+ }
185+
186+ virtual void serializeItemAttributes_OTBM(const IOMap& maphandle, NodeFileWriteHandle& f) const;
187+ virtual bool readItemAttribute_OTBM(const IOMap& maphandle, OTBM_ItemAttribute attr, BinaryNode* node);
188+
189+protected:
190+ Outfit outfit;
191+ uint8_t direction;
192+ bool showOutfit = true;
193+ bool showMount = true;
194+ bool showPlatform = true;
195+};
196+#endif
A RD_Map_Editor/source/container_properties_window.cpp +216-0 View file
@@ -0,0 +1,216 @@
1+//////////////////////////////////////////////////////////////////////
2+// This file is part of Remere's Map Editor
3+//////////////////////////////////////////////////////////////////////
4+// Remere's Map Editor is free software: you can redistribute it and/or modify
5+// it under the terms of the GNU General Public License as published by
6+// the Free Software Foundation, either version 3 of the License, or
7+// (at your option) any later version.
8+//
9+// Remere's Map Editor is distributed in the hope that it will be useful,
10+// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+// GNU General Public License for more details.
13+//
14+// You should have received a copy of the GNU General Public License
15+// along with this program. If not, see <http://www.gnu.org/licenses/>.
16+//////////////////////////////////////////////////////////////////////
17+
18+#include "main.h"
19+
20+#include "container_properties_window.h"
21+
22+#include "old_properties_window.h"
23+#include "properties_window.h"
24+#include "find_item_window.h"
25+#include "gui.h"
26+#include "complexitem.h"
27+#include "map.h"
28+
29+// ============================================================================
30+// Container Item Button
31+// Displayed in the container object properties menu, needs some
32+// custom event handling for the right-click menu etcetera so we
33+// need to define a custom class for it.
34+
35+std::unique_ptr<ContainerItemPopupMenu> ContainerItemButton::popup_menu;
36+
37+BEGIN_EVENT_TABLE(ContainerItemButton, ItemButton)
38+EVT_LEFT_DOWN(ContainerItemButton::OnMouseDoubleLeftClick)
39+EVT_RIGHT_UP(ContainerItemButton::OnMouseRightRelease)
40+
41+EVT_MENU(CONTAINER_POPUP_MENU_ADD, ContainerItemButton::OnAddItem)
42+EVT_MENU(CONTAINER_POPUP_MENU_EDIT, ContainerItemButton::OnEditItem)
43+EVT_MENU(CONTAINER_POPUP_MENU_REMOVE, ContainerItemButton::OnRemoveItem)
44+END_EVENT_TABLE()
45+
46+ContainerItemButton::ContainerItemButton(wxWindow* parent, bool large, int _index, const Map* map, Item* item) :
47+ ItemButton(parent, (large ? RENDER_SIZE_32x32 : RENDER_SIZE_16x16), (item ? item->getClientID() : 0)),
48+ edit_map(map),
49+ edit_item(item),
50+ index(_index) {
51+ ////
52+}
53+
54+ContainerItemButton::~ContainerItemButton() {
55+ ////
56+}
57+
58+void ContainerItemButton::OnMouseDoubleLeftClick(wxMouseEvent& WXUNUSED(event)) {
59+ wxCommandEvent dummy;
60+
61+ if (edit_item) {
62+ OnEditItem(dummy);
63+ return;
64+ }
65+
66+ Container* container = getParentContainer();
67+ if (container->getVolume() > container->getItemCount()) {
68+ OnAddItem(dummy);
69+ }
70+}
71+
72+void ContainerItemButton::OnMouseRightRelease(wxMouseEvent& WXUNUSED(event)) {
73+ if (!popup_menu) {
74+ popup_menu.reset(newd ContainerItemPopupMenu);
75+ }
76+
77+ popup_menu->Update(this);
78+ PopupMenu(popup_menu.get());
79+}
80+
81+void ContainerItemButton::OnAddItem(wxCommandEvent& WXUNUSED(event)) {
82+ FindItemDialog dialog(GetParent(), "Choose Item to add", true);
83+
84+ if (dialog.ShowModal() == wxID_OK) {
85+ Container* container = getParentContainer();
86+ ItemVector& itemVector = container->getVector();
87+
88+ Item* item = Item::Create(dialog.getResultID());
89+ if (index < itemVector.size()) {
90+ itemVector.insert(itemVector.begin() + index, item);
91+ } else {
92+ itemVector.push_back(item);
93+ }
94+
95+ ObjectPropertiesWindowBase* propertyWindow = getParentContainerWindow();
96+ if (propertyWindow) {
97+ propertyWindow->Update();
98+ }
99+ }
100+ dialog.Destroy();
101+}
102+
103+void ContainerItemButton::OnEditItem(wxCommandEvent& WXUNUSED(event)) {
104+ ASSERT(edit_item);
105+
106+ wxPoint newDialogAt;
107+ wxWindow* w = this;
108+ while ((w = w->GetParent())) {
109+ if (ObjectPropertiesWindowBase* o = dynamic_cast<ObjectPropertiesWindowBase*>(w)) {
110+ newDialogAt = o->GetPosition();
111+ break;
112+ }
113+ }
114+
115+ newDialogAt += wxPoint(20, 20);
116+
117+ wxDialog* d;
118+
119+ if (edit_map->getVersion().otbm >= MAP_OTBM_4) {
120+ d = newd PropertiesWindow(this, edit_map, nullptr, edit_item, newDialogAt);
121+ } else {
122+ d = newd OldPropertiesWindow(this, edit_map, nullptr, edit_item, newDialogAt);
123+ }
124+
125+ d->ShowModal();
126+ d->Destroy();
127+}
128+
129+void ContainerItemButton::OnRemoveItem(wxCommandEvent& WXUNUSED(event)) {
130+ ASSERT(edit_item);
131+ int32_t ret = g_gui.PopupDialog(GetParent(), "Remove Item", "Are you sure you want to remove this item from the container?", wxYES | wxNO);
132+
133+ if (ret != wxID_YES) {
134+ return;
135+ }
136+
137+ Container* container = getParentContainer();
138+ ItemVector& itemVector = container->getVector();
139+
140+ auto it = itemVector.begin();
141+ for (; it != itemVector.end(); ++it) {
142+ if (*it == edit_item) {
143+ break;
144+ }
145+ }
146+
147+ ASSERT(it != itemVector.end());
148+
149+ itemVector.erase(it);
150+ delete edit_item;
151+
152+ ObjectPropertiesWindowBase* propertyWindow = getParentContainerWindow();
153+ if (propertyWindow) {
154+ propertyWindow->Update();
155+ }
156+}
157+
158+void ContainerItemButton::setItem(Item* item) {
159+ edit_item = item;
160+ if (edit_item) {
161+ SetSprite(edit_item->getClientID());
162+ } else {
163+ SetSprite(0);
164+ }
165+}
166+
167+ObjectPropertiesWindowBase* ContainerItemButton::getParentContainerWindow() {
168+ for (wxWindow* window = GetParent(); window != nullptr; window = window->GetParent()) {
169+ ObjectPropertiesWindowBase* propertyWindow = dynamic_cast<ObjectPropertiesWindowBase*>(window);
170+ if (propertyWindow) {
171+ return propertyWindow;
172+ }
173+ }
174+ return nullptr;
175+}
176+
177+Container* ContainerItemButton::getParentContainer() {
178+ ObjectPropertiesWindowBase* propertyWindow = getParentContainerWindow();
179+ if (propertyWindow) {
180+ return dynamic_cast<Container*>(propertyWindow->getItemBeingEdited());
181+ }
182+ return nullptr;
183+}
184+
185+// ContainerItemPopupMenu
186+ContainerItemPopupMenu::ContainerItemPopupMenu() :
187+ wxMenu("") {
188+ ////
189+}
190+
191+ContainerItemPopupMenu::~ContainerItemPopupMenu() {
192+ ////
193+}
194+
195+void ContainerItemPopupMenu::Update(ContainerItemButton* btn) {
196+ // Clear the menu of all items
197+ while (GetMenuItemCount() != 0) {
198+ wxMenuItem* m_item = FindItemByPosition(0);
199+ // If you add a submenu, this won't delete it.
200+ Delete(m_item);
201+ }
202+
203+ wxMenuItem* addItem = nullptr;
204+ if (btn->edit_item) {
205+ Append(CONTAINER_POPUP_MENU_EDIT, "&Edit Item", "Open the properties menu for this item");
206+ addItem = Append(CONTAINER_POPUP_MENU_ADD, "&Add Item", "Add a newd item to the container");
207+ Append(CONTAINER_POPUP_MENU_REMOVE, "&Remove Item", "Remove this item from the container");
208+ } else {
209+ addItem = Append(CONTAINER_POPUP_MENU_ADD, "&Add Item", "Add a newd item to the container");
210+ }
211+
212+ Container* parentContainer = btn->getParentContainer();
213+ if (parentContainer->getVolume() <= (int)parentContainer->getVector().size()) {
214+ addItem->Enable(false);
215+ }
216+}
A RD_Map_Editor/source/container_properties_window.h +65-0 View file
@@ -0,0 +1,65 @@
1+//////////////////////////////////////////////////////////////////////
2+// This file is part of Remere's Map Editor
3+//////////////////////////////////////////////////////////////////////
4+// Remere's Map Editor is free software: you can redistribute it and/or modify
5+// it under the terms of the GNU General Public License as published by
6+// the Free Software Foundation, either version 3 of the License, or
7+// (at your option) any later version.
8+//
9+// Remere's Map Editor is distributed in the hope that it will be useful,
10+// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+// GNU General Public License for more details.
13+//
14+// You should have received a copy of the GNU General Public License
15+// along with this program. If not, see <http://www.gnu.org/licenses/>.
16+//////////////////////////////////////////////////////////////////////
17+
18+#ifndef _RME_CONTAINER_PROPS_H_
19+#define _RME_CONTAINER_PROPS_H_
20+
21+#include "common_windows.h"
22+
23+class Container;
24+class ContainerItemButton;
25+
26+// Right-click popup menu
27+class ContainerItemPopupMenu : public wxMenu {
28+public:
29+ ContainerItemPopupMenu();
30+ virtual ~ContainerItemPopupMenu();
31+
32+ void Update(ContainerItemButton* what);
33+};
34+
35+// Container Item Button
36+class ContainerItemButton : public ItemButton {
37+ DECLARE_EVENT_TABLE()
38+public:
39+ ContainerItemButton(wxWindow* parent, bool large, int index, const Map* map, Item* item);
40+ ~ContainerItemButton();
41+
42+ void OnMouseDoubleLeftClick(wxMouseEvent& event);
43+ void OnMouseRightRelease(wxMouseEvent& event);
44+
45+ void OnAddItem(wxCommandEvent& event);
46+ void OnEditItem(wxCommandEvent& event);
47+ void OnRemoveItem(wxCommandEvent& event);
48+
49+ ObjectPropertiesWindowBase* getParentContainerWindow();
50+ Container* getParentContainer();
51+
52+ void setItem(Item* item);
53+
54+private:
55+ static std::unique_ptr<ContainerItemPopupMenu> popup_menu;
56+
57+ const Map* edit_map;
58+ Item* edit_item;
59+
60+ size_t index;
61+
62+ friend class ContainerItemPopupMenu;
63+};
64+
65+#endif
Top