| 220 | #if USE_EDITOR |
| 221 | |
| 222 | bool ModelBase::Save(bool withMeshDataFromGpu, const StringView& path) |
| 223 | { |
| 224 | // Validate state |
| 225 | if (OnCheckSave(path)) |
| 226 | return true; |
| 227 | if (withMeshDataFromGpu && IsInMainThread()) |
| 228 | { |
| 229 | LOG(Error, "To save model with GPU mesh buffers it needs to be called from the other thread (not the main thread)."); |
| 230 | return true; |
| 231 | } |
| 232 | if (IsVirtual() && !withMeshDataFromGpu) |
| 233 | { |
| 234 | LOG(Error, "To save virtual model asset you need to specify 'withMeshDataFromGpu' (it has no other storage container to get data)."); |
| 235 | return true; |
| 236 | } |
| 237 | auto chunkLocks = Storage ? Storage->Lock() : FlaxStorage::LockData(); |
| 238 | ScopeLock lock(Locker); |
| 239 | |
| 240 | // Use a temporary chunks for data storage for virtual assets |
| 241 | FlaxChunk* tmpChunks[ASSET_FILE_DATA_CHUNKS]; |
| 242 | Platform::MemoryClear(tmpChunks, sizeof(tmpChunks)); |
| 243 | Array<FlaxChunk> chunks; |
| 244 | if (IsVirtual()) |
| 245 | chunks.Resize(ASSET_FILE_DATA_CHUNKS); |
| 246 | Function<FlaxChunk*(int32)> getChunk = [&](int32 index) -> FlaxChunk* { |
| 247 | return IsVirtual() ? tmpChunks[index] = &chunks[index] : GetOrCreateChunk(index); |
| 248 | }; |
| 249 | |
| 250 | // Save LODs data |
| 251 | const int32 lodsCount = GetLODsCount(); |
| 252 | if (withMeshDataFromGpu) |
| 253 | { |
| 254 | // Fetch runtime mesh data (from GPU) |
| 255 | MemoryWriteStream meshesStream; |
| 256 | for (int32 lodIndex = 0; lodIndex < lodsCount; lodIndex++) |
| 257 | { |
| 258 | meshesStream.SetPosition(0); |
| 259 | if (SaveLOD(meshesStream, lodIndex)) |
| 260 | return true; |
| 261 | auto lodChunk = getChunk(MODEL_LOD_TO_CHUNK_INDEX(lodIndex)); |
| 262 | if (lodChunk == nullptr) |
| 263 | return true; |
| 264 | lodChunk->Data.Copy(ToSpan(meshesStream)); |
| 265 | } |
| 266 | } |
| 267 | else if (!IsVirtual()) |
| 268 | { |
| 269 | // Load all chunks with a mesh data |
| 270 | for (int32 lodIndex = 0; lodIndex < lodsCount; lodIndex++) |
| 271 | { |
| 272 | if (LoadChunk(MODEL_LOD_TO_CHUNK_INDEX(lodIndex))) |
| 273 | return true; |
| 274 | } |
| 275 | } |
| 276 | |
| 277 | // Save custom data |
| 278 | if (Save(withMeshDataFromGpu, getChunk)) |
| 279 | return true; |
nothing calls this directly
no test coverage detected