filein (RsConfigGetWildWestDir() + "script/3dsMax/_config_files/Wildwest_header.ms") rsta_loadCommonFunction #("FN_RSTA_userSettings") if (RsPathDeform != undefined) do try(RsPathDeform.dispose())catch() struct RsPathDeform ( ----------------------------------------------------- -- LOCALS ----------------------------------------------------- version = 2.01, MainWindow, Settings = rsta_userSettings app:"RsPathDeform", vm, theObject, theSpline, ----------------------------------------------------- -- FUNCTIONS ----------------------------------------------------- fn ease_in_out t b c d = ( t = t as float b = b as float c = c as float d = d as float if ((t /= d / 2) < 1) then v = (c - b) / 2 * t * t + b else v = -(c - b) / 2 * ((t - 1) * ((t - 1) - 2) - 1) + b return v ), ----------------------------------------------------------- fn sTwist_sortByPercent v1 v2 = ( if (v1.percent < v2.percent) do return -1 if (v1.percent > v2.percent) do return 1 return 0 ), ----------------------------------------------------------- fn twistCurve3D spline fraction = ( local percent = fraction * 100 -- GET SPLINE TWISTS local sTwists = for h in helpers where (classof h == RsSplineTwist) AND (h.spline == spline) collect h if (sTwists.count != 0) then ( qsort sTwists sTwist_sortByPercent -- GET SPLINE TWISTS TO THE LEF AND RIGHT OF PERCENT POINT local c = 1 while (c < sTwists.count + 1) AND (percent > sTwists[c].percent) do c += 1 local idx_left = if (c == 1) then c else c-1 local idx_right = if (c > sTwists.count) then idx_left else c local left_sTwist = sTwists[idx_left] local right_sTwist = sTwists[idx_right] -- GET RELATIVE PERCENT BETWEEN SPLINE TWISTS local relativePercent = (100.0/(right_sTwist.percent - left_sTwist.percent)) * (percent - left_sTwist.percent) relativePercent = (if relativePercent > 100 then 100 else relativePercent) -- GET TWIST AMOUNT WITH EASE IN/OUT return (ease_in_out relativePercent left_sTwist.angle right_sTwist.angle 100) ) else return 0 ), ---------------------------------------------------- fn isSpline obj = ( return (classof_array #(line,SplineShape) obj) ), ----------------------------------------------------- fn Set_Object = ( for i in (getCurrentSelection()) do ( if (classof_array #(editable_poly, editable_mesh) i) do ( theObject = i vm.ObjectName = theObject.name ) ) ), ----------------------------------------------------- fn getSplineLength s = ( local l = getSegLengths s 1 return l[l.count] ), ----------------------------------------------------- fn getTemplateLength t = ( return (t.max - t.min).y ), ----------------------------------------------------- fn deform_mesh theMesh startFraction endFraction = ( scale (matrix3 1) theMesh.scale theMesh.pos = [0,0,0] theMesh.transform = (matrix3 1) local numVerts = meshop.getNumVerts theMesh local y_length = getTemplateLength theMesh local y_min = theMesh.min.y local vP local lengthFraction for vertNum = 1 to numVerts do ( vP = meshop.getvert theMesh vertNum lengthFraction = (vP.y - y_min)/y_length --if lengthFraction < 0.001 do lengthFraction = 0 --if lengthFraction > 0.999 do lengthFraction = 1 adjustedLengthFraction = (lengthFraction * (endFraction - startFraction)) + startFraction -- CURRENT SPLINE INFO spPos = interpCurve3D theSpline 1 adjustedLengthFraction spTangent = normalize (tangentCurve3D theSpline 1 adjustedLengthFraction) spTwist = twistCurve3D theSpline adjustedLengthFraction -- TRANS MATRIX tm = transMatrix [vP.x,0,vP.z] -- SPLINE DIRECTION rotateX tm (atan2 spTangent.z 1) rotateY tm spTwist rotateZ tm -(atan2 spTangent.x spTangent.y) -- MOVE VERT meshop.setVert theMesh vertNum (spPos + tm.pos) ) ), ----------------------------------------------------- fn getFractionArray c = ( local b = (vm.StartPos/100) local e = (vm.EndPos/100) return (for i=0 to c-1 collect #(b + (((e - b)/c) * i), b + (((e - b)/c) * i) + ((e - b)/c))) ), -------------------------------------------------------- fn do_deform = ( undo "Path Deform" on ( for s in (getCurrentSelection()) where (isSpline s) do ( theSpline = s if (vm.IsAutoFill) do ( local sl = getSplineLength theSpline sl *= ((vm.EndPos - vm.StartPos)/100) local tl = getTemplateLength theObject if (tl > sl) then vm.ObjCount = 1 else vm.ObjCount = floor ((sl/tl) + 0.5) ) local objs = #() local fArray = getFractionArray vm.ObjCount for i=1 to vm.ObjCount do ( local temp_obj = copy theObject convertToMesh temp_obj deform_mesh temp_obj fArray[i][1] fArray[i][2] temp_obj.pivot = temp_obj.center append objs temp_obj ) if (vm.IsMerged) do ( for i=2 to objs.count do meshop.attach objs[1] objs[i] ) completeRedraw() ) ) ), ------------------------------------------------------------------------ -- SPLINE TOOLS ------------------------------------------------------------------------ fn makePoint pos dir:[0,0,1] = ( local pnt = (point pos:pos dir:dir centermarker:false axistripod:true cross:false box:true size:10) pnt.wirecolor = color 114 255 0 return pnt ), ------------------------------------------------------------------------ fn Do_CreateSplineBetweenHelpers = ( local pntA = $[1] local pntB = $[2] local offsetA = (preTranslate pntA.transform [0,1,0]).translationpart local offsetB = (preTranslate pntB.transform [0,-1,0]).translationpart local vA = normalize (offsetA - pntA.pos) local vB = normalize (offsetB - pntB.pos) local dist = (distance pntA pntB)/2 local handA = pntA.pos + (vA * dist * vm.Spline_startVel) local handB = pntB.pos + (vB * dist * vm.Spline_endVel) ss = SplineShape pos:pntA.pos addNewSpline ss addKnot ss 1 #bezier #curve pntA.pos pntA.pos handA addKnot ss 1 #bezier #curve pntB.pos handB pntB.pos updateShape ss ss completeRedraw() ), ------------------------------------------------------------------------ fn Do_FlipSplineHelper = ( for h in (getCurrentSelection()) where (superclassof h == helper) do ( in coordsys local h.rotation.z_rotation += 180 ) ), ------------------------------------------------------------------------ fn Do_addSplineHelper = ( if (selection.count == 0) then makePoint [0,0,0] else ( local obj = selection[1] case of ( (classof obj == editable_poly) : ( local edges = polyop.getEdgeSelection obj if not (edges.isempty) then ( verts = polyop.getVertsUsingEdge obj (edges as array)[1] v1 = polyop.getVert obj (verts as array)[1] v2 = polyop.getVert obj (verts as array)[2] local pnt = makePoint v2 dir:(v2 - v1) in coordsys local pnt.rotation.x_rotation -= 90 ) else makePoint obj.pos dir:obj.dir ) (classof obj == editable_mesh) : ( local edges = getEdgeSelection obj if not (edges.isempty) then ( verts = meshop.getVertsUsingEdge obj (edges as array)[1] v1 = getVert obj (verts as array)[1] v2 = getVert obj (verts as array)[2] local pnt = makePoint v2 dir:(v2 - v1) in coordsys local pnt.rotation.x_rotation -= 90 ) else makePoint obj.pos dir:obj.dir ) (classof_array #(line, SplineShape) obj) : ( selKnot = getKnotSelection obj 1 if (selKnot.count == 1) then ( local pos = getKnotPoint obj 1 selKnot[1] local vec = if (selKnot[1] == 1) then getOutVec obj 1 selKnot[1] else getInVec obj 1 selKnot[1] local pnt = makePoint pos dir:(pos - vec) in coordsys local pnt.rotation.x_rotation -= 90 ) else makePoint obj.pos dir:obj.dir ) default: ( makePoint obj.pos dir:obj.dir ) ) ) ), ------------------------------------------------------------------------ fn Do_AddTwistsToSpline = ( for spline in (getCurrentSelection()) where (isSpline spline) do ( local fraction_step = 100/(vm.TwistCountToAdd - 1) for i=1 to (vm.TwistCountToAdd) do ( local sTwist = RsSplineTwist() sTwist.spline = spline case i of ( 1 : sTwist.percent = 0 (vm.TwistCountToAdd) : sTwist.percent = 100 default : sTwist.percent = fraction_step * (i - 1) ) ) ) ), ----------------------------------------------------- fn Do_ResizeTwists = ( local twists = #() if (vm.TwistResize_FilterIdx == 0) then twists = for h in (getCurrentSelection()) where (classof h == RsSplineTwist) collect h else twists = for h in helpers where (classof h == RsSplineTwist) collect h for i in twists do ( i.size = vm.TwistResize_Size i.distance = vm.TwistResize_Distance ) ), ------------------------------------------------------------------------ -- STRUCT FUNCTIONS ------------------------------------------------------------------------ fn dispose = ( if (MainWindow != undefined) do ( -- WINDOW POS settings.wpf_windowPos mainWindow #set -- CLOSE AND DISPOSE THE WINDOW MainWindow.Close() MainWindow = undefined ) execute ("RsPathDeform = undefined") ), ----------------------------------------------------- -- EVENTS ----------------------------------------------------- on create do ( -- LOAD ASSEMBLY dotnet.loadAssembly (RsConfigGetToolsDir() + @"techart\dcc\3dsMax\RSG.TechArt.PathDeform.dll") -- MAKE MAIN WINDOW INSTANCE MainWindow = dotNetObject "RSG.TechArt.PathDeform.MainWindow" MainWindow.Title = "Path Deform - " + version as string dn_window.setup MainWindow MainWindow.Tag = dotnetmxsvalue this -- PARENTS THE WINDOW UNDER MAX, STOPS IT FROM DROPPING BEHIND MainWindow.ChangeOwner (DotNetObject "System.IntPtr" (Windows.GetMAXHWND())) -- WINDOW POS settings.wpf_windowPos mainWindow #get -- SHOW THE WINDOW MainWindow.show() vm = MainWindow.DataContext ) ) RsPathDeform = RsPathDeform()