13
13
*/
14
14
#include < gk/core/Exception.hpp>
15
15
16
+ #include " Registry.hpp"
16
17
#include " TextureAtlas.hpp"
17
18
18
- void TextureAtlas::addFile (const std::string &filename) {
19
- SurfacePtr surface{IMG_Load (filename.c_str ()), &SDL_FreeSurface};
20
- if (!surface) {
21
- throw EXCEPTION (" Failed to load texture:" , filename);
22
- }
19
+ void TextureAtlas::addFile (const std::string &path, const std::string &filename) {
20
+ auto it = m_textureMap.find (filename);
21
+ if (it != m_textureMap.end ())
22
+ return ;
23
23
24
- auto it = m_textures.find (filename);
25
- if (it != m_textures.end ()) {
26
- throw EXCEPTION (" Texture already exists in atlas:" , filename);
27
- }
24
+ SurfacePtr surface{IMG_Load ((path + filename).c_str ()), &SDL_FreeSurface};
25
+ if (!surface)
26
+ throw EXCEPTION (" Failed to load texture:" , path + filename);
28
27
29
- if (!m_width && !m_height) {
30
- m_width = surface->w ;
31
- m_height = surface->h ;
32
- }
33
- else if (m_width != surface->w || m_height != surface->h ) {
34
- throw EXCEPTION (" Texture size unexpected for" , filename + " . Got" , surface->w , surface->w , " instead of" , m_width, m_height);
35
- }
28
+ if (!m_tileSize)
29
+ m_tileSize = surface->w ;
30
+
31
+ if (m_tileSize != surface->w || m_tileSize != surface->h )
32
+ throw EXCEPTION (" Texture size unexpected for" , path + filename + " . Got" , surface->w , surface->w , " instead of" , m_tileSize, m_tileSize);
36
33
37
- m_textures.emplace (filename, std::move (surface));
34
+ m_textureMap.emplace (filename, m_textures.size ());
35
+ m_textures.emplace_back (std::move (surface));
38
36
}
39
37
40
38
void TextureAtlas::packTextures () {
41
- if (!m_width && !m_height) {
39
+ if (!m_tileSize)
42
40
throw EXCEPTION (" Cannot pack zero-sized textures!" );
43
- }
41
+
42
+ SurfacePtr atlas{nullptr , &SDL_FreeSurface};
44
43
45
44
// Max amount of textures on one line
46
45
const u16 atlasWidth = 16 ;
47
46
48
47
// Max amount of textures on one column
49
- const u16 atlasHeight = m_textures.size () / atlasWidth;
48
+ const u16 atlasHeight = std::ceil (( float ) m_textures.size () / atlasWidth) ;
50
49
51
50
Uint32 rmask, gmask, bmask, amask;
52
51
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
@@ -61,36 +60,49 @@ void TextureAtlas::packTextures() {
61
60
amask = 0xff000000 ;
62
61
#endif
63
62
64
- m_atlas .reset (SDL_CreateRGBSurface (0 , atlasWidth * m_width , atlasHeight * m_height , 32 , rmask, gmask, bmask, amask));
65
- if (!m_atlas ) {
63
+ atlas .reset (SDL_CreateRGBSurface (0 , atlasWidth * m_tileSize , atlasHeight * m_tileSize , 32 , rmask, gmask, bmask, amask));
64
+ if (!atlas ) {
66
65
throw EXCEPTION (" Failed to create surface:" , SDL_GetError ());
67
66
}
68
67
69
68
u16 i = 0 ;
70
69
for (auto &it : m_textures) {
71
70
SDL_Rect outRect;
72
- outRect.x = (i % atlasWidth) * m_width;
73
- outRect.y = (i / atlasWidth) * m_height;
74
- outRect.w = m_width;
75
- outRect.h = m_height;
76
-
77
- SDL_BlitSurface (it.second .get (), nullptr , m_atlas.get (), &outRect);
71
+ outRect.x = (i % atlasWidth) * m_tileSize;
72
+ outRect.y = (i / atlasWidth) * m_tileSize;
73
+ outRect.w = m_tileSize;
74
+ outRect.h = m_tileSize;
78
75
79
- m_textureMap. emplace (it.first , i );
76
+ SDL_BlitSurface (it.get (), nullptr , atlas. get (), &outRect );
80
77
81
78
++i;
82
79
}
83
80
84
81
m_textures.clear ();
82
+
83
+ m_isReady = true ;
84
+
85
+ if (IMG_SavePNG (atlas.get (), " test_atlas.png" ) < 0 )
86
+ throw EXCEPTION (" Failed to save texture to: test_altas.png. Reason:" , SDL_GetError ());
87
+
88
+ m_texture.loadFromSurface (atlas.get ());
85
89
}
86
90
87
- void TextureAtlas::saveToFile (const std::string &filename) {
88
- if (IMG_SavePNG (m_atlas.get (), filename.c_str ()) < 0 ) {
89
- throw EXCEPTION (" Failed to save texture to:" , filename + " . Reason:" , SDL_GetError ());
91
+ void TextureAtlas::loadFromRegistry () {
92
+ for (auto &block : Registry::getInstance ().blocks ()) {
93
+ if (!block->textureFilename ().empty ())
94
+ addFile (" resources/textures/faithful32/blocks/" , block->textureFilename ());
95
+ }
96
+
97
+ for (auto &item : Registry::getInstance ().items ()) {
98
+ if (!item.textureFilename ().empty () && !item.isBlock ())
99
+ addFile (" resources/textures/faithful32/items/" , item.textureFilename ());
90
100
}
101
+
102
+ packTextures ();
91
103
}
92
104
93
- u16 TextureAtlas::getTextureID (const std::string &filename) {
105
+ u16 TextureAtlas::getTextureID (const std::string &filename) const {
94
106
auto it = m_textureMap.find (filename);
95
107
if (it == m_textureMap.end ()) {
96
108
throw EXCEPTION (" Unable to find texture in atlas:" , filename);
@@ -99,3 +111,26 @@ u16 TextureAtlas::getTextureID(const std::string &filename) {
99
111
return it->second ;
100
112
}
101
113
114
+ gk::FloatRect TextureAtlas::getTexCoords (const std::string &filename, bool normalized) const {
115
+ if (filename.empty ()) return gk::FloatRect{0 , 0 , 0 , 0 };
116
+
117
+ if (!m_isReady)
118
+ throw EXCEPTION (" Can't get texture coordinates from empty atlas" );
119
+
120
+ u16 textureID = getTextureID (filename);
121
+
122
+ float textureX = (textureID % (m_texture.getSize ().x / m_tileSize)) * m_tileSize;
123
+ float textureY = (textureID / (m_texture.getSize ().x / m_tileSize)) * m_tileSize;
124
+
125
+ if (normalized)
126
+ return gk::FloatRect{textureX / m_texture.getSize ().x ,
127
+ textureY / m_texture.getSize ().y ,
128
+ (float )m_tileSize / m_texture.getSize ().x ,
129
+ (float )m_tileSize / m_texture.getSize ().y };
130
+ else
131
+ return gk::FloatRect{textureX,
132
+ textureY,
133
+ (float )m_tileSize,
134
+ (float )m_tileSize};
135
+ }
136
+
0 commit comments