// =========================================================================== // Copyright 2018 Autodesk, Inc. All rights reserved. // // Use of this software is subject to the terms of the Autodesk license // agreement provided at the time of installation or download, or which // otherwise accompanies this software in either electronic or hard copy form. // =========================================================================== // // // Creation Date: 20 Feb 2002 // // Description: // Create Fluids Playback + Render cache // // global proc setupActiveFluidPBCaches() { if( !`exists getActiveFluidShapes` ) { source "getFluidShape.mel"; } string $fluidShapes[] = `getActiveFluidShapes`; for( $fluid in $fluidShapes ) { setupFluidPBCache( $fluid ); } } global proc setupFluidPBCache( string $fluid) // // Description: // If there's not already a cache connected to the diskCache IC // create it, else clear the existing cache // make the cache writeable, save the fluid, and reset the // writeableness to its former state // { if( `connectionInfo -id ($fluid + ".diskCache")` == 0 ) { string $sel[] =`ls -sl`; createAndAttachFluidDiskCache( $fluid, "mcfp" ); select -r $sel; } } global int $gAskAddToCache = false; global proc doFluidsDiskCache( int $version, string $args[] ) // // Description: // // { global int $gAskAddToCache; if(( $version < 1 ) || ( size( $args ) < 10 )) { error (uiRes("m_doFluidsDiskCache.kArgumentError")); return; } $gAskAddToCache = true; doitFluidsDiskCache($version, $args); } global proc doitFluidsDiskCache( int $version, string $args[] ) // // Description: // // { string $cacheType = $args[0]; int $rangeMode = $args[1]; int $sampling = $args[2]; float $diskCacheStartTime = $args[3]; float $diskCacheEndTime = $args[4]; int $samplingRate = $args[5]; int $uiSettings[] = { int( $args[6]), // density $args[7], // velocity $args[8], // temperature $args[9], // reaction $args[10], // color $args[11], // texture coords $args[12] };// falloff int $doSegment = false; string $namingPrefix = ""; int $segmentSize = $diskCacheEndTime - $diskCacheStartTime; if(( $version >= 2 ) && (size( $args ) >=16) ) { $doSegment = $args[13]; $namingPrefix = $args[14]; $segmentSize = $args[15]; } float $startTime; float $endTime; if( $rangeMode == 1 ) { $startTime = `getAttr defaultRenderGlobals.startFrame`; $endTime = `getAttr defaultRenderGlobals.endFrame`; } else if( $rangeMode == 2 ) { $startTime = `playbackOptions -q -min`; $endTime = `playbackOptions -q -max`; } else { $startTime = $diskCacheStartTime; $endTime = $diskCacheEndTime; } if( $doSegment ) { doFluidsDiskCache_segment( $cacheType, $sampling, $startTime, $endTime, $samplingRate, $uiSettings, $namingPrefix, $segmentSize ); } else { doFluidsDiskCache_single( $cacheType, $sampling, $startTime, $endTime, $samplingRate, $uiSettings ); } } global proc doFluidsDiskCache_single( string $cacheType, int $sampling, float $start, float $end, int $samplingRate, int $uiSettings[] ) // // Description: // // { global int $gAskAddToCache; if( !`exists getActiveFluidShapes` ) { source "getFluidShape.mel"; } // Make sure that we have a fluid selected // or warn the user and fail // string $fluidShapes[] = getActiveFluidShapes(); if (size($fluidShapes) == 0) { warning (uiRes("m_doFluidsDiskCache.kFluidSelectionWarn")); return; } // If there is already a diskCache node for one of the // fluids, we really can't go about creating another // one until the user deletes the existing one. We'll // call this an error condition... // for( $f in $fluidShapes ) { int $numFrames = $end - $start + 1; int $cacheSize = fluidCacheSize( $f, $numFrames ); if( `fluidCacheInfo -q -playback -hasCache $f` ) { string $errorMsg = (uiRes("m_doFluidsDiskCache.kCreateCacheError")) ; error(`format -s $f $errorMsg`); break; } if( !fluidCacheSizeConfirm( $cacheSize ) ) { return; } } // make sure that we know where the Fluids Cache goes // verifyWorkspaceFileRule( "diskCache", "data" ); setupActiveFluidPBCaches; // Just to make sure either autoSave or the confirm box // kicks in if there might be data loss, before starting // to create the cache. // string $ctx = `currentCtx -q`; if( $ctx == "artFluidAttrContext" ) { artFluidAttrCtx -e -doAutoSave artFluidAttrContext; } if( !`exists fluidPlaybackCaches_disableUnselected` ) { source "fluidPlaybackCaches.mel"; } string $changedCaches[] = fluidPlaybackCaches_disableUnselected(); string $cmd; // do nothing if there is no diskCache string $allDiskCaches[] = `ls -type "diskCache"`; if( size($allDiskCaches) < 1 ) { string $msg = (uiRes("m_doFluidsDiskCache.kCacheWarning")); warning $msg; return; } // Verify all diskCache files have unique names int $n, $m; for($n = 1; $n < size($allDiskCaches); $n++) { string $cacheName = `getAttr ($allDiskCaches[$n] + ".cacheName")`; if( size($cacheName) == 0 ) $cacheName = `getAttr ($allDiskCaches[$n] + ".hiddenCacheName")`; for( $m = 0; $m < $n; $m++) { string $preCacheName = `getAttr ($allDiskCaches[$m] + ".cacheName")`; if( size($preCacheName) == 0 ) $prevCacheName = `getAttr ($allDiskCaches[$m] + ".hiddenCacheName")`; if( $cacheName == $preCacheName ) { string $msg = ( "Disk cache is not created because ^1s and ^2s have disk cache name conflict, and one of them has to be renamed." ); error (`format -s $allDiskCaches[$m] -s $allDiskCaches[$n] $msg`); return; } } } verifyWorkspaceFileRule( "diskCache", "data" ); string $samplingType = ""; if( $sampling == 1 ) { $samplingType = "-os"; } $cmd = "diskCache" + " -st " + $start + " -et " + $end + " " + $samplingType + " -ct " + $cacheType + " -sr " + $samplingRate; // Make sure the fluidShapes have their "what-to-cache" attrs // updated with the settings in the option vars. And then, make // sure we ony affect enabled cache nodes. // But only ask once if it's a segmented cache, and don't ask // at all if its batch or prompt if($gAskAddToCache) { string $addToCache = (uiRes("m_doFluidsDiskCache.kAddtoCache")); applyFluidDiskCacheOptions( $uiSettings, "Create Cache", $addToCache ); $gAskAddToCache = false; } eval( $cmd + " -enabledCachesOnly " ); fluidPlaybackCaches_enable( $changedCaches ); // Since it's the actual reading of the diskCache header // that sets the startTime and endTime attrs on the diskCache // node, we'll do a cacheInfo query for each fluid. // // This will force the initial attribute editor start/end // values to display correctly. // for( $f in $fluidShapes ) { if( `fluidCacheInfo -hasData -playback $f` ) { fluidCacheInfo -playback -startFrame $f; } } } global proc doFluidsDiskCache_segment( string $cacheType, int $sampling, float $start, float $end, int $samplingRate, int $uiSettings[], string $namingPrefix, int $segmentSize ) { global int $gAskAddToCache; if( !`exists getActiveFluidShapes` ) { source "getFluidShape.mel"; } string $fluids[] = getActiveFluidShapes(); if( size( $fluids ) > 1 ) { error( (uiRes("m_doFluidsDiskCache.kCreateSegmentationError")) ); return; } else if( size( $fluids ) == 0 ) { error( (uiRes("m_doFluidsDiskCache.kFluidSelectionError")) ); return; } if( $start > $end ) { error( (uiRes("m_doFluidsDiskCache.kSegmentStartTimeError")) ); return; } float $fluidStart = `getAttr ($fluids[0] + ".startFrame")`; if( $start < $fluidStart ) { error( (uiRes("m_doFluidsDiskCache.kSegmentFluidStartError")) ); return; } // at the moment, segmented caches do not support undersampling $sampling = 1; // The diskCache files that get created are named // according to the scene name that's already in effect. // (These get written to the project directory after // all.) If the user hasn't saved the scene yet, prompt // him to now. // string $title = (uiRes("m_doFluidsDiskCache.kCreateCacheWarning")); string $cancel = (uiRes("m_doFluidsDiskCache.kCancel")); string $defaultFileName = untitledFileName(); if( $namingPrefix == $defaultFileName ) { string $msg = (uiRes("m_doFluidsDiskCache.kFrameMessage")) ; string $saveScene = (uiRes("m_doFluidsDiskCache.kSaveScene")); string $lastChance = `confirmDialog -title $title -message $msg -messageAlign "left" -button $saveScene -button $cancel -defaultButton $saveScene -cancelButton $cancel -dismissString $cancel`; int $goAhead = ( $lastChance == $saveScene ); if( $goAhead ) { SaveScene; string $scene = `file -q -sceneName`; $namingPrefix = `basename $scene ""`; if( size( $namingPrefix ) == 0 ) { $namingPrefix = $defaultFileName; } } if(( size( $namingPrefix ) == 0 ) || ( $namingPrefix == $defaultFileName ) ) { return; } } int $cacheSize = fluidCacheSize( $fluids[0], $segmentSize ); if( !fluidCacheSizeConfirm( $cacheSize ) ) { return; } // This operation isn't interruptable... Yikes, this could // get annoying, so let's only offer an out if they're caching // 10 frames or more... // if(( $end - $start ) > 10 && $gAskAddToCache ) { string $msg = (uiRes("m_doFluidsDiskCache.kOperationMessage")); string $continue =(uiRes("m_doFluidsDiskCache.kContinue")); string $lastChance = `confirmDialog -title $title -message $msg -messageAlign "left" -button $continue -button $cancel -defaultButton $continue -cancelButton $cancel -dismissString $cancel`; int $goAhead = ( $lastChance == $continue ); if( !$goAhead ) { return; } } string $cache; string $tmpDir = `diskCache -q -tempDir`; verifyWorkspaceFileRule( "diskCache", "data" ); string $diskCacheDir = ( `workspace -q -rootDirectory` + `workspace -fileRuleEntry "diskCache"` ); int $density = $uiSettings[0]; int $velocity = $uiSettings[1]; int $temperature = $uiSettings[2]; int $reaction = $uiSettings[3]; int $color = $uiSettings[4]; int $texture = $uiSettings[5]; int $falloff = $uiSettings[6]; int $createdAnimCurve = false; string $animCurve; int $dontAskOverwrite = false; int $i; for( $i = $start; $i <= $end; $i += $segmentSize ) { string $origNames[]; int $j = 0; int $endOfSegment = $i + $segmentSize - 1; if( $endOfSegment > $end ) { $endOfSegment = $end; } doitFluidsDiskCache( 1, { "mcfp", 3, $sampling, $i, $endOfSegment, $samplingRate, $density, $velocity, $temperature, $reaction, $color, $texture, $density } ); currentTime $endOfSegment; $cache = fluidPlaybackCacheName( $fluids[0] ); // Segmented caches need dynamic attributes on the cache node. // addAttr -ln "segmentStartFrame" -sn "ssf" -at long -dv 0 $cache; string $hid = `getAttr ($cache + ".hiddenCacheName")`; string $seg = fluidCacheSegmentizeName( $cache, $i, $namingPrefix ); string $fullPath = ( $diskCacheDir + "/" + $seg ); int $goAhead = true; // Check to make sure we don't overwrite files in the user's // project area. // if( !$dontAskOverwrite && `filetest -f $fullPath` ) { string $fmt = (uiRes("m_doFluidsDiskCache.kCacheMessage")); string $msg = `format -s $fullPath $fmt`; string $overwriteAll = (uiRes("m_doFluidsDiskCache.kOverwriteAll")); string $lastChance = `confirmDialog -title $title -message $msg -messageAlign "left" -button $overwriteAll -button $cancel -defaultButton $cancel -cancelButton $cancel -dismissString $cancel`; if( $lastChance == $overwriteAll ) { $dontAskOverwrite = true; } $goAhead = ( $lastChance != $cancel ); } if( !$goAhead ) { DeleteFluidCache; $cache = ""; return; } eval ( "sysFile -cp \"" + $diskCacheDir + "/" + $seg + "\" \"" + $tmpDir + "/" + $hid + "\"" ); if( !$createdAnimCurve && ( size( $cache ) > 0 )) { string $prevSel[] = `ls -sl`; $animCurve = `createNode animCurveTU`; select $prevSel; $createdAnimCurve = true; } if( $createdAnimCurve && ($segmentSize != 0) ) { int $num = $start + $segmentSize * (int( ($i-$start)/$segmentSize )); setKeyframe -ott step -t $i -v $num $animCurve; } // Don't delete the last time, so we can keep the cache // around to hook up the expression that will update // the cacheName values when time changes. // if( $endOfSegment != $end ) { DeleteFluidCache; } } // Hook the expression node up to change the active // filename segment based on time. // if( size( $cache ) > 0 ) { string $expression = ( "updateCacheSegmentAtCurrentTime " + $cache + " " + $namingPrefix ); string $expNode = `expression -ae true -s $expression -name ($namingPrefix + "_currentSegment")`; addAttr -ln "segmentStartFrame" -sn "ssf" -at long -dv 0 $expNode; // We don't really need to hook things up like this // for evaluation purposes, but it helps for deleting // the expression and animCurve when the fluid is deleted. // connectAttr ($animCurve + ".output") ($expNode + ".segmentStartFrame"); connectAttr ($expNode + ".segmentStartFrame") ($cache + ".segmentStartFrame"); } currentTime $start; }