aboutsummaryrefslogtreecommitdiff
path: root/src/client/tile.h
blob: 2a33dd160801ed35acf1f3a0c7cab26f099cdce2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
/*
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

This program 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 Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#pragma once

#include "irrlichttypes.h"
#include "irr_v3d.h"
#include <ITexture.h>
#include <string>
#include <vector>
#include <SMaterial.h>
#include <memory>
#include "util/numeric.h"

#if __ANDROID__
#include <IVideoDriver.h>
/*
   CGUITTFont FreeType class for Irrlicht
   Copyright (c) 2009-2010 John Norman

   This software is provided 'as-is', without any express or implied
   warranty. In no event will the authors be held liable for any
   damages arising from the use of this software.

   Permission is granted to anyone to use this software for any
   purpose, including commercial applications, and to alter it and
   redistribute it freely, subject to the following restrictions:

   1. The origin of this software must not be misrepresented; you
      must not claim that you wrote the original software. If you use
      this software in a product, an acknowledgment in the product
      documentation would be appreciated but is not required.

   2. Altered source versions must be plainly marked as such, and
      must not be misrepresented as being the original software.

   3. This notice may not be removed or altered from any source
      distribution.

   The original version of this class can be located at:
   http://irrlicht.suckerfreegames.com/

   John Norman
   john@suckerfreegames.com
*/

#ifndef __C_GUI_TTFONT_H_INCLUDED__
#define __C_GUI_TTFONT_H_INCLUDED__

#include <irrlicht.h>
#include <ft2build.h>
#include FT_FREETYPE_H

namespace irr
{
namespace gui
{
	struct SGUITTFace;
	class CGUITTFont;

	//! Class to assist in deleting glyphs.
	class CGUITTAssistDelete
	{
		public:
			template <class T, typename TAlloc>
			static void Delete(core::array<T, TAlloc>& a)
			{
				TAlloc allocator;
				allocator.deallocate(a.pointer());
			}
	};

	//! Structure representing a single TrueType glyph.
	struct SGUITTGlyph
	{
		//! Constructor.
		SGUITTGlyph() : isLoaded(false), glyph_page(0), surface(0), parent(0) {}

		//! Destructor.
		~SGUITTGlyph() { unload(); }

		//! Preload the glyph.
		//!	The preload process occurs when the program tries to cache the glyph from FT_Library.
		//! However, it simply defines the SGUITTGlyph's properties and will only create the page
		//! textures if necessary.  The actual creation of the textures should only occur right
		//! before the batch draw call.
		void preload(u32 char_index, FT_Face face, video::IVideoDriver* driver, u32 font_size, const FT_Int32 loadFlags);

		//! Unloads the glyph.
		void unload();

		//! Creates the IImage object from the FT_Bitmap.
		video::IImage* createGlyphImage(const FT_Bitmap& bits, video::IVideoDriver* driver) const;

		//! If true, the glyph has been loaded.
		bool isLoaded;

		//! The page the glyph is on.
		u32 glyph_page;

		//! The source rectangle for the glyph.
		core::recti source_rect;

		//! The offset of glyph when drawn.
		core::vector2di offset;

		//! Glyph advance information.
		FT_Vector advance;

		//! This is just the temporary image holder.  After this glyph is paged,
		//! it will be dropped.
		mutable video::IImage* surface;

		//! The pointer pointing to the parent (CGUITTFont)
		CGUITTFont* parent;
	};

	//! Holds a sheet of glyphs.
	class CGUITTGlyphPage
	{
		public:
			CGUITTGlyphPage(video::IVideoDriver* Driver, const io::path& texture_name) :texture(0), available_slots(0), used_slots(0), dirty(false), driver(Driver), name(texture_name) {}
			~CGUITTGlyphPage()
			{
				if (texture)
				{
					if (driver)
						driver->removeTexture(texture);
					else texture->drop();
				}
			}

			//! Create the actual page texture,
			bool createPageTexture(const u8& pixel_mode, const core::dimension2du& texture_size)
			{
				if( texture )
					return false;

				bool flgmip = driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
				driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);

				// Set the texture color format.
				switch (pixel_mode)
				{
					case FT_PIXEL_MODE_MONO:
						texture = driver->addTexture(texture_size, name, video::ECF_A1R5G5B5);
						break;
					case FT_PIXEL_MODE_GRAY:
					default:
						texture = driver->addTexture(texture_size, name, video::ECF_A8R8G8B8);
						break;
				}

				// Restore our texture creation flags.
				driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, flgmip);
				return texture ? true : false;
			}

			//! Add the glyph to a list of glyphs to be paged.
			//! This collection will be cleared after updateTexture is called.
			void pushGlyphToBePaged(const SGUITTGlyph* glyph)
			{
				glyph_to_be_paged.push_back(glyph);
			}

