| 203 | } |
| 204 | |
| 205 | static ScanResult AnalyzeItem(const ScanItem& item) |
| 206 | { |
| 207 | ScanResult result; |
| 208 | result.path = item.pboPath.empty() ? item.path : (item.pboPath + "#" + item.entryName); |
| 209 | result.category = item.category; |
| 210 | result.size = item.size; |
| 211 | |
| 212 | try |
| 213 | { |
| 214 | std::string tempPath; |
| 215 | std::string filePath = item.path; |
| 216 | |
| 217 | if (!item.pboPath.empty()) |
| 218 | { |
| 219 | if (item.size == 0) |
| 220 | { |
| 221 | result.formatDetail = "0 B"; |
| 222 | result.success = true; |
| 223 | return result; |
| 224 | } |
| 225 | auto data = ExtractPboEntry(item.pboPath, item.entryName); |
| 226 | if (data.empty()) |
| 227 | { |
| 228 | result.error = "Failed to extract from PBO"; |
| 229 | return result; |
| 230 | } |
| 231 | tempPath = WriteTempFile(data, item.extension); |
| 232 | if (tempPath.empty()) |
| 233 | { |
| 234 | result.error = "Failed to write temp file"; |
| 235 | return result; |
| 236 | } |
| 237 | filePath = tempPath; |
| 238 | } |
| 239 | switch (item.category) |
| 240 | { |
| 241 | case FileCategory::Model: |
| 242 | { |
| 243 | Poseidon::ModelInfo info; |
| 244 | { |
| 245 | std::lock_guard<std::mutex> lock(g_engineMutex); |
| 246 | info = Poseidon::InspectModel(filePath); |
| 247 | } |
| 248 | if (info.valid) |
| 249 | { |
| 250 | int totalVerts = 0; |
| 251 | for (const auto& lod : info.lods) |
| 252 | totalVerts += lod.points; |
| 253 | result.formatDetail = info.format + " v" + std::to_string(info.version) + " " + |
| 254 | std::to_string(info.lodCount) + " LODs " + std::to_string(totalVerts) + |
| 255 | " verts"; |
| 256 | result.success = true; |
| 257 | } |
| 258 | else |
| 259 | { |
| 260 | result.error = info.errorMessage.empty() ? "Parse failed" : info.errorMessage; |
| 261 | } |
| 262 | break; |
no test coverage detected