Otclient  14/8/2020
spritemanager.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2020 OTClient <https://github.com/edubart/otclient>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  * THE SOFTWARE.
21  */
22 
23 #include "spritemanager.h"
24 #include "game.h"
28 
30 
32 {
33  m_spritesCount = 0;
34  m_signature = 0;
35 }
36 
38 {
39  unload();
40 }
41 
42 bool SpriteManager::loadSpr(std::string file)
43 {
44  m_spritesCount = 0;
45  m_signature = 0;
46  m_loaded = false;
47  try {
48  file = g_resources.guessFilePath(file, "spr");
49 
50  m_spritesFile = g_resources.openFile(file);
51  // cache file buffer to avoid lags from hard drive
52  m_spritesFile->cache();
53 
54  m_signature = m_spritesFile->getU32();
55  m_spritesCount = g_game.getFeature(Otc::GameSpritesU32) ? m_spritesFile->getU32() : m_spritesFile->getU16();
56  m_spritesOffset = m_spritesFile->tell();
57  m_loaded = true;
58  g_lua.callGlobalField("g_sprites", "onLoadSpr", file);
59  return true;
60  } catch(stdext::exception& e) {
61  g_logger.error(stdext::format("Failed to load sprites from '%s': %s", file, e.what()));
62  return false;
63  }
64 }
65 
66 void SpriteManager::saveSpr(std::string fileName)
67 {
68  if(!m_loaded)
69  stdext::throw_exception("failed to save, spr is not loaded");
70 
71  try {
72  FileStreamPtr fin = g_resources.createFile(fileName);
73  if(!fin)
74  stdext::throw_exception(stdext::format("failed to open file '%s' for write", fileName));
75 
76  fin->cache();
77 
78  fin->addU32(m_signature);
80  fin->addU32(m_spritesCount);
81  else
82  fin->addU16(m_spritesCount);
83 
84  uint32 offset = fin->tell();
85  uint32 spriteAddress = offset + 4 * m_spritesCount;
86  for(int i = 1; i <= m_spritesCount; i++)
87  fin->addU32(0);
88 
89  for(int i = 1; i <= m_spritesCount; i++) {
90  m_spritesFile->seek((i - 1) * 4 + m_spritesOffset);
91  uint32 fromAdress = m_spritesFile->getU32();
92  if(fromAdress != 0) {
93  fin->seek(offset + (i - 1) * 4);
94  fin->addU32(spriteAddress);
95  fin->seek(spriteAddress);
96 
97  m_spritesFile->seek(fromAdress);
98  fin->addU8(m_spritesFile->getU8());
99  fin->addU8(m_spritesFile->getU8());
100  fin->addU8(m_spritesFile->getU8());
101 
102  uint16 dataSize = m_spritesFile->getU16();
103  fin->addU16(dataSize);
104  char spriteData[SPRITE_DATA_SIZE];
105  m_spritesFile->read(spriteData, dataSize);
106  fin->write(spriteData, dataSize);
107 
108  spriteAddress = fin->tell();
109  }
110  //TODO: Check for overwritten sprites.
111  }
112 
113  fin->flush();
114  fin->close();
115  } catch(std::exception& e) {
116  g_logger.error(stdext::format("Failed to save '%s': %s", fileName, e.what()));
117  }
118 }
119 
121 {
122  m_spritesCount = 0;
123  m_signature = 0;
124  m_spritesFile = nullptr;
125 }
126 
128 {
129  try {
130 
131  if(id == 0 || !m_spritesFile)
132  return nullptr;
133 
134  m_spritesFile->seek(((id-1) * 4) + m_spritesOffset);
135 
136  uint32 spriteAddress = m_spritesFile->getU32();
137 
138  // no sprite? return an empty texture
139  if(spriteAddress == 0)
140  return nullptr;
141 
142  m_spritesFile->seek(spriteAddress);
143 
144  // skip color key
145  m_spritesFile->getU8();
146  m_spritesFile->getU8();
147  m_spritesFile->getU8();
148 
149  uint16 pixelDataSize = m_spritesFile->getU16();
150 
151  ImagePtr image(new Image(Size(SPRITE_SIZE, SPRITE_SIZE)));
152 
153  uint8 *pixels = image->getPixelData();
154  int writePos = 0;
155  int read = 0;
157  uint8 channels = useAlpha ? 4 : 3;
158 
159  // decompress pixels
160  while(read < pixelDataSize && writePos < SPRITE_DATA_SIZE) {
161  uint16 transparentPixels = m_spritesFile->getU16();
162  uint16 coloredPixels = m_spritesFile->getU16();
163 
164  for(int i = 0; i < transparentPixels && writePos < SPRITE_DATA_SIZE; i++) {
165  pixels[writePos + 0] = 0x00;
166  pixels[writePos + 1] = 0x00;
167  pixels[writePos + 2] = 0x00;
168  pixels[writePos + 3] = 0x00;
169  writePos += 4;
170  }
171 
172  for(int i = 0; i < coloredPixels && writePos < SPRITE_DATA_SIZE; i++) {
173  pixels[writePos + 0] = m_spritesFile->getU8();
174  pixels[writePos + 1] = m_spritesFile->getU8();
175  pixels[writePos + 2] = m_spritesFile->getU8();
176  pixels[writePos + 3] = useAlpha ? m_spritesFile->getU8() : 0xFF;
177  writePos += 4;
178  }
179 
180  read += 4 + (channels * coloredPixels);
181  }
182 
183  // fill remaining pixels with alpha
184  while(writePos < SPRITE_DATA_SIZE) {
185  pixels[writePos + 0] = 0x00;
186  pixels[writePos + 1] = 0x00;
187  pixels[writePos + 2] = 0x00;
188  pixels[writePos + 3] = 0x00;
189  writePos += 4;
190  }
191 
192  return image;
193  } catch(stdext::exception& e) {
194  g_logger.error(stdext::format("Failed to get sprite id %d: %s", id, e.what()));
195  return nullptr;
196  }
197 }
198 
FileStream::write
void write(const void *buffer, uint count)
Definition: filestream.cpp:130
FileStream::seek
void seek(uint pos)
Definition: filestream.cpp:142
FileStream::close
void close()
Definition: filestream.cpp:78
FileStream::addU32
void addU32(uint32 v)
Definition: filestream.cpp:377
Otc::GameSpritesAlphaChannel
@ GameSpritesAlphaChannel
Definition: const.h:399
uint32
uint32_t uint32
Definition: types.h:35
LuaInterface::callGlobalField
void callGlobalField(const std::string &global, const std::string &field, const T &... args)
Definition: luainterface.h:445
resourcemanager.h
Logger::error
void error(const std::string &what)
Definition: logger.h:54
g_game
Game g_game
Definition: game.cpp:37
SpriteManager::getSpriteImage
ImagePtr getSpriteImage(int id)
Definition: spritemanager.cpp:127
stdext::format
std::string format()
Definition: format.h:82
uint16
uint16_t uint16
Definition: types.h:36
Otc::GameSpritesU32
@ GameSpritesU32
Definition: const.h:363
Image
Definition: image.h:29
g_resources
ResourceManager g_resources
Definition: resourcemanager.cpp:32
SpriteManager::SpriteManager
SpriteManager()
Definition: spritemanager.cpp:31
FileStream::cache
void cache()
Definition: filestream.cpp:58
FileStream::getU16
uint16 getU16()
Definition: filestream.cpp:199
g_sprites
SpriteManager g_sprites
Definition: spritemanager.cpp:29
g_logger
Logger g_logger
Definition: logger.cpp:35
spritemanager.h
g_lua
LuaInterface g_lua
Definition: luainterface.cpp:31
image.h
SpriteManager::saveSpr
void saveSpr(std::string fileName)
Definition: spritemanager.cpp:66
Size
TSize< int > Size
Definition: size.h:107
Game::getFeature
bool getFeature(Otc::GameFeature feature)
Definition: game.h:310
FileStream::read
int read(void *buffer, uint size, uint nmemb=1)
Definition: filestream.cpp:109
stdext::throw_exception
void throw_exception(const std::string &what)
Throws a generic exception.
Definition: exception.h:43
ResourceManager::openFile
FileStreamPtr openFile(const std::string &fileName)
Definition: resourcemanager.cpp:232
filestream.h
stdext::exception::what
virtual const char * what() const
Definition: exception.h:37
FileStream::tell
uint tell()
Definition: filestream.cpp:167
stdext::shared_object_ptr< FileStream >
SpriteManager
Definition: spritemanager.h:30
SpriteManager::terminate
void terminate()
Definition: spritemanager.cpp:37
FileStream::getU32
uint32 getU32()
Definition: filestream.cpp:215
FileStream::flush
void flush()
Definition: filestream.cpp:90
game.h
FileStream::addU8
void addU8(uint8 v)
Definition: filestream.cpp:354
SpriteManager::loadSpr
bool loadSpr(std::string file)
Definition: spritemanager.cpp:42
ResourceManager::createFile
FileStreamPtr createFile(const std::string &fileName)
Definition: resourcemanager.cpp:250
SpriteManager::unload
void unload()
Definition: spritemanager.cpp:120
FileStream::getU8
uint8 getU8()
Definition: filestream.cpp:183
uint8
uint8_t uint8
Definition: types.h:37
ResourceManager::guessFilePath
std::string guessFilePath(const std::string &filename, const std::string &type)
Definition: resourcemanager.cpp:352
FileStream::addU16
void addU16(uint16 v)
Definition: filestream.cpp:365
stdext::exception
Definition: exception.h:31