try(destroydialog pf_spliner)catch() rollout pf_spliner "PF Spliner 3.5" width:150 height:298 ( -- Forward function declerations -------------------------------------------------------------------- local pf_filt local invertMaskBitmap -- Local variable declerations -------------------------------------------------------------------- local source local f_start local f_end local increments local threshold local pf_particles = #() local pf_shapes = #() local pf_ConnectTheDotsShapes = #() local lastpos = #() local arrowIcon = getDir #ui + "\icons\MergeAnim_24i.bmp" local arrowIconAlpha = invertMaskBitmap (openBitmap (getDir #ui + "\icons\MergeAnim_24i.bmp")) -- User Interface --------------------------------------------------------------------- pickbutton btn_pick "Pick Particle Source" pos:[5,5] width:140 height:24 filter:pf_filt GroupBox grp_time "Time:" pos:[5,30] width:140 height:80 label lbl_start "Start:" pos:(grp_time.pos + [10,17]) width:27 height:15 spinner spn_start "" pos:(lbl_start.pos + [60,-1]) fieldWidth:50 height:16 range:[-99999,9999,0] type:#integer scale:0.1 align:#right label lbl_end "End:" pos:(lbl_start.pos + [0,20]) width:25 height:15 spinner spn_end "" pos:(lbl_end.pos + [60,-1]) fieldWidth:50 height:16 range:[-99999,9999,0] type:#integer scale:0.1 align:#right label lbl_inc "Increments:" pos:(lbl_end.pos + [0,20]) width:57 height:15 spinner spn_inc "" pos:(lbl_inc.pos + [60,-1]) fieldWidth:50 height:16 range:[1,9999,0] type:#integer scale:0.1 align:#right GroupBox grp_ops "Options" pos:(grp_time.pos + [0,grp_time.height + 5]) width:140 height:165 enabled:true radioButtons rbGenerateMethod "Generate Method:" labels:#("Spline Per Particle", "Spline Per System") pos:(grp_ops.pos + [5,15]) align:#left label lbl_thres "Threshold:" pos:(rbGenerateMethod.pos + [5,40]) width:50 height:15 spinner spn_thres "" pos:(lbl_thres.pos + [60,-1]) fieldWidth:50 height:16 range:[0,9999,0] type:#worldunits scale:0.1 checkbox chk_ani "" pos:(lbl_thres.pos + [-5,25]) width:15 height:15 checked:false button btn_ani "Animated Growth" pos:(chk_ani.pos + [15,-3]) width:115 height:20 checkbox chk_attach "" pos:(chk_ani.pos + [0,22]) width:15 height:15 button btn_attach "Attach Splines" pos:(chk_attach.pos + [15,-3]) width:115 height:20 tooltip:"Attach selected spline objects" checkbox chk_del "" pos:(chk_attach.pos + [0,22]) width:15 height:15 enabled:false checked:true button btn_del "Delete Old Splines" pos:(chk_del.pos + [15,-3]) width:115 height:20 enabled:false button btn_gen "Generate Splines" pos:(grp_ops.pos + [0,grp_ops.height + 5]) width:110 height:30 enabled:false toolTip:"Hold ESC button to stop." button btn_sel "" pos:(btn_gen.pos + [110,0]) width:30 height:30 enabled:false toolTip:"Select Generated Splines" images:#(arrowIcon,arrowIconAlpha,4,2,2,2,2) progressBar pb_sub "ProgressBar" pos:(btn_gen.pos + [0,35]) width:140 height:8 color:green value:100 progressBar pb_main "ProgressBar" pos:(pb_sub.pos + [0,10]) width:140 height:8 color:green value:100 checkbutton ckb_info "" pos:(pb_main.pos + [0,15]) width:140 height:10 toolTip:"Script Info" GroupBox grp_info "Info:" pos:(ckb_info.pos + [0,11]) width:140 height:125 label lbl_author "Original Author:" pos:(grp_info.pos + [10,16]) label lbl_charley "Charley Carlat" pos:(lbl_author.pos + [25,14]) HyperLink lbl_link "www.charleycarlat.com" align:#Center address:"www.charleycarlat.com" offset:[0,-5] label lbl_mod "Modified by:" pos:(lbl_author.pos + [0,50]) width:60 height:15 label lbl_authors "Jefferson Lim \nJBHaywood \nOfer Zelichover" pos:(lbl_mod.pos + [25,14]) width:100 height:40 -- Functions ------------------------------------------------------------------------ fn pf_filt obj = (classof obj == PF_Source) fn invertMaskBitmap maskBmp threshold:127.5 = ( local bmpHeightMin1 = maskBmp.height - 1 local bmpWidth = maskBmp.width local scanline for y = 0 to (bmpHeightMin1) do ( scanline = getPixels maskBmp [0,y] bmpWidth for x = 1 to bmpWidth do ( scanline[x] = (if (scanline[x].v > threshold) then ( (color 0 0 0) ) else ( (color 255 255 255) ) ) ) setPixels maskBmp [0,y] scanline ) maskBmp ) -- By Ofer Zelichover fn connectTheDots = ( pb_sub.color = red pb_main.color = blue local posArray = #() -- where to collect Point3 val's local numFrames = (f_end - f_start).frame as float local canceled = false -- Goto the first frame in the range sliderTime = f_start -- Create a spline: local sp = splineShape() addnewSpline sp -- Loop through the frames and animate the spline. for t = f_start to f_end by increments while not canceled do ( if keyboard.escPressed then canceled = true -- Move to the right frame sliderTime = t local needAnimateVert = false -- Get the number of particles local numParticles = source.NumParticles() -- Loop through the particles and animate the spline. for p = 1 to numParticles while not canceled do ( if keyboard.escPressed then canceled = true -- Get the particle position local pos = source.getParticlePosition p -- If there are not enough knots in the spline then add a knot if numKnots sp 1 < numParticles then ( addKnot sp 1 #smooth #curve pos needAnimateVert = true ) else ( -- Animate the position of the knot local knotChannelNum = 2 + ((p - 1) * 3) if sp.baseObject[#Master].numSubs >= knotChannelNum then ( animate on sp.baseObject[#Master][knotChannelNum].value = pos ) ) pb_sub.value = (p as float) / numParticles * 100 ) if numKnots sp 1 > 1 then updateShape sp if needAnimateVert then animateVertex sp #All pb_main.value = t.frame / numFrames * 100 ) pb_sub.color = pb_main.color = green pf_ConnectTheDotsShapes = #(sp) ) -- by jbhaywood fn splineGrow spl startFrame:0 = ( pb_sub.color = red pb_main.color = blue count = spl.count for o in 1 to count where canConvertTo spl[o] splineShape do ( pb_main.value = o*100.0/count obj = spl[o] if classOf obj == line do ( addModifier obj (edit_spline()) ) convertToSplineShape obj animateVertex obj #all startNum = 0 -- loop through each spline within the spline object seperately splineCount = numSplines obj for s = 1 to splineCount do ( if keyboard.escPressed do return false pVal = s*1.0/splineCount -- create bitarray of knot indexes for current spline local knotArr = #{1..numKnots obj s} -- get the total number of knots local n = knotArr.numberSet -- create array of positions for each knot so we know where they should end up local knotPosArr = for i = 1 to n collect in coordsys obj (getKnotPoint obj s i) -- this is where the magic happens for i = 1 to n do ( pb_sub.value = (i*100.0/n) * pVal -- define the end of the following loop local n2 = startNum + (n * 3) -- animate only the Vertex master control points, not the InVec or OutVec points for j = ( (((i * 2) - 1) + i) + startNum ) to n2 by 3 do ( -- set keys for the position of the knots animate on ( -- for the first iteration of the loop, set all the knot positions to the position of the first knot at frame zero if i == 1 do ( at time 0 obj[#Object__Editable_Spline][#Master][j].value = knotPosArr[i] ) -- then start setting keys at the startFrame plus the current loop iteration at time ((startFrame - 1) + i) obj[#Object__Editable_Spline][#Master][j].value = knotPosArr[i] ) ) ) startNum += n * 3 ) ) pb_sub.color = pb_main.color = green ) fn genSplines = ( pf_particles = #() pf_shapes = #() lastpos = #() pb_sub.color = red pb_main.color = blue for t in f_start to f_end by increments do ( tNow = ((t - f_start) as float)/ticksperframe tLast = ((f_end as float) - (f_start as float))/ticksperframe tVal = (tNow / tLast ) * 100 pb_main.value = tVal if keyboard.escPressed do exit SliderTime = t num = source.numParticles() for p in 1 to num do ( pb_sub.value = p*100.0/num ID = source.getParticleID p if (finditem pf_particles ID) == 0 do ( pf_particles[ID] = ID the_shape = splineShape name:(uniquename ("pf_"+ ID as string +"_spline ")) addNewSpline the_shape pf_shapes[ID] = the_shape lastpos[ID] = [99999,99999,99999] ) pos = source.getParticlePositionByID ID dist = distance pos lastpos[ID] if dist > threshold do addknot pf_shapes[ID] 1 #smooth #curve pos lastpos[ID] = pos ) ) del_shapes = #() for s in pf_shapes do try(updateShape s)catch(append del_shapes s) for d in del_shapes do (deleteitem pf_shapes (finditem pf_shapes d); delete d) pb_sub.color = pb_main.color = green if chk_ani.checked then splineGrow pf_shapes ) fn attachSplines = ( disableSceneRedraw() sel = selection if sel != undefined do ( splines = for s in sel where (superclassof s == shape) collect s count = splines.count if count > 1 do ( for i in count to 2 by -1 do addAndWeld splines[1] splines[i] 0.0 pf_shapes = splines[1] ) ) try(updateShape pf_shapes)catch() enableSceneRedraw() ) fn delOldSplines = ( for s in (join pf_shapes pf_ConnectTheDotsShapes) where isValidNode s do delete s ) -- Event Handlers ---------------------------------------------------------------------- on pf_spliner open do ( spn_start.value = f_start = animationrange.start spn_end.value = f_end = animationrange.end spn_inc.value = increments = 5 spn_thres.value = threshold = 1 pf_systems = for i in $* where classof i == PF_Source collect i if pf_systems.count == 1 do btn_pick.picked pf_systems[1] ) on btn_pick picked obj do ( source = obj btn_pick.caption = obj.name btn_gen.enabled = btn_sel.enabled = true ) on spn_start changed val do ( f_start = val if val >= f_end do f_end = spn_end.value = val+1 ) on spn_end changed val do ( f_end = val if val <= f_start do f_start = spn_start.value = val-1 ) on spn_inc changed val do increments = val on spn_thres changed val do threshold = val on rbGenerateMethod changed state do ( spn_thres.enabled = state == 1 chk_ani.enabled = state == 1 btn_ani.enabled = state == 1 chk_attach.enabled = state == 1 btn_attach.enabled = state == 1 ) on btn_ani pressed do ( undo "Animated Spline Growth" on ( try(splineGrow (for i in selection where classOf i == SplineShape collect i)) catch(print "Error Appling Animated Spline Growth") ) ) on btn_attach pressed do ( undo "Attach Splines" on try(attachSplines())catch(print "Error Attaching Splines") ) on btn_del pressed do ( undo "Delete Old Splines" on try(delOldSplines())catch(print "Error Deleting Old Splines") ) on btn_gen pressed do ( if chk_del.checked do try(delOldSplines())catch() case rbGenerateMethod.state of ( 1: genSplines() 2: connectTheDots() ) chk_del.enabled = btn_del.enabled = true if chk_attach.checked do ( -- deselect $* select (join pf_shapes pf_ConnectTheDotsShapes) attachSplines() ) -- deselect $* select pf_shapes ) on btn_sel pressed do ( try(select (join pf_shapes pf_ConnectTheDotsShapes))catch(print "Error Selecting Genereted Splines") ) on ckb_info changed state do ( if state then pf_spliner.height += grp_info.height + 2 else pf_spliner.height -= grp_info.height + 2 ) ) createdialog pf_spliner height:358 /* [added] 3.5 (Idea by Ian Clemmer / Programmed by Ofer Zelichover) 2010-10-11 - Added Spline Per System. - Done some code re-organization. 3.4.1 2010-01-02 - fixed bitmap pointer in 'invertMaskBitmap' function to point to valid Icon (it seems the original was removed in ver2010) 3.4 2009-06-29 - added animated growth checkbox/button - added credits to jbhaywood for the animated splines part - added progress bars (splining and animated growth) - added select button for generated splines - added ESC for animated growth - added tooltips 3.3 2009-05-09 - esc enabled [to do] - event baking - subframe sampling */