
/*
-- Road Offsetter --
-- Copyright : © 2009-2021  3D | R.n.D, All rights reserved
-- Author    : Bayan Al Safadi
-------------------------------------

This Script will Automatically create main road lanes based on selected spline 

Run script or drag and drop to 3ds max, a dialog is created with some input parameters 

		- number of lanes.

		- Lane width.

		- Yellow lanes distance.

		- Enable Yellow lanes ?

		- Flip direction ?

		- Spline is road axis ?

modify the inputs as you need then press (( Offset it ! )) button !

the splines created has material id applied to them as follows :

		- Edge splines with ID = 1

		- Normal white separators with  ID = 2
		
		- Yellow splines with ID = 3
		

-- Version   : 1.05

--this software is provided on an "as is" basis, without warranty of any kind, express or implied, including without limitation, any implied warranties of merchantability,

--the entire risk as to the quality and performance of the software is borne by you, and it is your responsibility to ensure that it does what you require it to do prior to using it

--the author is not responsible for any indirect, special, incidental, or consequential damages of any character including, without limitation, damages for loss of goodwill,

--work stoppage, computer failure or malfunction, or any and all other commercial damages or losses.

------------------------------------- */
	global msgRollPopup
	
		fn msgRollPopup = 
		(
							rollout fixing "fixing"
				(
				  timer clock "testClock" interval:1 --tick once a second
				  label test "1"
				  on clock tick do
				  (
					valUp = (test.text as integer)+1
					test.text = valUp as string
					  if valup == 2 do (
						  destroydialog fixing
					  )
				  )
				)
				createDialog fixing modal:true
			
			)
if roadoffsetter != undefined do
	if classOf roadoffsetter == RolloutClass do
		destroyDialog roadoffsetter
rollout roadoffsetter "Road Offsetter 1.05" width:180
(
	label lbl1 "Number of Lanes :" width:100 across:2 align:#left
	spinner spn1 "" width:60 range:[1,100,2] type:#integer align:#right
	label lbl2 "Lane Width :" width:100 across:2 align:#left
	spinner spn2 "" width:60 range:[0,1000,3.5] type:#worldunits align:#right
	label lbl3 "Yellow Lines Dist. :"  width:100 across:2 align:#left
	spinner spn3 "" width:60 range:[0,1000,0.5] type:#worldunits align:#right
	checkbox chk1 " Enable Yellow Lanes" offset:[0,5]
	checkbox chk2 " Flip Direction"
	checkbox chk3 " Spline is Road Center"
	
	button btn1 "Offset it !" width:160 height:24 offset:[0,5]
	hyperLink web "3D_R.n.D Tools and Models" address:"https://linktr.ee/3D_R.n.D" offset:[0,5]
	label cRight "Copyright 2021"
	
	local thespline, spl, allspl, selspl, opened, new = #(), y, f, v, v2, vy, fo, aa, aa1, t
	--( FUNCTIONS
	fn CreateShp arr = (
		s = splineshape()
		addnewspline s
		for i = 1 to arr.count do addKnot s 1 arr[i][1] #line arr[i][2] arr[i][3] arr[i][4]
		updateShape s
		s
	)
	fn Apply_Offset shp f n sel:true weld:true opened:true shp1: = (
		local s
		applyOffset shp f
		if not opened then deleteSpline shp 1 else (
			local n = numKnots shp
			local arr = for i = (n/2)+1 to n collect #(getKnotType shp 1 i,getKnotPoint shp 1 i,getInVec  shp 1 i,getOutVec shp 1 i)
			s = CreateShp arr
			delete shp
		)
		if weld do if s != undefined then addAndWeld shp1 s 0 else addAndWeld shp1 shp 0
	)
	fn Delete_Spline shp = (
		a = copy shp
		spl = getSplineSelection a
		allspl = numSplines a
		for i = allspl to 1 by -1 do (
			if i != spl[1] do deleteSpline a i
		)
		a
	)
	--)
	on  btn1 pressed do  (
		if selection.count == 1 and canConvertTo $ SplineShape do with undo on (
			thespline = $
			convertToSplineShape thespline
			selspl = getSplineSelection thespline
			allspl = numSplines thespline
			if selspl.count == 0 then (t = allspl ; spl = #(allspl))
			else (t = selspl.count ; spl = selspl)
				
			if t != 1 then messagebox "please make sure to only select 1 spline" else (
		     	max create mode
				setSplineSelection thespline #(1)
				opened = not (isClosed thespline spl[1])
					
				if chk1.state then y = 2 else y = 0
				if chk2.state then f = -1 else f = 1
					
				for i = 1 to allspl do setSegSelection thespline i #()
				v = spn2.value*f
        		v2 = spn2.value*f
         		vy = spn3.value*f
         	 	fo = ((spn1.value*v)+vy*2)/2
				
         		if chk3.state do Apply_Offset thespline fo 1 sel:true weld:false opened:opened
				setSplineSelection thespline #(1)
				aa1 = Delete_Spline thespline
				-------------------------------------- yellow option
				if y == 2 then (
					aa = Delete_Spline thespline
					Apply_Offset aa vy 3 sel:true weld:true opened:opened shp1:thespline
					v2 = (v2 + vy)
					for j = 1 to spn1.value do (
						aa = copy aa1
						if j != spn1.value then Apply_Offset aa v2 2 sel:false weld:true opened:opened shp1:thespline
						else Apply_Offset aa v2 3 sel:false weld:true opened:opened shp1:thespline
						v2 = (v2 + v)
					)
					v2 = (v2 +- v + vy)
					Apply_Offset aa1 v2 1 sel:false weld:true opened:opened shp1:thespline
				)
				---------------------------------------yellow option end
				else (
					for j = 1 to spn1.value do (
		  		    	if j != spn1.value then (
							aa = copy aa1
							Apply_Offset aa v2 2 sel:false weld:true opened:opened shp1:thespline
						)
						else Apply_Offset aa1 v2 3 sel:false weld:true opened:opened shp1:thespline
						v2 = (v2 + v)
					)
				)
			)
		)
		------------------operation ends here
		updateshape thespline
	)
)
createDialog roadoffsetter
clearListener()