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/graphics.h +435-0 View file
@@ -0,0 +1,435 @@
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_GRAPHICS_H_
19+#define RME_GRAPHICS_H_
20+
21+#include "outfit.h"
22+#include "common.h"
23+#include <deque>
24+
25+#include "client_version.h"
26+
27+enum SpriteSize {
28+ SPRITE_SIZE_16x16,
29+ // SPRITE_SIZE_24x24,
30+ SPRITE_SIZE_32x32,
31+ SPRITE_SIZE_64x64,
32+ SPRITE_SIZE_COUNT
33+};
34+
35+enum AnimationDirection {
36+ ANIMATION_FORWARD = 0,
37+ ANIMATION_BACKWARD = 1
38+};
39+
40+enum ItemAnimationDuration {
41+ ITEM_FRAME_DURATION = 500
42+};
43+
44+class MapCanvas;
45+class GraphicManager;
46+class FileReadHandle;
47+class Animator;
48+
49+struct SpriteLight {
50+ uint8_t intensity = 0;
51+ uint8_t color = 0;
52+};
53+
54+class Sprite {
55+public:
56+ Sprite() { }
57+ virtual ~Sprite() { }
58+
59+ virtual void DrawTo(wxDC* dc, SpriteSize sz, int start_x, int start_y, int width = -1, int height = -1) = 0;
60+ virtual void unloadDC() = 0;
61+
62+private:
63+ Sprite(const Sprite&);
64+ Sprite& operator=(const Sprite&);
65+};
66+
67+class EditorSprite : public Sprite {
68+public:
69+ EditorSprite(wxBitmap* b16x16, wxBitmap* b32x32, wxBitmap* b64x64 = nullptr);
70+ virtual ~EditorSprite();
71+
72+ virtual void DrawTo(wxDC* dc, SpriteSize sz, int start_x, int start_y, int width = -1, int height = -1);
73+ virtual void unloadDC();
74+
75+protected:
76+ wxBitmap* bm[SPRITE_SIZE_COUNT];
77+};
78+
79+class GameSprite : public Sprite {
80+public:
81+ GameSprite();
82+ ~GameSprite();
83+
84+ int getIndex(int width, int height, int layer, int pattern_x, int pattern_y, int pattern_z, int frame) const;
85+ GLuint getHardwareID(int _x, int _y, int _layer, int _subtype, int _pattern_x, int _pattern_y, int _pattern_z, int _frame);
86+ GLuint getHardwareID(int _x, int _y, int _dir, int _addon, int _pattern_z, const Outfit& _outfit, int _frame); // CreatureDatabase
87+ virtual void DrawTo(wxDC* dc, SpriteSize sz, int start_x, int start_y, int width = -1, int height = -1);
88+
89+ // Method to draw creatures with outfit colors
90+ virtual void DrawOutfit(wxDC* dc, SpriteSize sz, int start_x, int start_y, const Outfit& outfit);
91+
92+ virtual void unloadDC();
93+
94+ void clean(int time);
95+
96+ int getDrawHeight() const;
97+ std::pair<int, int> getDrawOffset() const;
98+ uint8_t getMiniMapColor() const;
99+
100+ bool hasLight() const noexcept {
101+ return has_light;
102+ }
103+ const SpriteLight& getLight() const noexcept {
104+ return light;
105+ }
106+
107+protected:
108+ class Image;
109+ class NormalImage;
110+ class TemplateImage;
111+
112+ wxMemoryDC* getDC(SpriteSize size);
113+ TemplateImage* getTemplateImage(int sprite_index, const Outfit& outfit);
114+
115+ class Image {
116+ public:
117+ Image();
118+ virtual ~Image();
119+
120+ bool isGLLoaded;
121+ int lastaccess;
122+
123+ void visit();
124+ virtual void clean(int time);
125+
126+ virtual GLuint getHardwareID() = 0;
127+ virtual uint8_t* getRGBData() = 0;
128+ virtual uint8_t* getRGBAData() = 0;
129+
130+ protected:
131+ virtual void createGLTexture(GLuint whatid);
132+ virtual void unloadGLTexture(GLuint whatid);
133+ };
134+
135+ class NormalImage : public Image {
136+ public:
137+ NormalImage();
138+ virtual ~NormalImage();
139+
140+ // We use the sprite id as GL texture id
141+ uint32_t id;
142+
143+ // This contains the pixel data
144+ uint16_t size;
145+ uint8_t* dump;
146+
147+ virtual void clean(int time);
148+
149+ virtual GLuint getHardwareID();
150+ virtual uint8_t* getRGBData();
151+ virtual uint8_t* getRGBAData();
152+
153+ protected:
154+ virtual void createGLTexture(GLuint ignored = 0);
155+ virtual void unloadGLTexture(GLuint ignored = 0);
156+ };
157+
158+ class TemplateImage : public Image {
159+ public:
160+ TemplateImage(GameSprite* parent, int v, const Outfit& outfit);
161+ virtual ~TemplateImage();
162+
163+ virtual GLuint getHardwareID();
164+ virtual uint8_t* getRGBData();
165+ virtual uint8_t* getRGBAData();
166+
167+ GLuint gl_tid;
168+ GameSprite* parent;
169+ int sprite_index;
170+ uint8_t lookHead;
171+ uint8_t lookBody;
172+ uint8_t lookLegs;
173+ uint8_t lookFeet;
174+
175+ protected:
176+ void colorizePixel(uint8_t color, uint8_t& r, uint8_t& b, uint8_t& g);
177+
178+ virtual void createGLTexture(GLuint ignored = 0);
179+ virtual void unloadGLTexture(GLuint ignored = 0);
180+ };
181+
182+ uint32_t id;
183+ wxMemoryDC* dc[SPRITE_SIZE_COUNT];
184+
185+public:
186+ // GameSprite info
187+ uint8_t height;
188+ uint8_t width;
189+ uint8_t layers;
190+ uint8_t pattern_x;
191+ uint8_t pattern_y;
192+ uint8_t pattern_z;
193+ uint8_t frames;
194+ uint32_t numsprites;
195+
196+ Animator* animator;
197+
198+ uint16_t draw_height;
199+ uint16_t drawoffset_x;
200+ uint16_t drawoffset_y;
201+
202+ uint16_t minimap_color;
203+
204+ bool has_light = false;
205+ SpriteLight light;
206+
207+ std::vector<NormalImage*> spriteList;
208+ std::list<TemplateImage*> instanced_templates; // Templates that use this sprite
209+
210+ friend class GraphicManager;
211+};
212+
213+struct FrameDuration {
214+ int min;
215+ int max;
216+
217+ FrameDuration(int min, int max) :
218+ min(min), max(max) {
219+ ASSERT(min <= max);
220+ }
221+
222+ int getDuration() const {
223+ if (min == max) {
224+ return min;
225+ }
226+ return uniform_random(min, max);
227+ };
228+
229+ void setValues(int min, int max) {
230+ ASSERT(min <= max);
231+ this->min = min;
232+ this->max = max;
233+ }
234+};
235+
236+class Animator {
237+public:
238+ Animator(int frames, int start_frame, int loop_count, bool async);
239+ ~Animator();
240+
241+ int getStartFrame() const;
242+
243+ FrameDuration* getFrameDuration(int frame);
244+
245+ int getFrame();
246+ void setFrame(int frame);
247+
248+ void reset();
249+
250+private:
251+ int getDuration(int frame) const;
252+ int getPingPongFrame();
253+ int getLoopFrame();
254+ void calculateSynchronous();
255+
256+ int frame_count;
257+ int start_frame;
258+ int loop_count;
259+ bool async;
260+ std::vector<FrameDuration*> durations;
261+ int current_frame;
262+ int current_loop;
263+ int current_duration;
264+ int total_duration;
265+ AnimationDirection direction;
266+ long last_time;
267+ bool is_complete;
268+};
269+
270+class GraphicManager {
271+public:
272+ GraphicManager();
273+ ~GraphicManager();
274+
275+ void clear();
276+ void cleanSoftwareSprites();
277+
278+ Sprite* getSprite(int id);
279+ GameSprite* getCreatureSprite(int id);
280+
281+ long getElapsedTime() const {
282+ return (animation_timer->TimeInMicro() / 1000).ToLong();
283+ }
284+
285+ uint16_t getItemSpriteMaxID() const;
286+ uint16_t getCreatureSpriteMaxID() const;
287+
288+ // Get an unused texture id (this is acquired by simply increasing a value starting from 0x10000000)
289+ GLuint getFreeTextureID();
290+
291+ // This is part of the binary
292+ bool loadEditorSprites();
293+ // Metadata should be loaded first
294+ // This fills the item / creature adress space
295+ bool loadOTFI(const FileName& filename, wxString& error, wxArrayString& warnings);
296+ bool loadSpriteMetadata(const FileName& datafile, wxString& error, wxArrayString& warnings);
297+ bool loadSpriteMetadataFlags(FileReadHandle& file, GameSprite* sType, wxString& error, wxArrayString& warnings);
298+ bool loadSpriteData(const FileName& datafile, wxString& error, wxArrayString& warnings);
299+
300+ // Cleans old & unused textures according to config settings
301+ void garbageCollection();
302+ void addSpriteToCleanup(GameSprite* spr);
303+
304+ wxFileName getMetadataFileName() const {
305+ return metadata_file;
306+ }
307+ wxFileName getSpritesFileName() const {
308+ return sprites_file;
309+ }
310+
311+ bool hasTransparency() const;
312+ bool isUnloaded() const;
313+
314+ ClientVersion* client_version;
315+
316+private:
317+ bool unloaded;
318+ // This is used if memcaching is NOT on
319+ std::string spritefile;
320+ bool loadSpriteDump(uint8_t*& target, uint16_t& size, int sprite_id);
321+
322+ typedef std::map<int, Sprite*> SpriteMap;
323+ SpriteMap sprite_space;
324+ typedef std::map<int, GameSprite::Image*> ImageMap;
325+ ImageMap image_space;
326+ std::deque<GameSprite*> cleanup_list;
327+
328+ DatFormat dat_format;
329+ uint16_t item_count;
330+ uint16_t creature_count;
331+ bool otfi_found;
332+ bool is_extended;
333+ bool has_transparency;
334+ bool has_frame_durations;
335+ bool has_frame_groups;
336+ wxFileName metadata_file;
337+ wxFileName sprites_file;
338+
339+ int loaded_textures;
340+ int lastclean;
341+
342+ wxStopWatch* animation_timer;
343+
344+ friend class GameSprite::Image;
345+ friend class GameSprite::NormalImage;
346+ friend class GameSprite::TemplateImage;
347+};
348+
349+struct RGBQuad {
350+ uint8_t red;
351+ uint8_t green;
352+ uint8_t blue;
353+ uint8_t reserved;
354+
355+ RGBQuad(uint8_t r, uint8_t g, uint8_t b) :
356+ red(r), green(g), blue(b), reserved(0) { }
357+
358+ operator uint32_t() {
359+ return (blue << 0) | (green << 8) | (red << 16);
360+ }
361+
362+ operator bool() {
363+ // std::cout << "RGBQuad operator bool " << int(red) << " || " << int(blue) << " || " << int(green) << std::endl;
364+ return blue != 0 || red != 0 || green != 0;
365+ }
366+};
367+
368+static RGBQuad minimap_color[256] = {
369+ RGBQuad(0, 0, 0), RGBQuad(0, 0, 51), RGBQuad(0, 0, 102), RGBQuad(0, 0, 153), // 0
370+ RGBQuad(0, 0, 204), RGBQuad(0, 0, 255), RGBQuad(0, 51, 0), RGBQuad(0, 51, 51), // 4
371+ RGBQuad(0, 51, 102), RGBQuad(0, 51, 153), RGBQuad(0, 51, 204), RGBQuad(0, 51, 255), // 8
372+ RGBQuad(0, 102, 0), RGBQuad(0, 102, 51), RGBQuad(0, 102, 102), RGBQuad(0, 102, 153), // 12
373+ RGBQuad(0, 102, 204), RGBQuad(0, 102, 255), RGBQuad(0, 153, 0), RGBQuad(0, 153, 51), // 16
374+ RGBQuad(0, 153, 102), RGBQuad(0, 153, 153), RGBQuad(0, 153, 204), RGBQuad(0, 153, 255), // 20
375+ RGBQuad(0, 204, 0), RGBQuad(0, 204, 51), RGBQuad(0, 204, 102), RGBQuad(0, 204, 153), // 24
376+ RGBQuad(0, 204, 204), RGBQuad(0, 204, 255), RGBQuad(0, 255, 0), RGBQuad(0, 255, 51), // 28
377+ RGBQuad(0, 255, 102), RGBQuad(0, 255, 153), RGBQuad(0, 255, 204), RGBQuad(0, 255, 255), // 32
378+ RGBQuad(51, 0, 0), RGBQuad(51, 0, 51), RGBQuad(51, 0, 102), RGBQuad(51, 0, 153), // 36
379+ RGBQuad(51, 0, 204), RGBQuad(51, 0, 255), RGBQuad(51, 51, 0), RGBQuad(51, 51, 51), // 40
380+ RGBQuad(51, 51, 102), RGBQuad(51, 51, 153), RGBQuad(51, 51, 204), RGBQuad(51, 51, 255), // 44
381+ RGBQuad(51, 102, 0), RGBQuad(51, 102, 51), RGBQuad(51, 102, 102), RGBQuad(51, 102, 153), // 48
382+ RGBQuad(51, 102, 204), RGBQuad(51, 102, 255), RGBQuad(51, 153, 0), RGBQuad(51, 153, 51), // 52
383+ RGBQuad(51, 153, 102), RGBQuad(51, 153, 153), RGBQuad(51, 153, 204), RGBQuad(51, 153, 255), // 56
384+ RGBQuad(51, 204, 0), RGBQuad(51, 204, 51), RGBQuad(51, 204, 102), RGBQuad(51, 204, 153), // 60
385+ RGBQuad(51, 204, 204), RGBQuad(51, 204, 255), RGBQuad(51, 255, 0), RGBQuad(51, 255, 51), // 64
386+ RGBQuad(51, 255, 102), RGBQuad(51, 255, 153), RGBQuad(51, 255, 204), RGBQuad(51, 255, 255), // 68
387+ RGBQuad(102, 0, 0), RGBQuad(102, 0, 51), RGBQuad(102, 0, 102), RGBQuad(102, 0, 153), // 72
388+ RGBQuad(102, 0, 204), RGBQuad(102, 0, 255), RGBQuad(102, 51, 0), RGBQuad(102, 51, 51), // 76
389+ RGBQuad(102, 51, 102), RGBQuad(102, 51, 153), RGBQuad(102, 51, 204), RGBQuad(102, 51, 255), // 80
390+ RGBQuad(102, 102, 0), RGBQuad(102, 102, 51), RGBQuad(102, 102, 102), RGBQuad(102, 102, 153), // 84
391+ RGBQuad(102, 102, 204), RGBQuad(102, 102, 255), RGBQuad(102, 153, 0), RGBQuad(102, 153, 51), // 88
392+ RGBQuad(102, 153, 102), RGBQuad(102, 153, 153), RGBQuad(102, 153, 204), RGBQuad(102, 153, 255), // 92
393+ RGBQuad(102, 204, 0), RGBQuad(102, 204, 51), RGBQuad(102, 204, 102), RGBQuad(102, 204, 153), // 96
394+ RGBQuad(102, 204, 204), RGBQuad(102, 204, 255), RGBQuad(102, 255, 0), RGBQuad(102, 255, 51), // 100
395+ RGBQuad(102, 255, 102), RGBQuad(102, 255, 153), RGBQuad(102, 255, 204), RGBQuad(102, 255, 255), // 104
396+ RGBQuad(153, 0, 0), RGBQuad(153, 0, 51), RGBQuad(153, 0, 102), RGBQuad(153, 0, 153), // 108
397+ RGBQuad(153, 0, 204), RGBQuad(153, 0, 255), RGBQuad(153, 51, 0), RGBQuad(153, 51, 51), // 112
398+ RGBQuad(153, 51, 102), RGBQuad(153, 51, 153), RGBQuad(153, 51, 204), RGBQuad(153, 51, 255), // 116
399+ RGBQuad(153, 102, 0), RGBQuad(153, 102, 51), RGBQuad(153, 102, 102), RGBQuad(153, 102, 153), // 120
400+ RGBQuad(153, 102, 204), RGBQuad(153, 102, 255), RGBQuad(153, 153, 0), RGBQuad(153, 153, 51), // 124
401+ RGBQuad(153, 153, 102), RGBQuad(153, 153, 153), RGBQuad(153, 153, 204), RGBQuad(153, 153, 255), // 128
402+ RGBQuad(153, 204, 0), RGBQuad(153, 204, 51), RGBQuad(153, 204, 102), RGBQuad(153, 204, 153), // 132
403+ RGBQuad(153, 204, 204), RGBQuad(153, 204, 255), RGBQuad(153, 255, 0), RGBQuad(153, 255, 51), // 136
404+ RGBQuad(153, 255, 102), RGBQuad(153, 255, 153), RGBQuad(153, 255, 204), RGBQuad(153, 255, 255), // 140
405+ RGBQuad(204, 0, 0), RGBQuad(204, 0, 51), RGBQuad(204, 0, 102), RGBQuad(204, 0, 153), // 144
406+ RGBQuad(204, 0, 204), RGBQuad(204, 0, 255), RGBQuad(204, 51, 0), RGBQuad(204, 51, 51), // 148
407+ RGBQuad(204, 51, 102), RGBQuad(204, 51, 153), RGBQuad(204, 51, 204), RGBQuad(204, 51, 255), // 152
408+ RGBQuad(204, 102, 0), RGBQuad(204, 102, 51), RGBQuad(204, 102, 102), RGBQuad(204, 102, 153), // 156
409+ RGBQuad(204, 102, 204), RGBQuad(204, 102, 255), RGBQuad(204, 153, 0), RGBQuad(204, 153, 51), // 160
410+ RGBQuad(204, 153, 102), RGBQuad(204, 153, 153), RGBQuad(204, 153, 204), RGBQuad(204, 153, 255), // 164
411+ RGBQuad(204, 204, 0), RGBQuad(204, 204, 51), RGBQuad(204, 204, 102), RGBQuad(204, 204, 153), // 168
412+ RGBQuad(204, 204, 204), RGBQuad(204, 204, 255), RGBQuad(204, 255, 0), RGBQuad(204, 255, 51), // 172
413+ RGBQuad(204, 255, 102), RGBQuad(204, 255, 153), RGBQuad(204, 255, 204), RGBQuad(204, 255, 255), // 176
414+ RGBQuad(255, 0, 0), RGBQuad(255, 0, 51), RGBQuad(255, 0, 102), RGBQuad(255, 0, 153), // 180
415+ RGBQuad(255, 0, 204), RGBQuad(255, 0, 255), RGBQuad(255, 51, 0), RGBQuad(255, 51, 51), // 184
416+ RGBQuad(255, 51, 102), RGBQuad(255, 51, 153), RGBQuad(255, 51, 204), RGBQuad(255, 51, 255), // 188
417+ RGBQuad(255, 102, 0), RGBQuad(255, 102, 51), RGBQuad(255, 102, 102), RGBQuad(255, 102, 153), // 192
418+ RGBQuad(255, 102, 204), RGBQuad(255, 102, 255), RGBQuad(255, 153, 0), RGBQuad(255, 153, 51), // 196
419+ RGBQuad(255, 153, 102), RGBQuad(255, 153, 153), RGBQuad(255, 153, 204), RGBQuad(255, 153, 255), // 200
420+ RGBQuad(255, 204, 0), RGBQuad(255, 204, 51), RGBQuad(255, 204, 102), RGBQuad(255, 204, 153), // 204
421+ RGBQuad(255, 204, 204), RGBQuad(255, 204, 255), RGBQuad(255, 255, 0), RGBQuad(255, 255, 51), // 208
422+ RGBQuad(255, 255, 102), RGBQuad(255, 255, 153), RGBQuad(255, 255, 204), RGBQuad(255, 255, 255), // 212
423+ RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), // 216
424+ RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), // 220
425+ RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), // 224
426+ RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), // 228
427+ RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), // 232
428+ RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), // 236
429+ RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), // 240
430+ RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), // 244
431+ RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), // 248
432+ RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0), RGBQuad(0, 0, 0) // 252
433+};
434+
435+#endif
Top