| 188 | } // namespace ObjectSave |
| 189 | |
| 190 | Expected<void> serializeObjectTree( const Object& object, const std::filesystem::path& path, |
| 191 | FolderCallback preCompress, const SceneSave::Settings& settings ) |
| 192 | { |
| 193 | MR_TIMER; |
| 194 | if (path.empty()) |
| 195 | return unexpected( "Cannot save to empty path" ); |
| 196 | |
| 197 | UniqueTemporaryFolder scenePath; |
| 198 | if ( !scenePath ) |
| 199 | return unexpected( "Cannot create temporary folder" ); |
| 200 | |
| 201 | if ( !reportProgress( settings.progress, 0.0f ) ) |
| 202 | return unexpectedOperationCanceled(); |
| 203 | |
| 204 | Json::Value root; |
| 205 | root["FormatVersion"] = 1.0; |
| 206 | if ( settings.lengthUnit ) |
| 207 | root["LengthUnits"] = std::string( getUnitInfo( *settings.lengthUnit ).prettyName ); |
| 208 | auto expectedSaveModelFutures = object.serializeRecursive( scenePath, root, 0 ); |
| 209 | if ( !expectedSaveModelFutures.has_value() ) |
| 210 | return unexpected( expectedSaveModelFutures.error() ); |
| 211 | auto & saveModelFutures = expectedSaveModelFutures.value(); |
| 212 | |
| 213 | assert( !object.name().empty() ); |
| 214 | auto paramsFile = scenePath / asU8String( object.name() + ".json" ); |
| 215 | if ( !serializeJsonValue( root, paramsFile ) ) |
| 216 | return unexpected( "Cannot write parameters " + utf8string( paramsFile ) ); |
| 217 | |
| 218 | #ifndef __EMSCRIPTEN__ |
| 219 | if ( !reportProgress( settings.progress, 0.1f ) ) |
| 220 | return unexpectedOperationCanceled(); |
| 221 | |
| 222 | // wait for all models are saved before making compressed folder |
| 223 | BitSet inProgress( saveModelFutures.size(), true ); |
| 224 | while ( inProgress.any() ) |
| 225 | { |
| 226 | for ( auto i : inProgress ) |
| 227 | { |
| 228 | if ( saveModelFutures[i].wait_for( std::chrono::milliseconds( 200 ) ) != std::future_status::timeout ) |
| 229 | inProgress.reset( i ); |
| 230 | } |
| 231 | if ( !reportProgress( subprogress( settings.progress, 0.1f, 0.9f ), 1.0f - (float)inProgress.count() / inProgress.size() ) ) |
| 232 | return unexpectedOperationCanceled(); |
| 233 | } |
| 234 | #endif |
| 235 | |
| 236 | for ( auto & f : saveModelFutures ) |
| 237 | { |
| 238 | auto v = f.get(); |
| 239 | if ( !v ) |
| 240 | return v; |
| 241 | } |
| 242 | |
| 243 | if ( preCompress ) |
| 244 | preCompress( scenePath ); |
| 245 | |
| 246 | return compressZip( path, scenePath, { .cb = subprogress( settings.progress, 0.9f, 1.0f ) } ); |
| 247 | } |