// =========================================================================== // 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: July, 1998 // // Description: // This script contains code to create a sprite smoke effect // for Dynamics. It does so by creating an emitter, setting // appropriate attributes for the emitter and the emitted particles // (the smoke), and creating a turbulence field, if so specified that // is parented to the emitter and connected to the particle smoke. // // // ====================== spriteSmoke ====================== // // SYNOPSIS // Create a sprite smoke clip effect. // // INPUT ARGUMENTS // // string $imageName The name of the base image // int $startImage The first image frame to use // int $endImage The second image frame to use // int $cycleEnabled // float $minLifespan The minimum lifespan for a smoke particle. // float $maxLifespan The maximum lifespan for a smoke particle. // float $smokeThreshold Value for where we start tapering opacity. // float $smokeOpacity Overall scaling value for smoke's opacity. // int $useTurbulence // // Return Value: // string returnNames[] = // The names of the new emitter and turbulence field (if created). // global proc string [] spriteSmoke( string $particleName, string $emitterName, string $turbulenceName, string $imageName, int $startImage, int $endImage, int $cycleEnabled, float $minLifespan, float $maxLifespan, float $smokeThreshold, float $smokeOpacity, int $useTurbulence) { // To return the names of the created emitter and turbulence field, so the // attributes can be set. // string $returnNames[]; clear( $returnNames ); // Make sure the initial sprite image file exists. if not, return. // if (size($imageName) == 0) { warning( (uiRes("m_spriteSmoke.kSpriteFileMissing"))); clear($returnNames); return $returnNames; } // Commented out this well-meaning test because it returns error if // customer simply puts the images in "sourceimages" and puts the name // in the option box -- which is what the customer will expect to do // because that is how file textures work. Too complicated to check // all possible locations. js 4-12-99 // // if(!`filetest -r $imageName`) // { // warning("Could not find sprite file " + $imageName + " or it is not readable; sprite smoke effect was not created."); // clear($returnNames); // return $returnNames; // } // Make sure there is at most one item in the selection list. This // script requires that only one emitter be created. // string $selectedObjects[] = `ls -sl`; if (size($selectedObjects) > 1) { warning( (uiRes("m_spriteSmoke.kSpriteSomkeOnlyOne"))); clear($returnNames); return ($returnNames); } int $imageCount = $endImage-$startImage+1; // Create an emitter and a particle shape, and record the names of // the emitter and particle shape. // If there is something selected, the emitter will be added to it, // if it is a valid owner. If there is nothing selected a positional // emitter will be created at 0 0 0. If the owner is not valid, a // warning message will be posted and we will return. // string $result[]; int $failed = 0; string $emitter; $failed = catch( $result = `emitter -type direction -dx 0.0 -dy 1.0 -dz 0.0 -spread 0.1 -maxDistance 0 -minDistance 0 -rate 112.4 -speed 1.0`); if ($failed) { warning( (uiRes("m_spriteSmoke.kObjectCannotOwnEmitter"))); clear($returnNames); return $returnNames; } else { // Name the emitter and store the name // Emitter is selected following emitter command, // no matter whether it was created or added. // if (size($emitterName) > 0) { $emitter = `rename $emitterName`; } else { $emitter = `rename "SmokeEmitter#"`; } } // Make the particle shape. // We make it with default name now. This is so that we can easily // get both transform and shape name from the particle command. // We will need both to add dynamic attributes and expressions. // After all that's done, we'll rename the object. // $result = `particle`; string $particle = $result[0]; string $particleShape = $result[1]; // Connect the particle shape to the emitter. // connectDynamic -em $emitter $particleShape; // Set up to return the name of the emitter. // $returnNames[0] = $emitter; // Set sprite rendering attributes in the particle object // select -r $particleShape; setAttr ($particleShape+".particleRenderType") 5; addAttr -is true -ln "spriteTwist" -at "float" -min -180 -max 180 -dv 0.0 $particleShape; addAttr -is true -ln "spriteScaleX" -dv 1.0 $particleShape; addAttr -is true -ln "spriteScaleY" -dv 1.0 $particleShape; addAttr -is true -ln "spriteNum" -at long -dv 1 $particleShape; addAttr -is true -ln "useLighting" -at bool -dv false $particleShape; setAttr ($particleShape+".depthSort") 1; // Make a shader // string $lambert = `shadingNode -asShader lambert`; string $lambertSG = $lambert + "SG"; sets -renderable true -noSurfaceShader true -empty -name $lambertSG; connectAttr -f ($lambert+".outColor") ($lambertSG+".surfaceShader"); // Make a file texture. // string $fileTex = `shadingNode -asTexture file`; string $placeTex = `shadingNode -asUtility place2dTexture`; connectAttr -f ($placeTex+".coverage") ($fileTex+".coverage"); connectAttr -f ($placeTex+".translateFrame") ($fileTex+".translateFrame"); connectAttr -f ($placeTex+".rotateFrame") ($fileTex+".rotateFrame"); connectAttr -f ($placeTex+".mirrorU") ($fileTex+".mirrorU"); connectAttr -f ($placeTex+".mirrorV") ($fileTex+".mirrorV"); connectAttr -f ($placeTex+".stagger") ($fileTex+".stagger"); connectAttr -f ($placeTex+".wrapU") ($fileTex+".wrapU"); connectAttr -f ($placeTex+".wrapV") ($fileTex+".wrapV"); connectAttr -f ($placeTex+".repeatUV") ($fileTex+".repeatUV"); connectAttr -f ($placeTex+".offset") ($fileTex+".offset"); connectAttr -f ($placeTex+".rotateUV") ($fileTex+".rotateUV"); connectAttr -f ($placeTex+".noiseUV") ($fileTex+".noiseUV"); connectAttr -f ($placeTex+".vertexUvOne") ($fileTex+".vertexUvOne"); connectAttr -f ($placeTex+".vertexUvTwo") ($fileTex+".vertexUvTwo"); connectAttr -f ($placeTex+".vertexUvThree") ($fileTex+".vertexUvThree"); connectAttr -f ($placeTex+".vertexCameraOne") ($fileTex+".vertexCameraOne"); connectAttr ($placeTex+".outUV") ($fileTex+".uv"); connectAttr ($placeTex+".outUvFilterSize") ($fileTex+".uvFilterSize"); // Hook the file texture to the color // connectAttr -f ($fileTex+".outColor") ($lambert+".color"); // Assign the source image. // We use whatever is the default path. // Enable frame extension and hardware texture cycling. // setAttr -type "string" ($fileTex+".fileTextureName") $imageName; setAttr ($fileTex+".useFrameExtension") 1; setAttr ($fileTex+".useHardwareTextureCycling") 1; setAttr ($fileTex+".startCycleExtension") $startImage; setAttr ($fileTex+".endCycleExtension") $endImage; // Set expression on frameExtension to force file load and to reseed random stream. // string $exprString = "if (frame <= 1) seed(1);\n\nint $start = startCycleExtension;\nint $end = endCycleExtension;\nif (frame <= $end-$start+1)\n\tframeExtension = $start + frame - 1;\nelse\n\tframeExtension = $end;"; expression -s $exprString -o $fileTex -ae 1 -uc all ; // Assign the shader. // sets -e -forceElement $lambertSG $particle; // Add spriteNumPP and opacityPP attributes to the particle // and write expressions on them. // addAttr -ln "opacityPP" -dt doubleArray $particleShape; addAttr -ln "opacityPP0" -dt doubleArray $particleShape; addAttr -ln spriteNumPP -dt doubleArray $particleShape; addAttr -ln spriteNumPP0 -dt doubleArray $particleShape; // Set lifespan mode to use lifespan random range. // Prior to v3.0 this effect had "min lifespan" and "max lifespan" // controls. These were equivalent (though not identical) to // lifespan random range, so use the new method now. // setAttr ($particleShape+".lifespanMode") 2; // Set lifespan attributes according to min and max passed in. // float $avgLifespan = ($maxLifespan+$minLifespan)/ 2.0; setAttr ($particleShape+".lifespan") $avgLifespan; setAttr ($particleShape+".lifespanRandom") ($maxLifespan - $minLifespan); // Threshold value for where we start tapering opacity. // addAttr -ln smokeThreshold -at double -min 0.0 -max 1.0 $particleShape; setAttr -e -keyable true ($particleShape+".smokeThreshold"); setAttr ($particleShape+".smokeThreshold") $smokeThreshold; // Overall scaling value for smoke's opacity. // addAttr -ln smokeOpacity -at double -min 0.0 -max 1.0 $particleShape; setAttr -e -keyable true ($particleShape+".smokeOpacity"); setAttr ($particleShape+".smokeOpacity") $smokeOpacity; // Enable/disable cycling // addAttr -ln "cycleEnabled" -at bool $particleShape; setAttr -e -keyable true ($particleShape+".cycleEnabled"); setAttr ($particleShape+".cycleEnabled") $cycleEnabled; // Make the expressions // string $creationExprString = "spriteNumPP=rand(1)*"+ $imageCount +";\nopacityPP = 0.0;" ; dynExpression -s $creationExprString -c $particleShape; string $runtimeExprString; $runtimeExprString = "if ((cycleEnabled)&&(age/finalLifespanPP > smokeThreshold))\n{\n\tspriteNumPP=(age/finalLifespanPP)*"+$imageCount+"+1;\n}\n\nif (age/finalLifespanPP < smokeThreshold)\n{\n\topacityPP = smokeOpacity*age/finalLifespanPP;\n}\nelse\n{\n\topacityPP=smokeOpacity*(1-( (age-smokeThreshold)/(finalLifespanPP-smokeThreshold)));\n}" ; dynExpression -s $runtimeExprString -r $particleShape; // Make a turbulence field, if the user specifies to do so, to dissipate // the smoke further; parent it to the emitter and connect it to the // particle. // if ($useTurbulence) { $result = `turbulence -pos 0 0 0 -magnitude 0.2 -attenuation 2.8 -frequency 2.0 -phase 0 -maxDistance 2.0 `; string $turb; if (size($turbulenceName) > 0) { $turb = `rename $turbulenceName`; } else { $turb = `rename "SmokeTurbulence#"`; } move 0 4.05 0; parent $turb $emitter; connectDynamic -f $turb $particleShape; $returnNames[1] = $turb; } select -r $particle; if (size($particleName) > 0) { rename $particleName; } else { rename "SmokeParticle#"; } return $returnNames; } // ============ spriteSmokeSetEmissionAttributes ============ // // SYNOPSIS // Set emitter attributes for sprite smoke. // // INPUT ARGUMENTS // // string $emitterName name of the emitter // float $rate rate of emission // float $spread spread angle of emission // float $speed speed of emission // float $directionX direction of emission // float $directionY direction of emission // float $directionZ direction of emission // // global proc spriteSmokeSetEmissionAttributes( string $emitterName, float $rate, float $spread, float $speed, float $directionX, float $directionY, float $directionZ) { if (objExists($emitterName)) { setAttr ($emitterName+".rate") $rate; setAttr ($emitterName+".spread") $spread; setAttr ($emitterName+".speed") $speed; setAttr ($emitterName+".directionX") $directionX; setAttr ($emitterName+".directionY") $directionY; setAttr ($emitterName+".directionZ") $directionZ; } else { string $warnFormat = (uiRes("m_spriteSmoke.kEmitterNotExist")); string $warnMsg = `format -stringArg $emitterName $warnFormat`; warning $warnMsg; } } // ============ spriteSmokeSetTurbulenceAttributes ============ // // SYNOPSIS // Set turbulence attributes for sprite smoke. // // INPUT ARGUMENTS // // string $turbulenceName name of the turbulence field // float $magnitude magnitude of the turbulence field // float $frequency frequency of the turbulence field // float $attenuation attenuation of the turbulence field // // global proc spriteSmokeSetTurbulenceAttributes( string $turbulenceName, float $magnitude, float $frequency, float $attenuation) { if (objExists($turbulenceName)) { setAttr ($turbulenceName+".magnitude") $magnitude; setAttr ($turbulenceName+".frequency") $frequency; setAttr ($turbulenceName+".attenuation") $attenuation; } else { string $warnFormat = (uiRes("m_spriteSmoke.kTurbNotExist")); string $warnMsg = `format -stringArg $turbulenceName $warnFormat`; warning $warnMsg; } } // ============ defaultSpriteSmoke ============ // // SYNOPSIS // Create a default sprite smoke effect. // // INPUT ARGUMENTS // global proc defaultSpriteSmoke() { string $particleName = "Smoke"; string $emitterName = "SmokeEmitter"; string $turbulenceName = "SmokeTurbulence"; string $imageName = ""; int $startImage = 0; int $endImage = 9; int $cycleEnabled = 1; float $minLifespan = 3; float $maxLifespan = 7; float $smokeThreshold = .25; float $smokeOpacity = .4; int $useTurbulence = 1; spriteSmoke( "", "", "", "", 0, 9, 0, 3, 7, .25, .4, 1); }