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/wall_brush.h +112-0 View file
@@ -0,0 +1,112 @@
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_WALL_BRUSH_H
19+#define RME_WALL_BRUSH_H
20+
21+#include "brush.h"
22+
23+//=============================================================================
24+// Wallbrush, for drawing walls
25+
26+class WallBrush : public TerrainBrush {
27+public:
28+ static void init();
29+
30+ WallBrush();
31+ virtual ~WallBrush();
32+
33+ bool isWall() const {
34+ return true;
35+ }
36+ WallBrush* asWall() {
37+ return static_cast<WallBrush*>(this);
38+ }
39+
40+ virtual bool load(pugi::xml_node node, wxArrayString& warnings);
41+
42+ virtual bool canDraw(BaseMap* map, const Position& position) const {
43+ return true;
44+ }
45+
46+ // Draw to the target tile
47+ // Note that this actually only puts the first WALL_NORMAL item on the tile.
48+ // It's up to the doWalls function to change it to the correct alignment
49+ virtual void draw(BaseMap* map, Tile* tile, void* parameter);
50+ virtual void undraw(BaseMap* map, Tile* tile);
51+ // Creates walls on the target tile (does not depend on brush in any way)
52+ static void doWalls(BaseMap* map, Tile* tile);
53+
54+ // If the specified wall item is part of this wall
55+ bool hasWall(Item* item);
56+ ::DoorType getDoorTypeFromID(uint16_t id);
57+
58+ virtual bool canSmear() const {
59+ return false;
60+ }
61+ virtual bool canDrag() const {
62+ return true;
63+ }
64+
65+ static uint32_t full_border_types[16];
66+ static uint32_t half_border_types[16];
67+
68+protected:
69+ struct WallType {
70+ int chance;
71+ uint16_t id;
72+ };
73+ struct WallNode {
74+ WallNode() :
75+ total_chance(0) { }
76+ int total_chance;
77+ std::vector<WallType> items;
78+ };
79+ struct DoorType {
80+ ::DoorType type;
81+ uint16_t id;
82+ bool locked;
83+ };
84+ WallNode wall_items[17];
85+ std::vector<DoorType> door_items[17];
86+
87+ WallBrush* redirect_to;
88+
89+ friend class DoorBrush;
90+};
91+
92+//=============================================================================
93+// Wall decoration brush, for drawing decoration on walls
94+
95+class WallDecorationBrush : public WallBrush {
96+public:
97+ WallDecorationBrush();
98+ virtual ~WallDecorationBrush();
99+
100+ bool isWallDecoration() const {
101+ return true;
102+ }
103+ WallDecorationBrush* asWallDecoration() {
104+ return static_cast<WallDecorationBrush*>(this);
105+ }
106+
107+ // We use the exact same loading algorithm as normal walls
108+
109+ virtual void draw(BaseMap* map, Tile* tile, void* parameter);
110+};
111+
112+#endif
A RD_Map_Editor/source/waypoints.cpp +66-0 View file
@@ -0,0 +1,66 @@
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 "waypoints.h"
21+#include "map.h"
22+
23+void Waypoints::addWaypoint(Waypoint* wp) {
24+ removeWaypoint(wp->name);
25+ if (wp->pos != Position()) {
26+ Tile* t = map.getTile(wp->pos);
27+ if (!t) {
28+ map.setTile(wp->pos, t = map.allocator(map.createTileL(wp->pos)));
29+ }
30+ t->getLocation()->increaseWaypointCount();
31+ }
32+ waypoints.insert(std::make_pair(as_lower_str(wp->name), wp));
33+}
34+
35+Waypoint* Waypoints::getWaypoint(std::string name) {
36+ to_lower_str(name);
37+ WaypointMap::iterator iter = waypoints.find(name);
38+ if (iter == waypoints.end()) {
39+ return nullptr;
40+ }
41+ return iter->second;
42+}
43+
44+Waypoint* Waypoints::getWaypoint(TileLocation* location) {
45+ if (!location) {
46+ return nullptr;
47+ }
48+ // TODO find waypoint by position hash.
49+ for (WaypointMap::iterator it = waypoints.begin(); it != waypoints.end(); it++) {
50+ Waypoint* waypoint = it->second;
51+ if (waypoint && waypoint->pos == location->position) {
52+ return waypoint;
53+ }
54+ }
55+ return nullptr;
56+}
57+
58+void Waypoints::removeWaypoint(std::string name) {
59+ to_lower_str(name);
60+ WaypointMap::iterator iter = waypoints.find(name);
61+ if (iter == waypoints.end()) {
62+ return;
63+ }
64+ delete iter->second;
65+ waypoints.erase(iter);
66+}
A RD_Map_Editor/source/waypoints.h +64-0 View file
@@ -0,0 +1,64 @@
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_WAYPOINTS_H_
19+#define RME_WAYPOINTS_H_
20+
21+#include "position.h"
22+
23+class Waypoint {
24+public:
25+ std::string name;
26+ Position pos;
27+};
28+
29+typedef std::map<std::string, Waypoint*> WaypointMap;
30+
31+class Waypoints {
32+ Map& map;
33+
34+public:
35+ Waypoints(Map& map) :
36+ map(map) { }
37+ ~Waypoints() {
38+ for (WaypointMap::iterator iter = waypoints.begin(); iter != waypoints.end(); ++iter) {
39+ delete iter->second;
40+ }
41+ }
42+
43+ void addWaypoint(Waypoint* wp);
44+ Waypoint* getWaypoint(std::string name);
45+ Waypoint* getWaypoint(TileLocation* location);
46+ void removeWaypoint(std::string name);
47+
48+ WaypointMap waypoints;
49+
50+ WaypointMap::iterator begin() {
51+ return waypoints.begin();
52+ }
53+ WaypointMap::const_iterator begin() const {
54+ return waypoints.begin();
55+ }
56+ WaypointMap::iterator end() {
57+ return waypoints.end();
58+ }
59+ WaypointMap::const_iterator end() const {
60+ return waypoints.end();
61+ }
62+};
63+
64+#endif
A RD_Map_Editor/source/waypoint_brush.cpp +60-0 View file
@@ -0,0 +1,60 @@
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 "waypoint_brush.h"
21+#include "waypoints.h"
22+#include "basemap.h"
23+
24+//=============================================================================
25+// Waypoint Brush
26+
27+WaypointBrush::WaypointBrush() :
28+ Brush() {
29+ ////
30+}
31+
32+WaypointBrush::~WaypointBrush() {
33+ ////
34+}
35+
36+void WaypointBrush::setWaypoint(Waypoint* wp) {
37+ if (wp) {
38+ waypoint_name = wp->name;
39+ } else {
40+ waypoint_name = "";
41+ }
42+}
43+
44+std::string WaypointBrush::getWaypoint() const {
45+ return waypoint_name;
46+}
47+
48+bool WaypointBrush::canDraw(BaseMap* map, const Position& position) const {
49+ return map->getTile(position) != nullptr;
50+}
51+
52+void WaypointBrush::undraw(BaseMap* map, Tile* tile) {
53+ // Never called
54+ ASSERT(false);
55+}
56+
57+void WaypointBrush::draw(BaseMap* map, Tile* tile, void* parameter) {
58+ // Never called
59+ ASSERT(false);
60+}
A RD_Map_Editor/source/waypoint_brush.h +73-0 View file
@@ -0,0 +1,73 @@
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_WAYPOINT_BRUSH_H
19+#define RME_WAYPOINT_BRUSH_H
20+
21+#include "brush.h"
22+
23+//=============================================================================
24+// WaypointBrush, draws waypoints simply
25+// This doesn't actually draw anything, and the draw/undraw functions will ASSERT if
26+// you try to call them, so I strongly advice against it
27+
28+class WaypointBrush : public Brush {
29+public:
30+ WaypointBrush();
31+ virtual ~WaypointBrush();
32+
33+ bool isWaypoint() const {
34+ return true;
35+ }
36+ WaypointBrush* asWaypoint() {
37+ return static_cast<WaypointBrush*>(this);
38+ }
39+
40+ // Not used
41+ virtual bool load(pugi::xml_node node, wxArrayString& warnings) {
42+ return true;
43+ }
44+
45+ virtual bool canDraw(BaseMap* map, const Position& position) const;
46+ // Will ASSERT
47+ virtual void draw(BaseMap* map, Tile* tile, void* parameter);
48+ virtual void undraw(BaseMap* map, Tile* tile);
49+
50+ virtual bool canDrag() const {
51+ return false;
52+ }
53+ virtual bool canSmear() const {
54+ return false;
55+ }
56+ virtual bool oneSizeFitsAll() const {
57+ return true;
58+ }
59+
60+ std::string getWaypoint() const;
61+ void setWaypoint(Waypoint* wp);
62+ virtual int getLookID() const {
63+ return 0;
64+ } // We don't have a graphic
65+ virtual std::string getName() const {
66+ return "Waypoint Brush";
67+ }
68+
69+protected:
70+ std::string waypoint_name;
71+};
72+
73+#endif
A RD_Map_Editor/source/welcome_dialog.cpp +294-0 View file
@@ -0,0 +1,294 @@
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+#include "welcome_dialog.h"
20+#include "settings.h"
21+#include "preferences.h"
22+
23+wxDEFINE_EVENT(WELCOME_DIALOG_ACTION, wxCommandEvent);
24+
25+WelcomeDialog::WelcomeDialog(const wxString& title_text, const wxString& version_text, const wxSize& size, const wxBitmap& rme_logo, const std::vector<wxString>& recent_files) :
26+ wxDialog(nullptr, wxID_ANY, "", wxDefaultPosition, size) {
27+ Centre();
28+ wxColour base_colour = wxColor(250, 250, 250);
29+ m_welcome_dialog_panel = newd WelcomeDialogPanel(this, GetClientSize(), title_text, version_text, base_colour, wxBitmap(rme_logo.ConvertToImage().Scale(FROM_DIP(this, 48), FROM_DIP(this, 48))), recent_files);
30+}
31+
32+void WelcomeDialog::OnButtonClicked(const wxMouseEvent& event) {
33+ auto* button = dynamic_cast<WelcomeDialogButton*>(event.GetEventObject());
34+ wxSize button_size = button->GetSize();
35+ wxPoint click_point = event.GetPosition();
36+ if (click_point.x > 0 && click_point.x < button_size.x && click_point.y > 0 && click_point.y < button_size.x) {
37+ if (button->GetAction() == wxID_PREFERENCES) {
38+ PreferencesWindow preferences_window(m_welcome_dialog_panel, true);
39+ preferences_window.ShowModal();
40+ m_welcome_dialog_panel->updateInputs();
41+ } else {
42+ wxCommandEvent action_event(WELCOME_DIALOG_ACTION);
43+ if (button->GetAction() == wxID_OPEN) {
44+ wxString wildcard = g_settings.getInteger(Config::USE_OTGZ) != 0 ? "(*.otbm;*.otgz)|*.otbm;*.otgz" : "(*.otbm)|*.otbm|Compressed OpenTibia Binary Map (*.otgz)|*.otgz";
45+ wxFileDialog file_dialog(this, "Open map file", "", "", wildcard, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
46+ if (file_dialog.ShowModal() == wxID_OK) {
47+ action_event.SetString(file_dialog.GetPath());
48+ } else {
49+ return;
50+ }
51+ }
52+ action_event.SetId(button->GetAction());
53+ ProcessWindowEvent(action_event);
54+ }
55+ }
56+}
57+
58+void WelcomeDialog::OnCheckboxClicked(const wxCommandEvent& event) {
59+ g_settings.setInteger(Config::WELCOME_DIALOG, event.GetInt());
60+}
61+
62+void WelcomeDialog::OnRecentItemClicked(const wxMouseEvent& event) {
63+ auto* recent_item = dynamic_cast<RecentItem*>(event.GetEventObject());
64+ wxSize button_size = recent_item->GetSize();
65+ wxPoint click_point = event.GetPosition();
66+ if (click_point.x > 0 && click_point.x < button_size.x && click_point.y > 0 && click_point.y < button_size.x) {
67+ wxCommandEvent action_event(WELCOME_DIALOG_ACTION);
68+ action_event.SetString(recent_item->GetText());
69+ action_event.SetId(wxID_OPEN);
70+ ProcessWindowEvent(action_event);
71+ }
72+}
73+
74+WhatsNewPanel::WhatsNewPanel(wxWindow* parent, const wxColour& base_colour) :
75+ wxPanel(parent, wxID_ANY),
76+ m_text_colour(base_colour.ChangeLightness(40)),
77+ m_background_colour(base_colour.ChangeLightness(98)) {
78+
79+ SetBackgroundColour(m_background_colour);
80+
81+ wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
82+
83+ // Add title
84+ wxStaticText* title = new wxStaticText(this, wxID_ANY, "What's New");
85+ wxFont titleFont = GetFont();
86+ titleFont.SetPointSize(12);
87+ titleFont.SetWeight(wxFONTWEIGHT_BOLD);
88+ title->SetFont(titleFont);
89+ title->SetForegroundColour(m_text_colour);
90+ sizer->Add(title, 0, wxALL, 10);
91+
92+ // Add text control for whatsnew.txt content
93+ whats_new_text = new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize,
94+ wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH2 | wxBORDER_NONE);
95+ whats_new_text->SetBackgroundColour(m_background_colour);
96+ whats_new_text->SetForegroundColour(m_text_colour);
97+ sizer->Add(whats_new_text, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 10);
98+
99+ SetSizer(sizer);
100+ LoadWhatsNew();
101+}
102+
103+void WhatsNewPanel::LoadWhatsNew() {
104+ wxString whatsnew_path = g_gui.GetDataDirectory() + "/whatsnew.txt";
105+ if (wxFileExists(whatsnew_path)) {
106+ wxFile file(whatsnew_path);
107+ if (file.IsOpened()) {
108+ wxString content;
109+ file.ReadAll(&content);
110+ whats_new_text->SetValue(content);
111+ }
112+ }
113+}
114+
115+WelcomeDialogPanel::WelcomeDialogPanel(WelcomeDialog* dialog, const wxSize& size, const wxString& title_text, const wxString& version_text, const wxColour& base_colour, const wxBitmap& rme_logo, const std::vector<wxString>& recent_files) :
116+ wxPanel(dialog),
117+ m_rme_logo(rme_logo),
118+ m_title_text("OTARME RD"),
119+ m_version_text(version_text),
120+ m_text_colour(base_colour.ChangeLightness(40)),
121+ m_background_colour(base_colour) {
122+
123+ auto* recent_maps_panel = newd RecentMapsPanel(this, dialog, base_colour, recent_files);
124+ recent_maps_panel->SetMaxSize(wxSize(size.x / 3, size.y));
125+ recent_maps_panel->SetBackgroundColour(base_colour.ChangeLightness(98));
126+
127+ auto* whats_new_panel = newd WhatsNewPanel(this, base_colour);
128+ whats_new_panel->SetMaxSize(wxSize(size.x / 3, size.y));
129+ whats_new_panel->SetBackgroundColour(base_colour.ChangeLightness(98));
130+
131+ wxSize button_size = FROM_DIP(this, wxSize(150, 35));
132+ wxColour button_base_colour = base_colour.ChangeLightness(90);
133+
134+ auto* new_map_button = newd WelcomeDialogButton(this, wxDefaultPosition, button_size, button_base_colour, "New");
135+ new_map_button->SetAction(wxID_NEW);
136+ new_map_button->Bind(wxEVT_LEFT_UP, &WelcomeDialog::OnButtonClicked, dialog);
137+
138+ auto* open_map_button = newd WelcomeDialogButton(this, wxDefaultPosition, button_size, button_base_colour, "Open");
139+ open_map_button->SetAction(wxID_OPEN);
140+ open_map_button->Bind(wxEVT_LEFT_UP, &WelcomeDialog::OnButtonClicked, dialog);
141+ auto* preferences_button = newd WelcomeDialogButton(this, wxDefaultPosition, button_size, button_base_colour, "Preferences");
142+ preferences_button->SetAction(wxID_PREFERENCES);
143+ preferences_button->Bind(wxEVT_LEFT_UP, &WelcomeDialog::OnButtonClicked, dialog);
144+
145+ // Left panel: vertical sizer with stretch spacers for centering
146+ wxBoxSizer* leftSizer = new wxBoxSizer(wxVERTICAL);
147+ leftSizer->AddStretchSpacer(1); // Top space
148+ // Logo
149+ wxStaticBitmap* logoBitmap = new wxStaticBitmap(this, wxID_ANY, m_rme_logo);
150+ leftSizer->Add(logoBitmap, 0, wxALIGN_CENTER | wxBOTTOM, 10);
151+ // Title
152+ wxStaticText* titleText = new wxStaticText(this, wxID_ANY, m_title_text);
153+ wxFont titleFont = GetFont();
154+ titleFont.SetPointSize(18);
155+ titleFont.SetWeight(wxFONTWEIGHT_BOLD);
156+ titleText->SetFont(titleFont);
157+ titleText->SetForegroundColour(m_text_colour);
158+ leftSizer->Add(titleText, 0, wxALIGN_CENTER | wxBOTTOM, 5);
159+ // Version
160+ wxStaticText* versionText = new wxStaticText(this, wxID_ANY, m_version_text);
161+ versionText->SetFont(GetFont());
162+ versionText->SetForegroundColour(m_text_colour.ChangeLightness(110));
163+ leftSizer->Add(versionText, 0, wxALIGN_CENTER | wxBOTTOM, 20);
164+ leftSizer->AddStretchSpacer(1); // Space before buttons
165+ // Buttons
166+ wxBoxSizer* buttonsSizer = new wxBoxSizer(wxVERTICAL);
167+ buttonsSizer->Add(new_map_button, 0, wxALIGN_CENTER | wxTOP, FROM_DIP(this, 10));
168+ buttonsSizer->Add(open_map_button, 0, wxALIGN_CENTER | wxTOP, FROM_DIP(this, 10));
169+ buttonsSizer->Add(preferences_button, 0, wxALIGN_CENTER | wxTOP, FROM_DIP(this, 10));
170+ leftSizer->Add(buttonsSizer, 0, wxALIGN_CENTER | wxBOTTOM, 10);
171+ // Checkbox at the bottom
172+ m_show_welcome_dialog_checkbox = newd wxCheckBox(this, wxID_ANY, "Show this dialog on startup");
173+ m_show_welcome_dialog_checkbox->SetValue(g_settings.getInteger(Config::WELCOME_DIALOG) == 1);
174+ m_show_welcome_dialog_checkbox->Bind(wxEVT_CHECKBOX, &WelcomeDialog::OnCheckboxClicked, dialog);
175+ m_show_welcome_dialog_checkbox->SetBackgroundColour(m_background_colour);
176+ leftSizer->Add(m_show_welcome_dialog_checkbox, 0, wxALIGN_LEFT | wxBOTTOM, 10);
177+
178+ Bind(wxEVT_PAINT, &WelcomeDialogPanel::OnPaint, this);
179+
180+ wxSizer* rootSizer = newd wxBoxSizer(wxHORIZONTAL);
181+ rootSizer->Add(leftSizer, 1, wxEXPAND | wxALL, 0);
182+ rootSizer->Add(whats_new_panel, 2, wxEXPAND);
183+ rootSizer->Add(recent_maps_panel, 1, wxEXPAND);
184+ SetSizer(rootSizer);
185+}
186+
187+void WelcomeDialogPanel::updateInputs() {
188+ m_show_welcome_dialog_checkbox->SetValue(g_settings.getInteger(Config::WELCOME_DIALOG) == 1);
189+}
190+
191+void WelcomeDialogPanel::OnPaint(const wxPaintEvent& event) {
192+ wxPaintDC dc(this);
193+
194+}
195+
196+WelcomeDialogButton::WelcomeDialogButton(wxWindow* parent, const wxPoint& pos, const wxSize& size, const wxColour& base_colour, const wxString& text) :
197+ wxPanel(parent, wxID_ANY, pos, size),
198+ m_action(wxID_CLOSE),
199+ m_text(text),
200+ m_text_colour(base_colour.ChangeLightness(40)),
201+ m_background(base_colour.ChangeLightness(96)),
202+ m_background_hover(base_colour.ChangeLightness(93)),
203+ m_is_hover(false) {
204+ Bind(wxEVT_PAINT, &WelcomeDialogButton::OnPaint, this);
205+ Bind(wxEVT_ENTER_WINDOW, &WelcomeDialogButton::OnMouseEnter, this);
206+ Bind(wxEVT_LEAVE_WINDOW, &WelcomeDialogButton::OnMouseLeave, this);
207+}
208+
209+void WelcomeDialogButton::OnPaint(const wxPaintEvent& event) {
210+ wxPaintDC dc(this);
211+
212+ wxColour colour = m_is_hover ? m_background_hover : m_background;
213+ dc.SetBrush(wxBrush(colour));
214+ dc.SetPen(wxPen(colour, 1));
215+ dc.DrawRectangle(wxRect(wxPoint(0, 0), GetClientSize()));
216+
217+ dc.SetFont(GetFont());
218+ dc.SetTextForeground(m_text_colour);
219+ wxSize text_size = dc.GetTextExtent(m_text);
220+ dc.DrawText(m_text, wxPoint(GetSize().x / 2 - text_size.x / 2, GetSize().y / 2 - text_size.y / 2));
221+}
222+
223+void WelcomeDialogButton::OnMouseEnter(const wxMouseEvent& event) {
224+ m_is_hover = true;
225+ Refresh();
226+}
227+
228+void WelcomeDialogButton::OnMouseLeave(const wxMouseEvent& event) {
229+ m_is_hover = false;
230+ Refresh();
231+}
232+
233+RecentMapsPanel::RecentMapsPanel(wxWindow* parent, WelcomeDialog* dialog, const wxColour& base_colour, const std::vector<wxString>& recent_files) :
234+ wxPanel(parent, wxID_ANY) {
235+ wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
236+ for (const wxString& file : recent_files) {
237+ auto* recent_item = newd RecentItem(this, base_colour, file);
238+ sizer->Add(recent_item, 0, wxEXPAND);
239+ recent_item->Bind(wxEVT_LEFT_UP, &WelcomeDialog::OnRecentItemClicked, dialog);
240+ }
241+ SetSizerAndFit(sizer);
242+}
243+
244+RecentItem::RecentItem(wxWindow* parent, const wxColour& base_colour, const wxString& item_name) :
245+ wxPanel(parent, wxID_ANY),
246+ m_text_colour(base_colour.ChangeLightness(40)),
247+ m_text_colour_hover(base_colour.ChangeLightness(20)),
248+ m_item_text(item_name) {
249+ SetBackgroundColour(base_colour.ChangeLightness(95));
250+ m_title = newd wxStaticText(this, wxID_ANY, wxFileNameFromPath(m_item_text));
251+ m_title->SetFont(GetFont().Bold());
252+ m_title->SetForegroundColour(m_text_colour);
253+ m_title->SetToolTip(m_item_text);
254+ m_file_path = newd wxStaticText(this, wxID_ANY, m_item_text, wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_START);
255+ m_file_path->SetToolTip(m_item_text);
256+ m_file_path->SetFont(GetFont().Smaller());
257+ m_file_path->SetForegroundColour(m_text_colour);
258+ wxBoxSizer* mainSizer = newd wxBoxSizer(wxHORIZONTAL);
259+ wxBoxSizer* sizer = newd wxBoxSizer(wxVERTICAL);
260+ sizer->Add(m_title);
261+ sizer->Add(m_file_path, 1, wxTOP, FROM_DIP(this, 2));
262+ mainSizer->Add(sizer, 0, wxEXPAND | wxALL, FROM_DIP(this, 8));
263+ Bind(wxEVT_ENTER_WINDOW, &RecentItem::OnMouseEnter, this);
264+ Bind(wxEVT_LEAVE_WINDOW, &RecentItem::OnMouseLeave, this);
265+ m_title->Bind(wxEVT_LEFT_UP, &RecentItem::PropagateItemClicked, this);
266+ m_file_path->Bind(wxEVT_LEFT_UP, &RecentItem::PropagateItemClicked, this);
267+ SetSizerAndFit(mainSizer);
268+}
269+
270+void RecentItem::PropagateItemClicked(wxMouseEvent& event) {
271+ event.ResumePropagation(1);
272+ event.SetEventObject(this);
273+ event.Skip();
274+}
275+
276+void RecentItem::OnMouseEnter(const wxMouseEvent& event) {
277+ if (GetScreenRect().Contains(ClientToScreen(event.GetPosition()))
278+ && m_title->GetForegroundColour() != m_text_colour_hover) {
279+ m_title->SetForegroundColour(m_text_colour_hover);
280+ m_file_path->SetForegroundColour(m_text_colour_hover);
281+ m_title->Refresh();
282+ m_file_path->Refresh();
283+ }
284+}
285+
286+void RecentItem::OnMouseLeave(const wxMouseEvent& event) {
287+ if (!GetScreenRect().Contains(ClientToScreen(event.GetPosition()))
288+ && m_title->GetForegroundColour() != m_text_colour) {
289+ m_title->SetForegroundColour(m_text_colour);
290+ m_file_path->SetForegroundColour(m_text_colour);
291+ m_title->Refresh();
292+ m_file_path->Refresh();
293+ }
294+}
A RD_Map_Editor/source/welcome_dialog.h +108-0 View file
@@ -0,0 +1,108 @@
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 WELCOME_DIALOG_H
19+#define WELCOME_DIALOG_H
20+
21+#include <wx/wx.h>
22+
23+wxDECLARE_EVENT(WELCOME_DIALOG_ACTION, wxCommandEvent);
24+
25+class WelcomeDialogPanel;
26+
27+class WelcomeDialog : public wxDialog {
28+public:
29+ WelcomeDialog(const wxString& titleText, const wxString& versionText, const wxSize& size, const wxBitmap& rmeLogo, const std::vector<wxString>& recentFiles);
30+ void OnButtonClicked(const wxMouseEvent& event);
31+ void OnCheckboxClicked(const wxCommandEvent& event);
32+ void OnRecentItemClicked(const wxMouseEvent& event);
33+
34+private:
35+ WelcomeDialogPanel* m_welcome_dialog_panel;
36+};
37+
38+class WelcomeDialogPanel : public wxPanel {
39+public:
40+ WelcomeDialogPanel(WelcomeDialog* parent, const wxSize& size, const wxString& title_text, const wxString& version_text, const wxColour& base_colour, const wxBitmap& rme_logo, const std::vector<wxString>& recent_files);
41+ void OnPaint(const wxPaintEvent& event);
42+ void updateInputs();
43+
44+private:
45+ wxBitmap m_rme_logo;
46+ wxString m_title_text;
47+ wxString m_version_text;
48+ wxColour m_text_colour;
49+ wxColour m_background_colour;
50+ wxCheckBox* m_show_welcome_dialog_checkbox;
51+};
52+
53+class WelcomeDialogButton : public wxPanel {
54+public:
55+ WelcomeDialogButton(wxWindow* parent, const wxPoint& pos, const wxSize& size, const wxColour& base_colour, const wxString& text);
56+ void OnPaint(const wxPaintEvent& event);
57+ void OnMouseEnter(const wxMouseEvent& event);
58+ void OnMouseLeave(const wxMouseEvent& event);
59+ wxStandardID GetAction() {
60+ return m_action;
61+ };
62+ void SetAction(wxStandardID action) {
63+ m_action = action;
64+ };
65+
66+private:
67+ wxStandardID m_action;
68+ wxString m_text;
69+ wxColour m_text_colour;
70+ wxColour m_background;
71+ wxColour m_background_hover;
72+ bool m_is_hover;
73+};
74+
75+class RecentMapsPanel : public wxPanel {
76+public:
77+ RecentMapsPanel(wxWindow* parent, WelcomeDialog* dialog, const wxColour& base_colour, const std::vector<wxString>& recent_files);
78+};
79+
80+class WhatsNewPanel : public wxPanel {
81+public:
82+ WhatsNewPanel(wxWindow* parent, const wxColour& base_colour);
83+ void LoadWhatsNew();
84+private:
85+ wxTextCtrl* whats_new_text;
86+ wxColour m_text_colour;
87+ wxColour m_background_colour;
88+};
89+
90+class RecentItem : public wxPanel {
91+public:
92+ RecentItem(wxWindow* parent, const wxColour& base_colour, const wxString& item_name);
93+ void OnMouseEnter(const wxMouseEvent& event);
94+ void OnMouseLeave(const wxMouseEvent& event);
95+ void PropagateItemClicked(wxMouseEvent& event);
96+ wxString GetText() {
97+ return m_item_text;
98+ };
99+
100+private:
101+ wxColour m_text_colour;
102+ wxColour m_text_colour_hover;
103+ wxStaticText* m_title;
104+ wxStaticText* m_file_path;
105+ wxString m_item_text;
106+};
107+
108+#endif // WELCOME_DIALOG_H
A RD_Map_Editor/tools/convert_png2cpp.py +65-0 View file
@@ -0,0 +1,65 @@
1+#!/usr/bin/python
2+"""
3+Converts all .png files into this directory to a .h & one .cpp
4+file.
5+"""
6+import sys
7+import os
8+import os.path
9+import re
10+import array
11+import glob
12+
13+r = re.compile("^([a-zA-Z._][a-zA-Z._0-9]*)[.][pP][nN][gG]$")
14+
15+header_file = open("pngfiles.h", "wb")
16+source_file = open("pngfiles.cpp", "wb")
17+
18+header_file.write("#ifndef __PNG_HEADER_FILE_H__\n")
19+header_file.write("#define __PNG_HEADER_FILE_H__\n")
20+
21+png_files = glob.glob("*.png")
22+
23+for path in png_files:
24+ filename = os.path.basename(path)
25+ m = r.match(filename)
26+ # Allow only filenames that make sense
27+ # as C variable names
28+ if not(m):
29+ print "Skipped file (unsuitable filename): " + filename
30+ continue
31+
32+ # Read PNG file as character array
33+ bytes = array.array('B', open(path, "rb").read())
34+ count = len(bytes)
35+
36+ # Output to header
37+ header_file.write("extern unsigned char " + m.group(1) + "_png[" + str(count) + "];\n")
38+ # Create the C file
39+ text = "/* " + filename + " - " + str(count) + " bytes */\nunsigned char " + m.group(1) + "_png[" + str(count) + "] = {\n"
40+
41+ # Iterate the characters, we want
42+ # lines like:
43+ # 0x01, 0x02, .... (8 values per line maximum)
44+ i = 0
45+ count = len(bytes)
46+ for byte in bytes:
47+ # Every new line starts with two whitespaces
48+ if (i % 8) == 0:
49+ text += " "
50+ # Then the hex data (up to 8 values per line)
51+ text += "0x%02x" % (byte)
52+ # Separate all but the last values
53+ if (i + 1) < count:
54+ text += ", "
55+ if (i % 8) == 7:
56+ text += '\n'
57+ i += 1
58+
59+ # Now conclude the C source
60+ text += "};\n/* End Of File */\n"
61+
62+ source_file.write(text)
63+
64+header_file.write("#endif //__PNG_HEADER_FILE_H__\n")
65+
A RD_Map_Editor/tools/Tibia.otfi +7-0 View file
@@ -0,0 +1,7 @@
1+DatSpr
2+ extended: false
3+ transparency: false
4+ frame-durations: false
5+ frame-groups: false
6+ metadata-file: Tibia.dat
7+ sprites-file: Tibia.spr
A RD_Map_Editor/towns/1.xml +39-0 View file
@@ -0,0 +1,39 @@
1+<?xml version="1.0"?>
2+<towns>
3+ <town id="1" name="Rookgaard">
4+ <temple x="1142" y="1103" z="5" />
5+ </town>
6+ <town id="2" name="Citadel Isle">
7+ <temple x="3696" y="3612" z="7" />
8+ </town>
9+ <town id="3" name="Elary">
10+ <temple x="3162" y="1332" z="7" />
11+ </town>
12+ <town id="4" name="Woodlow">
13+ <temple x="3161" y="1076" z="7" />
14+ </town>
15+ <town id="5" name="Smallville">
16+ <temple x="3192" y="1129" z="5" />
17+ </town>
18+ <town id="6" name="Emerald Town">
19+ <temple x="4791" y="3446" z="8" />
20+ </town>
21+ <town id="7" name="Caver Camp">
22+ <temple x="5036" y="3307" z="7" />
23+ </town>
24+ <town id="8" name="Toros Town">
25+ <temple x="4882" y="2982" z="6" />
26+ </town>
27+ <town id="9" name="Icelai">
28+ <temple x="5015" y="2325" z="7" />
29+ </town>
30+ <town id="10" name="Drathk'ia">
31+ <temple x="5110" y="4844" z="5" />
32+ </town>
33+ <town id="11" name="GM">
34+ <temple x="5094" y="5106" z="7" />
35+ </town>
36+ <town id="12" name="Nargor">
37+ <temple x="3917" y="3822" z="6" />
38+ </town>
39+</towns>
A RD_Map_Editor/towns/rookgaard.xml +39-0 View file
@@ -0,0 +1,39 @@
1+<?xml version="1.0"?>
2+<towns>
3+ <town id="1" name="Rookgaard">
4+ <temple x="1142" y="1103" z="5" />
5+ </town>
6+ <town id="2" name="Citadel Isle">
7+ <temple x="3696" y="3612" z="7" />
8+ </town>
9+ <town id="3" name="Elary">
10+ <temple x="3162" y="1332" z="7" />
11+ </town>
12+ <town id="4" name="Woodlow">
13+ <temple x="3161" y="1076" z="7" />
14+ </town>
15+ <town id="5" name="Smallville">
16+ <temple x="3192" y="1129" z="5" />
17+ </town>
18+ <town id="6" name="Emerald Town">
19+ <temple x="4791" y="3446" z="8" />
20+ </town>
21+ <town id="7" name="Caver Camp">
22+ <temple x="5036" y="3307" z="7" />
23+ </town>
24+ <town id="8" name="Toros Town">
25+ <temple x="4882" y="2982" z="6" />
26+ </town>
27+ <town id="9" name="Icelai">
28+ <temple x="5015" y="2325" z="7" />
29+ </town>
30+ <town id="10" name="Drathk'ia">
31+ <temple x="5110" y="4844" z="5" />
32+ </town>
33+ <town id="11" name="GM">
34+ <temple x="5094" y="5106" z="7" />
35+ </town>
36+ <town id="12" name="Nargor">
37+ <temple x="3917" y="3822" z="6" />
38+ </town>
39+</towns>
A RD_Map_Editor/towns/sm.xml +33-0 View file
@@ -0,0 +1,33 @@
1+<?xml version="1.0"?>
2+<towns>
3+ <town id="1" name="Rookgaard">
4+ <temple x="1142" y="1103" z="5" />
5+ </town>
6+ <town id="2" name="Citadel Isle">
7+ <temple x="3696" y="3612" z="7" />
8+ </town>
9+ <town id="3" name="Smallville">
10+ <temple x="3192" y="1129" z="5" />
11+ </town>
12+ <town id="4" name="Emerald Town">
13+ <temple x="4791" y="3446" z="8" />
14+ </town>
15+ <town id="5" name="Caver Camp">
16+ <temple x="5036" y="3307" z="7" />
17+ </town>
18+ <town id="6" name="Toros Town">
19+ <temple x="4882" y="2982" z="6" />
20+ </town>
21+ <town id="7" name="Icelai">
22+ <temple x="5015" y="2325" z="7" />
23+ </town>
24+ <town id="8" name="Drathk'ia">
25+ <temple x="5110" y="4844" z="5" />
26+ </town>
27+ <town id="9" name="GM">
28+ <temple x="5094" y="5106" z="7" />
29+ </town>
30+ <town id="10" name="Nargor">
31+ <temple x="3917" y="3822" z="6" />
32+ </town>
33+</towns>
Top