			//! Updates the texture atlas with new glyphs.
			void updateTexture()
			{
				if (!dirty) return;

				void* ptr = texture->lock();
				video::ECOLOR_FORMAT format = texture->getColorFormat();
				core::dimension2du size = texture->getOriginalSize();
				video::IImage* pageholder = driver->createImageFromData(format, size, ptr, true, false);

				for (u32 i = 0; i < glyph_to_be_paged.size(); ++i)
				{
					const SGUITTGlyph* glyph = glyph_to_be_paged[i];
					if (glyph && glyph->isLoaded)
					{
						if (glyph->surface)
						{
							glyph->surface->copyTo(pageholder, glyph->source_rect.UpperLeftCorner);
							glyph->surface->drop();
							glyph->surface = 0;
						}
						else
						{
							; // TODO: add error message?
							//currently, if we failed to create the image, just ignore this operation.
						}
					}
				}

				pageholder->drop();
				texture->unlock();
				glyph_to_be_paged.clear();
				dirty = false;
			}

			video::ITexture* texture;
			u32 available_slots;
			u32 used_slots;
			bool dirty;

			core::array<core::vector2di> render_positions;
			core::array<core::recti> render_source_rects;

		private:
			core::array<const SGUITTGlyph*> glyph_to_be_paged;
			video::IVideoDriver* driver;
			io::path name;
	};

	//! Class representing a TrueType font.
	class CGUITTFont : public IGUIFont
	{
		public:
			//! Creates a new TrueType font and returns a pointer to it.  The pointer must be drop()'ed when finished.
			//! \param env The IGUIEnvironment the font loads out of.
			//! \param filename The filename of the font.
			//! \param size The size of the font glyphs in pixels.  Since this is the size of the individual glyphs, the true height of the font may change depending on the characters used.
			//! \param antialias set the use_monochrome (opposite to antialias) flag
			//! \param transparency set the use_transparency flag
			//! \return Returns a pointer to a CGUITTFont.  Will return 0 if the font failed to load.
			static CGUITTFont* createTTFont(IGUIEnvironment *env, const io::path& filename, const u32 size, const bool antialias = true, const bool transparency = true);
			static CGUITTFont* createTTFont(IrrlichtDevice *device, const io::path& filename, const u32 size, const bool antialias = true, const bool transparency = true);
			static CGUITTFont* create(IGUIEnvironment *env, const io::path& filename, const u32 size, const bool antialias = true, const bool transparency = true);
			static CGUITTFont* create(IrrlichtDevice *device, const io::path& filename, const u32 size, const bool antialias = true, const bool transparency = true);

			//! Destructor
			virtual ~CGUITTFont();
span class="hl kwa">if (!(material_flags & MATERIAL_FLAG_TILEABLE_VERTICAL)) {
			material.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
			material.TextureLayer[1].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
		}
	}

	bool isTileable() const
	{
		return (material_flags & MATERIAL_FLAG_TILEABLE_HORIZONTAL)
			&& (material_flags & MATERIAL_FLAG_TILEABLE_VERTICAL);
	}

	// Ordered for size, please do not reorder

	video::ITexture *texture = nullptr;
	video::ITexture *normal_texture = nullptr;
	video::ITexture *flags_texture = nullptr;

	u32 shader_id = 0;

	u32 texture_id = 0;

	u16 animation_frame_length_ms = 0;
	u8 animation_frame_count = 1;

	u8 material_type = TILE_MATERIAL_BASIC;
	u8 material_flags =
		//0 // <- DEBUG, Use the one below
		MATERIAL_FLAG_BACKFACE_CULLING |
		MATERIAL_FLAG_TILEABLE_HORIZONTAL|
		MATERIAL_FLAG_TILEABLE_VERTICAL;

	//! If true, the tile has its own color.
	bool has_color = false;

	std::shared_ptr<std::vector<FrameSpec>> frames = nullptr;

	/*!
	 * The color of the tile, or if the tile does not own
	 * a color then the color of the node owning this tile.
	 */
	video::SColor color;

	u8 scale;
};

/*!
 * Defines a face of a node. May have up to two layers.
 */
struct TileSpec
{
	TileSpec() = default;

	/*!
	 * Returns true if this tile can be merged with the other tile.
	 */
	bool isTileable(const TileSpec &other) const {
		for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
			if (layers[layer] != other.layers[layer])
				return false;
			if (!layers[layer].isTileable())
				return false;
		}
		return rotation == 0
			&& rotation == other.rotation
			&& emissive_light == other.emissive_light;
	}

	//! If true, the tile rotation is ignored.
	bool world_aligned = false;
	//! Tile rotation.
	u8 rotation = 0;
	//! This much light does the tile emit.
	u8 emissive_light = 0;
	//! The first is base texture, the second is overlay.
	TileLayer layers[MAX_TILE_LAYERS];
};

std::vector<std::string> getTextureDirs();