352 lines
10 KiB
Plaintext
Executable File
352 lines
10 KiB
Plaintext
Executable File
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() |