@@ -88,47 +88,88 @@ void TileLayer::parse(const pugi::xml_node& node, Map*)
8888// private
8989void TileLayer::parseBase64 (const pugi::xml_node& node)
9090{
91- std::string data = node.text ().as_string ();
92- if (data.empty ())
91+ auto processDataString = [](std::string dataString, std::size_t tileCount, bool compressed)->std ::vector<std::uint32_t >
9392 {
94- Logger::log (" Layer " + getName () + " has no layer data. Layer skipped." , Logger::Type::Error);
95- return ;
96- }
93+ std::stringstream ss;
94+ ss << dataString;
95+ ss >> dataString;
96+ dataString = base64_decode (dataString);
97+
98+ std::size_t expectedSize = tileCount * 4 ; // 4 bytes per tile
99+ std::vector<unsigned char > byteData;
100+ byteData.reserve (expectedSize);
101+
102+ if (compressed)
103+ {
104+ // unzip
105+ std::size_t dataSize = dataString.length () * sizeof (unsigned char );
106+ if (!decompress (dataString.c_str (), byteData, dataSize, expectedSize))
107+ {
108+ LOG (" Failed to decompress layer data, node skipped." , Logger::Type::Error);
109+ return {};
110+ }
111+ }
112+ else
113+ {
114+ byteData.insert (byteData.end (), dataString.begin (), dataString.end ());
115+ }
116+
117+ // data stream is in bytes so we need to OR into 32 bit values
118+ std::vector<std::uint32_t > IDs;
119+ IDs.reserve (tileCount);
120+ for (auto i = 0u ; i < expectedSize - 3u ; i += 4u )
121+ {
122+ std::uint32_t id = byteData[i] | byteData[i + 1 ] << 8 | byteData[i + 2 ] << 16 | byteData[i + 3 ] << 24 ;
123+ IDs.push_back (id);
124+ }
97125
98- // using a string stream we can remove whitespace such as tabs
99- std::stringstream ss;
100- ss << data;
101- ss >> data;
102- data = base64_decode (data);
126+ return IDs;
127+ };
103128
104- std::size_t expectedSize = m_tileCount * 4 ; // 4 bytes per tile
105- std::vector<unsigned char > byteData;
106- byteData.reserve (expectedSize);
107129
108- if (node.attribute (" compression" ))
130+ std::string data = node.text ().as_string ();
131+ if (data.empty ())
109132 {
110- // unzip
111- std::size_t dataSize = data.length () * sizeof (unsigned char );
112- if (!decompress (data.c_str (), byteData, dataSize, expectedSize))
133+ // check for chunk nodes
134+ auto dataCount = 0 ;
135+ for (const auto & childNode : node.children ())
136+ {
137+ std::string childName = childNode.name ();
138+ if (childName == " chunk" )
139+ {
140+ std::string dataString = childNode.text ().as_string ();
141+ if (!dataString.empty ())
142+ {
143+ Chunk chunk;
144+ chunk.position .x = childNode.attribute (" x" ).as_int ();
145+ chunk.position .y = childNode.attribute (" y" ).as_int ();
146+
147+ chunk.size .x = childNode.attribute (" width" ).as_int ();
148+ chunk.size .y = childNode.attribute (" height" ).as_int ();
149+
150+ auto IDs = processDataString (dataString, (chunk.size .x * chunk.size .y ), node.attribute (" compression" ));
151+
152+ if (!IDs.empty ())
153+ {
154+ createTiles (IDs, chunk.tiles );
155+ m_chunks.push_back (chunk);
156+ dataCount++;
157+ }
158+ }
159+ }
160+ }
161+
162+ if (dataCount == 0 )
113163 {
114- LOG ( " Failed to decompress layer data, node skipped." , Logger::Type::Error);
164+ Logger::log ( " Layer " + getName () + " has no layer data. Layer skipped." , Logger::Type::Error);
115165 return ;
116166 }
117167 }
118168 else
119169 {
120- byteData.insert (byteData.end (), data.begin (), data.end ());
121- }
122-
123- // data stream is in bytes so whe need to OR into 32 bit values
124- std::vector<std::uint32_t > IDs;
125- IDs.reserve (m_tileCount);
126- for (auto i = 0u ; i < expectedSize - 3u ; i += 4u )
127- {
128- std::uint32_t id = byteData[i] | byteData[i + 1 ] << 8 | byteData[i + 2 ] << 16 | byteData[i + 3 ] << 24 ;
129- IDs.push_back (id);
170+ auto IDs = processDataString (data, m_tileCount, node.attribute (" compression" ));
171+ createTiles (IDs, m_tiles);
130172 }
131- createTiles (IDs);
132173}
133174
134175void TileLayer::parseCSV (const pugi::xml_node& node)
@@ -156,7 +197,7 @@ void TileLayer::parseCSV(const pugi::xml_node& node)
156197 }
157198 }
158199
159- createTiles (IDs);
200+ createTiles (IDs, m_tiles );
160201}
161202
162203void TileLayer::parseUnencoded (const pugi::xml_node& node)
@@ -174,19 +215,19 @@ void TileLayer::parseUnencoded(const pugi::xml_node& node)
174215 }
175216 }
176217
177- createTiles (IDs);
218+ createTiles (IDs, m_tiles );
178219}
179220
180- void TileLayer::createTiles (const std::vector<std::uint32_t >& IDs)
221+ void TileLayer::createTiles (const std::vector<std::uint32_t >& IDs, std::vector<Tile>& destination )
181222{
182223 // LOG(IDs.size() != m_tileCount, "Layer tile count does not match expected size. Found: "
183224 // + std::to_string(IDs.size()) + ", expected: " + std::to_string(m_tileCount));
184225
185226 static const std::uint32_t mask = 0xf0000000 ;
186227 for (const auto & id : IDs)
187228 {
188- m_tiles .emplace_back ();
189- m_tiles .back ().flipFlags = ((id & mask) >> 28 );
190- m_tiles .back ().ID = id & ~mask;
229+ destination .emplace_back ();
230+ destination .back ().flipFlags = ((id & mask) >> 28 );
231+ destination .back ().ID = id & ~mask;
191232 }
192233}
0 commit comments