Home Technical Talk

TexTools 3.0+

1234579

Replies

  • maze
    Hi there, I am having a small problem using textools when trying to find the pixel ratio of an asset composed of several objets.

    Basically I normalize the shells, then use the pixel ratio picker, but it does give me this error:

    pix2: -1.#IND

    It was working ok but then I am not sure what I did and started getting that! Thanks for your help! I'll appreciate it!
  • debashish
    is there a way to make this install on max2011?
    i tried the manual install, throwing errors :(
  • e-freak
    Just wanted to share some love: Tried out TexTools for the first time and am so addicted to it already! Great work :D
  • Valerien
    Waow, this tool is really impressive ! Now extending textures to pack multiple objects in it is a piece of cake, and all that stuff for free !
  • Octo
    Offline / Send Message
    Octo polycounter lvl 18
    'Hard Edges' in the Bake texture maps thingy is giving me unexpected results.
    The edges in the render are offset, and doesn't match the UVs...also, the lowest thickness (1) is way too fat, and my model is to scale (if that matters, it's a tank)
  • WarrenM
    I use this script all the time and it's amazing! But you know, I can never get "Rectify" to work. It looks like I should be able to select UV islands made up of quads and have them get straightened into rectangles but it never does anything when I left click the button. Is this a known thing or is there a hidden 'gotcha' that I'm not aware of?
  • AnimeAngel
    ya i have seen that too with rectify. I'll select a element that is fairly close to rectangular in the first place. click rectify and it will usually ball it all up and make a huge mess. Crtl-z
    Also can't get the linear align to work now in 2011. It never quite straightens it, always have to use the old scaling method again to get lines straight.
    Still an amazing tool overall and can't live without it. :)
  • AdamB
    Octo wrote: »
    'Hard Edges' in the Bake texture maps thingy is giving me unexpected results.
    The edges in the render are offset, and doesn't match the UVs...also, the lowest thickness (1) is way too fat, and my model is to scale (if that matters, it's a tank)
    I've been wondering myself how this works, any tips would be great!
  • cupsster
    Offline / Send Message
    cupsster polycounter lvl 11
    Hi Render,

    maybe you can implement something from this stuff.. I'd like to see transfer of UV from hipoly to lowpoly for example.. missing this :)
    -- UV Layout
    
    -- This program was split off from the Surface Toolkit.... Thanks to the guy who coded the TV drawing routine I'm using.
    -- please email me at vajuras@planetunreal.com so I can give ya credit. www.cyberkreations.com/kreationsedge
    
    -- Updated May 9, 2001 to work in Max 4. I think my interest in this was rekindled so that it could be used to help Chilliskinner advance.
    
    -- On jan. 23 the unwrap algorithm was vastly improved to handle unwraps on the right
    -- and left side. Also, added Match UVW function/utility.
    
    -- 2/7
    -- Made the Camera Projection Logic.
    
    -- 2/14
    -- Improved "Update Map" routine which would have an error.
    -- Render_map will now convert object to mesh if not an Editable Object.
    -- Added ability to separately render TVFaces without splitting a mesh object. This
    -- method seems to work much better and return more accurate results...
    
    -- 2/20
    -- Update_Texture now works with Multi-materials...
    
    -- 2/23
    -- started working on the Skin Composer routine.
    
    -- 3/02
    -- Actually put in the AI for Blender.
    -- Upgraded the UV Manager to create an alpha channel for uv maps.
    
    -- Blender uses advanced algorithm to compute across any range [n, n] instead of [0, 100].
    -- This is the code that does the math:
    --				dist = abs(sort_gy - sort_ly)
    --				pnt = 1/dist
    --				p_dist = abs(pix.y - sort_ly)
    --				blend_pnt = p_dist*pnt
    
    
    -- 3/12
    -- Added Attachments Utility
    
    -- 4/17
    -- Fixed a bug where the VertexSelection did not work for SurfUnwrap.
    
    -- v1.2 
    -- 4-21
    -- Added Edge Colors & Surface Glue.
    -- Extended the range of the size of an image.
    -- The Script used to crash if the restore 0r Apply under Project UVW button was pressed.
    -- You can now enter float values for the Width & Length of a bitmap (UV Manager)
    -- A lot of easy crashes were fixed that may be caused if a user clicks the wrong button.
    
    -- v1.2.2
    -- Fixed a crash that may occur during a 'render map' when the color comes up undefined...
    -- Default Material checkbox will now go & load the Material's diffusemap. Changes a BitmapTexture to Bitmap.
    -- Increased User Feedback
    
    -- v1.2.3 -> v1.2.4
    -- Fixed the bug in which the edge color array would crash the utility.
    -- The utility displays the expiration date.
    
    -- v1.3
    -- Added UV Mesher Tool.
    -- Improved Glue Tool Performance.
    
    -- v1.3.3
    -- UV Mesher grabs the dimension of the Diffuse Channel Bitmap if available.
    -- WARP feature for the UV Mesher was fixed.
    
    -- v1.4
    -- UpdateMap feature now reloads all the mapping channels instead of just the diffuse channel.
    
    utility surfHelp "UV Layout"
    (
    local sort_y, morph_state = false
    
    -- stores the selection of cross objects
    local b_cross = #()
    local b_crossNum = 0
    
    local s_width = 190
    local s_height = 345
    
    -- For the 3D Paint Options
    local default_secs = 3600
    local map_type = 0				--default mapping: planar
    local uvw_axis = 0
    
    -- Emergency ShutDown
    local shutDown = false
    
    -- Determines if this script is registed, if so, all features are enabled.
    local register = true
    
    label display_global ""
    
    --stores color for each edge (UV Layout & Edge)
    local color_mat = #()
    
    -- global user_color
    local global_color = red
    
    -- selection set data
    local sel_set =#(), sel_index = 1
    
    -- Variables for GLUE
    local glue_set = #()
    local glue_names = #()
    local glue_objA = #()
    local glue_objB = #()
    local glue_pos = #(#())
    local previous_b = #()     -- Stores the original OBJECT B
    
    -- Variables for UV Mesher
    local face_set = #()	-- Stores the origin for the TVFace.
    
    	fn grab_sel =
    	(
    		selection as array
    	)
    
    	-- Selects all the faces in a mesh.
    	fn setFaceArray tar numF =
    	(
    		tar = #()
    		for i = 1 to numF do
    		(
    			tar[i] = i
    		)
    			
    		return tar
    	)
    
    	-- Retrieves the date from a string and returns it in a 3-element array. The string must conform to localTime String Conventions
    	-- meaning a space character must be included like "11/23/98 8:23PM". This function can also tokenize a regular string.	
    	-- This routine automatically looks for / and \\ (backslash) but, an extra delimeter can be searched.
    	-- By default, you should send a space character.
    	fn get_all_tokens str_in delimeter =
    	(
    		tokens = #()
    		
    		str = str_in as string
    		len = str.count
    		count = 1									-- Count the # of tokens
    		elmo = 0									-- Count valid charcters
    		
    		for a = 1 to len do
    		(
    			if str[a] == "/" or str[a] == delimeter or str[a] == "\\" then 
    			(
    				this_token = substring str count elmo
    				append tokens this_token
    
    				-- Set the pointer to the beginning of the next slot.
    				count = a + 1	
    				elmo = 0			
    			)
    			else
    			(
    				-- Count the valid characters
    				elmo = elmo + 1
    			)
    		)
    
    		if shutDown == true then 
    		(
    		shutDown == true
    		return #()
    		)
    		
    		-- Return the last token also.
    		this_token = substring str count elmo
    		append tokens this_token
    
    		tokens
    	)
    	
    	-- Replace all occurances of a character with another.
    	fn replace_char str delimeter new_char =
    	(
    		len = str.count
    		
    		for a = 1 to len do
    		(
    			if str[a] == delimeter then str[a] = new_char
    		)
    		
    		str
    	)
    
    	-- Opt 1: Encrypt
    	--     2: Not Encrypted
    	fn read_data file_name opt =
    	(
    	count = 1
    	j_name = #()
    	
    	if opt == 2 then file = openFile (file_name)
    	else
    		file = openEncryptedFile (file_name) 252525
    	
    	if file != undefined then
    	(
    		while (not eof file) do
    		(
    			str = readline file
    			j_name[count] = str
    			count = count + 1
    		)	
    		
    		close file
    	) -- if
    	j_name
    	)
    	
    	-- Opt 1: encrypt
    	--     2: not encrypt
    	fn save_data file_name path_string opt =
    	(
    
    		if file_name != undefined then
    		(
    		  	if opt == 1 then file = createFile(file_name+".tmp")
    			else
    				file = createFile(file_name)
    				
    			format "%\n" path_string to:file
    			close file
    		) -- if
    		if opt == 1 then (
    		encryptFile (file_name+".tmp") file_name 299525 
    		deleteFile (file_name+".tmp")
    		)
    	)	
    	
    	-- Use the .ini file to determine where the MAX ROOT is.
    	fn get_root =
    	(
    		f = read_data "uv_max/layout.ini" 2
    		
    		if f.count < 1 then (
    		messagebox "Please press the Online Help (.chm) button first to install the .ini file before continuing."
    		return #()
    		)
    
    		tokens = get_all_tokens f[1] "-"
    		
    		tokens
    	) -- warez
    	
    
      -- This function will return another point that lies in the same spline. This func is called by the unwrap_spline
      -- func which in turn uses this AI to help determine which xAxis to assign to a spline knot. The Spline Ends Algorithm
      -- is applied which states that the very next vertex in the spline order can be used to determine the direction of the
      -- knot.
      fn findOtherKnot obj spl vert =
      (
      	local pnt
    	
    	numK = numKnots obj spl
    	old_pnt = getKnotPoint obj spl vert
      	next_vert = vert - 1
    	if vert >1 then next_vert = vert - 1
    	else
    		next_vert = vert + 1
    
    	pnt = getKnotPoint obj spl next_vert			
    	gw = "NEXT:"+next_vert as string+" SENT:"+vert as string
    	
    	-- Return the same point back if no vert exists on a different xAxis in the same spline.
    	pnt
      )
      
      -- This function will return another point that lies in the same spline. This func is called by the radialSolver
      -- func which in turn uses this AI to help determine which xAxis to assign to a spline knot.
      fn simpleFindOtherKnot obj spl vert =
      (
      	local pnt
    	
    	numK = numKnots obj spl
    	old_pnt = getKnotPoint obj spl vert
      	for i = 1 to numK do
    	(
    		pnt = getKnotPoint obj spl i
    		
    		if old_pnt.x != pnt.x then return pnt
    	)
    	
    	-- Return the same point back if no vert exists on a different xAxis in the same spline.
    	pnt
      )
      
      
      -- This function makes any knot that equal the deformed knot move also similar to the Global Transform Func.
      -- Since the new position is along the yAxis, it will not be deformed again.
      -- Var:
      -- new_pos - new position where this vert should move
      fn makeAllKnotsEqual obj spl vert new_pos thres =
      (
      	nums = numSplines obj
    	old = getKnotPoint obj spl vert		-- current position of the before the new move. 
    	for i = 1 to nums do
    	(
    		numk = numKnots obj i
    		for j = 1 to numk do
    		(
    			pnt = getKnotPoint obj i j
    			-- Exclude the spline where the original knot came from. Spline Ends Algorithm.
    
    				pntxUp = old.x + thres
    				pntxDown = old.x - thres
    				pntyUp = old.y + thres
    				pntyDown = old.y - thres
    				pntzUp = old.z + thres
    				pntzDown = old.z - thres
    			
    			if i != spl and (pnt.x <= pntxUp and pnt.x >= pntxDown) and (pnt.y <= pntyUp and pnt.y >= pntyDown) and (pnt.z <= pntzUp and pnt.z >= pntzDown)  then 
    			(
    				pnt = new_pos
    				setKnotPoint obj spl vert pnt
    			)
    		)
    	)	
      )
      
      -- This function will solve for a radial b-spline since the Spline Ends Algor. fails if the points lie within the
      -- threshold.
      fn radialSolver obj spl vert =
      (
      	numS = numSplines obj
    	
    	new_spline = spl - 1
    	
    	-- limit checks
    	if new_spline < 1 then new_spline = spl + 1
    	if new_spline > numS then new_spline = spl
    	
    	pnt = simpleFindOtherKnot obj new_spline vert
    	
    	-- Return another point on another spline that can be used to determine the direction.
    	pnt
      )
      
      -- This function unwraps a spline object. If the surf is cylindrical/spherical, the knots along the mid spline behind the base axis
      -- will be pulled apart. Spline Ends Algorithm examines a spline and will assign to the middle knot automatically the direction
      -- the knot should go which is naturally, determined by the Order of the spline.
      -- b_a - Y axis
      -- x_a - X axis 
      fn unwrap_spline obj b_a x_a thres output =
      (
      	local num_s, num_k, val, pnt, gw
    	dist = 0.0						-- distance pnt from x_a
    	try (
    	num_s = numSplines obj	
    	) catch (
    	messagebox "Please choose a valid object."
    	return 0
    	)
    	
    	for i = 1 to num_s do
    	(
    		num_k = numKnots obj i
    
    		calcy = (i as float / num_s as float) * 100
    		calcy = calcy as integer
    		lc = calcy as string + "%"
    		output.text = lc
    
    		for j = 1 to num_k do
    		(
    		
    			pnt = getKnotPoint obj i j
    			gw = i as string + ":" + j as string + " "+pnt as string
    
    			-- If the point is below the base axis, adjust the val variable.
    			if pnt.y > b_a then val = pnt.y - b_a
    			else
    				val = 0
    			ny = pnt.y
    			nx = pnt.x
    			dist = (abs(x_a - pnt.x))/100
    			
    			-- New Y coordinate will be at base axis. If Y coordinate is less than base axis, then let it keep its position.
    			if pnt.y > b_a then
    			(
    				ny = b_a
    				--nx = pnt.x - val				
    				--gw = "Behind base "+i as string+":"+j as string+" "+pnt.x as string
    				--print gw	
    				
    				-- If the point is along the middle spline behind the base axis.... Determine which direction to move.
    				midUp = (x_a as float + thres as float)
    				midDown = (x_a as float - thres as float)
    				if pnt.x <= midUp and pnt.x >= midDown then
    				(
    					otherKnot = findOtherKnot obj i j
    					--gw = "Mid "+i as string+":"+j as string
    					--print gw
    					
    					-- If the Spline Ends Algorithm has failed in case of radial b-splines then, use the radial b-solver algorithm
    					-- instead.
    					if otherKnot.x == pnt.x then otherKnot = radialSolver obj i j 
    					est = otherKnot.x
    
    					if est < (x_a) then nx = pnt.x - (val * dist)
    					else
    						nx = pnt.x + (val * dist)
    						
    					-- Now, deform any other colliding vertices.... The deformed verts will not ever be deformed again because
    					-- they will equal the b_a.
    					new_pnt = [nx, ny, pnt.z]
    					makeAllKnotsEqual obj i j new_pnt thres
    				)
    				else
    				(
    
    					if pnt.x < x_a then nx = pnt.x - (val * dist)
    					else
    					(
    						if pnt.x > x_a then 
    						(
    							nx = pnt.x + (val * dist)
    							gw = gw + "RIGHT "
    							new_pnt = [nx, ny, pnt.z]
    							--makeAllKnotsEqual obj i j new_pnt thres
    						) -- if
    					) -- if
    				
    				) -- if
    								
    			) -- if
    			setKnotPoint obj i j [nx, ny, pnt.z]
    			updateShape obj			
    			--gw = gw + " "+nx as string + ":" + ny as string + " " + val as string
    			--print gw
    		)
    	)
    	
    	try (
    	) catch (
    	messagebox "Please select a valid object"
    	return 0
    	)
    	
    	output.text = "->"
      )
      
      -- This is a general func designed to work with any type of surface. It
      -- takes the object and computes the highest or lowest x value.
      -- option 1: largest, opt 2: least
      fn compute_percent obj opt =
      (
      	local sort = 0, diff_x = 0.0, sort_x = 0
       
    	convertToMesh obj
      	numS = getnumverts obj
    	for i = 1 to numS do
    	(
    		pnt = getvert obj i		
    		
    		if i == 1 then (
    		diff_x = pnt.x
    		sort_x = i
    		)
    		else
    		( 
    			if opt == 1 and pnt.x > diff_X then 
    			(
    				sort_x = i
    				diff_x = pnt.x
    			)		
    
    			if opt != 1 and pnt.x < diff_X then 
    			(
    				sort_x = i
    				diff_x = pnt.x
    			)		
    
    		)		
    	)
    	
    	sort_x
      )
    	
      -- This function unwraps a mesh object. The val is computed to determine the total
      -- distance a point should be moved along the X axis. The dist is computed as the
      -- distance the point is from the X axis which gives a percentage value.
      -- b_a - Y axis
      -- x_a - X axis 
      fn unwrap_mesh obj b_a x_a x_width use_stack disp =
      (
      	local num_s, num_k, val, pnt, gw, target = #(), i, sort_x
    	
    	dist = 0.0					-- distance pnt.x is from x_a divided by 100 to get
    								-- a percentage. This computation will then be used 
    								-- to determine how far from the X axis the points
    								-- should be deformed.
    	count = 1
    	select_i = 0 -- turns on if stack is present...
    	num_verts = 0
    	
    	try (
    		  dummy = getnumfaces obj
    		) catch (
    		convertToMesh obj
    		)	
    	
    	--Had to take out unwrap support for a vertex selection. It was a useless feature anyway...	
    	num_verts = getnumverts obj
    	
    	if select_i == 0 or use_stack == false then 
    	(
    		for i = 1 to num_verts do
    		(
    			target[i] = i
    		)
    	) -- if
    	
    	disp.text = "Analyzing Topology...." 
    	
    	sort_x = compute_percent obj 1	
    	far_vert = getvert obj sort_x	
    	sort_neg = compute_percent obj 2	
    	least_vert = getvert obj sort_neg
    	
    	-- Get the percentage from the farthest vert. Then, this value will be used 
    	-- to equate the values to a range [low, 100]
    	percent = 100 / (abs(x_a - far_vert.x))
    	percent_neg = 100 / (abs(x_a - least_vert.x))
    	
    	progressStart "Unwrapping..."
    	
    	cond = true
    	
    	count = 1	
    	for i in target do
    	(
    		calcy = (i as float / num_verts as float) * 100
    		calcy = calcy as integer
    		lc = calcy as string + "%"
    		if select_i == 1 then disp.text = "Using Stack Selection...."
    		else
    		  cond = progressUpdate calcy
    	
    		if cond == false then return 0
    	
    			try (
    			pnt = getvert obj i 
    			) catch (
    			pnt = getvert obj count
    			)
    			
    			-- If the point is below the base axis, adjust the val variable.
    			if pnt.y > b_a then val = pnt.y - b_a
    			else
    				val = 0
    			ny = pnt.y
    			nx = pnt.x
    			if pnt.x < x_a then dist = (abs(pnt.x - x_a)) * percent_neg
    			else
    				if pnt.x > x_a then dist = (abs( pnt.x - x_a)) * percent
    			dist = dist / 100
    			
    			-- If the user wants to morph the mesh, then let dist always eq. 1 so
    			-- that the verts may be deformed.
    			--if morph_state == true then dist = 1
    			
    			-- New Y coordinate will be at base axis. If Y coordinate is less than base axis, then let it keep its position.
    			if pnt.y > b_a then
    			(
    				ny = b_a
    				--nx = pnt.x - val
    				
    				-- Include the middle spline as well
    				
    				-- If midpoint is from LEFT TO RIGHT then mid = x_a + 1
    				--mid = x_a + 1
    				if pnt.x < x_a then 
    					nx = pnt.x - (val * dist)
    				else
    				(
    				if pnt.x > x_a then (
    					nx = pnt.x + (val * dist)
    				)
    				total = val * dist
    				--gw = "Dist:"+dist as string+" Val:"+val as string+" Total:"+total as string
    				--print gw
    				)
    				
    			) -- if
    			try (
    			setvert obj i [nx, ny, pnt.z]
    			) catch (
    			setvert obj count [nx, ny, pnt.z]
    			)
    			
    			--gw = gw + " X:Y "+nx as string + ":" + ny as string + " V:" + val as string
    			--print gw
    
    	count = count + 1
    	)
    	update obj
    	disp.text = ""
    	progressEnd()
    	
    	-- Return target array.
    	target
      )
    
      
      -- This function uses the array (spl) to restore the original target.
      fn restore_spline obj spl output =
      (
      	local token = #()
    	local count = 1
    	
    	if classof obj != editable_mesh then return
    	
    	try (
    	lengt = spl.count
    	for i = 1 to lengt do
    	(
    		calcy = (i as float / lengt as float) * 100
    		calcy = calcy as integer
    		lc = calcy as string + "%"
    		output.text = lc
    	
    		token = get_token spl[i] " "
    		setKnotPoint obj (token[1] as Number) (token[2] as Number) [token[3] as float, token[4] as float, token[5] as float]
    	)
    	) catch (
    	messagebox "Cannot restore shape."
    	return 0
    	)
    	
    	output.text = "->"
    	updateShape obj
      )  
      
      fn restore_mesh obj target spl output =
      (
      	leng = target.count				-- Get the Vertex Selection
    	real_num = getnumverts obj		-- Get # of verts in the mesh object
    	count = 0
    	collapseStack obj
    	
    	if leng < 1 then
    	(
    		-- Fill target array
    		for i = 1 to real_num do
    		(
    			count = count + 1
    			target[count] = getvert obj i
    		)
    	)
    	
    	count = 0
    	progressStart "Restoring..."
    	
    	for i in target do
    	(
    		count = count + 1
    		calcy = (count as float / leng as float) * 100
    		calcy = calcy as integer
    		progressUpdate calcy
    		
    		-- An empty target array means No Vertex Selection was made.
    		if leng == real_num or leng < 1 then setvert obj count spl[count]
    		else
    		  setvert obj i spl[i]
    		--gw = "Restore:"+spl[count] as string	
    	)
    	
    	try (
    	--output.text = "->"
    	progressEnd()
    	) catch ()
    	
    	update obj		
      )
      
      -- This func draws the pixels in-between the 2 points.
      fn draw_line x1 y1 x2 y2 uvBMP u_color =
      (
      pnt = #()
      	-- Compute the pixels between 2 points. First, derive the distance.
    	dist_x = abs(x2 - x1)
    	dist_y = abs(y2 - y1)
    	
    	if x1 > x2 then l_x = x2
    	else
    	 l_x = x1
    
    	if y1 > y2 then l_y = y2
    	else
    	 l_y = y1
    	
    	-- Let i take the value of y
    	for i = 1 to (dist_y) do
    	(
    		-- move right
    		diff_x = x2 - x1
    		diff_y = y2 - y1
    
    		pnt[i] = [0,0]
    		if diff_x > 0 then pnt[i].x = diff_x
    		if diff_y > 0 then pnt[i].y = diff_y						
    	)
    	
      )
    
    	-- Bresenham line implimentation for MAXScript
    	-- by Harry Denholm, Kinetix 1998
    	function BLine bmp x1 y1 x2 y2 c old_color =
    	(
    	-- stick the colour into an array
    	local ary = c
    	
    	if ary == undefined then ary = #(old_color)
    	
    	-- assign originals
    	local Xb = x1 as integer
    	local Yb = y1 as integer
    	
    	-- build the line deltas
    	local dX = x2-x1 as float
    	local dY = y2-y1 as float
    	
    	-- straight horiz 
    	if dy == 0.0f do (
    		local xsign = 1
    		if xb > x2 then xsign = 1 as integer
    		if x2 < xb then xsign = -1 as integer
    		
    				setPixels bmp [xb,yb] ary
    				
    				while xb != x2 do
    					(
    						xb += xsign 
    						setPixels bmp [xb,yb] ary
    					)
    					return true
    	)
    	-- straight vertical 
    	if dx == 0.0f do (
    		local ysign = 1
    		if yb > y2 then ysign = 1 as integer
    		if y2 < yb then ysign = -1 as integer
    		
    				setPixels bmp [xb,yb] ary
    				while yb != y2 do
    					(
    						yb += ysign 
    						setPixels bmp [xb,yb] ary
    					)
    					return true
    	
    	)
    	
    	-- no straights, go for bresenham line slide
    	
    	-- set up the movements
    		local xsign = 1
    		if xb > x2 then xsign = 1 as integer
    		if x2 < xb then xsign = -1 as integer
    		local ysign = 1
    		if yb > y2 then ysign = 1 as integer
    		if y2 < yb then ysign = -1 as integer
    		dx = abs(dx)
    		dy = abs(dy)
    		setPixels bmp [xb,yb] ary
    		
    	-- line more vertical than horizontal
    		if dx < dy then
    		(
    			p = 2 * dx - dy
    			const1 = 2 * dx
    			const2 = 2 * (dx - dy)
    			while yb != y2 do
    			(
    				yb += ysign
    				if p < 0 then ( p = p + const1 )
    				else
    				(	
    					p += const2
    					xb += xsign
    				)
    				setPixels bmp [xb,yb] ary
    			)
    		)
    		
    	--	line more horizontal than vertical
    		else
    		(
    			p = 2 * dy - dx
    			const2 = 2 * (dy - dx)
    			const1 = 2 * dy
    			while xb != x2 do
    			(
    				xb = xb + xsign
    				if  p < 0 then ( p = p + const1 )
    				else
    				(	p = p + const2
    					yb = yb + ysign
    				)
    				setPixels bmp [xb,yb] ary
    			)
    		)
    	
    	)
    	
      -- Set material color to the bitmap.
      fn setMaterial uvBMP inMat =
      (
      	iW = uvBMP.width
    	iH = uvBMP.height
    	
    	inMat.alpha = 0.0
    	
    	mat_color = #(inMat)
    	for i = 1 to iW do
    	(
    		for j = 1 to iH do
    		(
    			setPixels uvBMP [i,j] mat_color
    		)
    	)
      )
      
      -- This function renders the unwrapped surface or face selection.
      -- opt - use face selection from stack.
      fn render_uvw obj uvBMP u_color opt =
      (
      	target = #()
    	
    	try (
      	iW = uvBMP.width
    	iH = uvBMP.height
    	) catch (
    	messagebox "Please select a bitmap or uncheck the Include Bitmap option."
    	return 0
    	)
    	
    	status = false
    	count = 0
    	edge_num = 0
    	
    	t_count = getnumfaces obj
    	Uobj = obj
    	cCol = newCol = u_color
    		
    	display_global.text = "Rendering UVW Coordinates..."
    	progressStart "Rendering..."
    	
    	-- Always assume that a UVWmap mod is at the top so, grab the next mod.	
    	try (
    		target = getFaceSelection Uobj Uobj.modifiers[1]
    		) catch (
    		try (
    		target = getFaceSelection Uobj Uobj.modifiers[2]			
    		) catch (
    		-- Set the func. to use all the faces in the mesh.	
    		opt = false
    		) -- catch
    	) -- catch
    
    gw = "Faces:"+t_count as string+" "+target as string
    print gw
    	
    	if opt == false then (
    		target = #()
    		--delta = (100.0/(getnumfaces Uobj)) as float
    		for a = 1 to t_count do
    		(
    			target[a] = a
    		)
    	)
        limit = target.count
    	
    			for t in target do
    			(
    				-- update our progress bar
    				count = count + 1
    		calcy = (count as float / limit as float) * 100
    		calcy = calcy as integer
    		progressUpdate calcy	
    				
    				--progressUpdate ((t*delta) as integer)
    				status = getProgressCancel()
    				
    				if shutDown == true then(
    				status == true
    				)
    				
    				if status == true then (
    				progressEnd()
    				display_global.text = ""
    				return false				
    				)
    				
    				-- get the faces
    				faceN = getface Uobj t
    				faceT = getTVFace Uobj t
    				
    				-- take the TVs out of the face index
    				tva = gettvert Uobj faceT.x
    				tvb = gettvert Uobj faceT.y
    				tvc = gettvert Uobj faceT.z
    				
    				
    				-- unwrap TVs. If a new Edge Color exists, use that color instead.
    				try (
    				edge_num = t * 3
    				newCol = #(color_mat[edge_num-2])
    				if color_mat[edge_num-2] == 0 then newCol = cCol
    				) catch (
    				newCol = cCol
    				)
    				
    				if newCol == undefined then newCol = cCol
    				
    				if (getedgevis Uobj t 1 and color_mat[edge_num-2] != -1) then \
    			Bline uvBMP (iW*tva.x) (iH*(1.0-tva.y)) (iW*tvb.x) (iH*(1.0-tvb.y)) newCol cCol
    
    				try (
    				edge_num = t * 3
    				newCol = #(color_mat[edge_num-1])
    				if color_mat[edge_num-1] == 0 then newCol = cCol 
    				) catch (
    				newCol =cCol
    				)
    
    				if newCol == undefined then newCol = cCol
    
    				if (getedgevis Uobj t 2 and color_mat[edge_num-1] != -1) then \
    			Bline uvBMP (iW*tvb.x) (iH*(1.0-tvb.y)) (iW*tvc.x) (iH*(1.0-tvc.y)) newCol cCol
    
    				try (
    				edge_num = t * 3
    				newCol = #(color_mat[edge_num])
    				if color_mat[edge_num] == 0 then newCol = cCol				
    				) catch (
    				newCol =cCol
    				)
    
    				if newCol == undefined then newCol = cCol
    
    				if (getedgevis Uobj t 3 and color_mat[edge_num] != -1) then \
    			Bline uvBMP (iW*tvc.x) (iH*(1.0-tvc.y)) (iW*tva.x) (iH*(1.0-tva.y)) newCol cCol
    
    			)
    	
    	progressEnd()
    	display_global.text = ""
    	display uvBMP
      )
      
      -- This func copies the UVW coordinates and material assignments from one object
      -- to another.
      fn match_uvw target source deform_uv =
      (
      	tmap = true				-- texture mapping applied
    	t_equal = true			-- if tverts equal then deform the texure vertices. If not,
    							-- simply assign the materials.
    	
        --convertToMesh target
    	--convertToMesh source
    	
    	try (
      	a = getnumfaces target
    	b = getnumfaces source
    	) catch (
    	return 0
    	)
    	
    	if a != b then (
    	messagebox "These objects have different face counts (topology)."
    	return 0
    	)
    	
    	try (
    	c = getnumtverts target
    	d = getnumtverts source
    	) catch (
    	--messagebox "No Mapping Applied..."
    	--return 0
    	tmap = false
    	c = d = 0
    	)
    	
    	if c < 1 or d < 1 then (
    	--messagebox "No Mapping Applied..."
    	--return 0	
    	tmap = false
    	)
    	
    	if c != d then (
    	--messagebox "The objects have different counts of texture vertices."
    	--return 0
    	t_equal = false
    	)
    	
    	progressStart "Setting TVFaces...."
    	--convertToMesh source
    	
    	-- copy materials
    	f = target.material
    	source.material = f
    	
    	for i = 1 to a do
    	(
    		calcy = (a as float / i as float) * 100
    		calcy = calcy as integer
    		progressUpdate calcy	
    		
    		-- Copy separate face assignments if Multi-Object has been applied.
    		f = getfacematid target i
    		setfacematid source i f
    		
    		if tmap == true and t_equal == true and deform_tv == true then (
    		f = getTVFace target i
    				
    		t1 = gettvert target f.x
    		settvert source f.x t1
    
    		t2 = gettvert target f.y
    		settvert source f.y t2
    		
    		t3 = gettvert target f.z
    		settvert source f.z t3		
    		
    		setTVFace source i f.x f.y f.z
    		)
    	)
    	
    	progressEnd()
    	update source
      )
    	
    	-- Update Map
    	-- Updates a standard and multi-material's diffusemap.
    	fn update_texture obj junk_bitmap =
    	(
    		local file_name
    		count = 0      -- count # of updated textures
    		
    		-- Grab the Current Selection to refresh the buffer.
    		obj_array = grab_sel()
    		obj = obj_array[1]
    		
    		try (
    		classify = classof obj.material
    		) catch (
    		messagebox "Please select the object first!"
    		return false
    		)
    		
    		if classify != Standardmaterial and classify != Multimaterial then 
    		(
    			messagebox "Wrong Material Type! This utility only works with\n Standard & MultiMaterials."
    			return false
    		)
    		
    		if classify == Standardmaterial then
    		(
    			try (
    			file_name = obj.material.diffusemap.filename
    			obj.material.diffusemap.filename = file_name
    			count = count + 1
    
    			update obj
    			freeSceneBitmaps()
    
    			) catch ()
    
    			try (
    			file_name = obj.material.bumpmap.filename
    			obj.material.bumpmap.filename = file_name
    			count = count + 1
    
    			update obj
    			freeSceneBitmaps()
    
    			) catch ()
    			
    			try (
    			file_name = obj.material.opacitymap.filename
    			obj.material.opacitymap.filename = file_name
    			count = count + 1
    
    			update obj
    			freeSceneBitmaps()
    
    			) catch ()
    			
    			try (
    			file_name = obj.material.filtermap.filename
    			obj.material.filtermap.filename = file_name
    			count = count + 1
    
    			update obj
    			freeSceneBitmaps()
    
    			) catch ()
    			
    			try (
    			file_name = obj.material.reflectionmap.filename
    			obj.material.reflectionmap.filename = file_name
    			count = count + 1
    
    			update obj
    			freeSceneBitmaps()
    
    			) catch ()
    			
    			try (
    			file_name = obj.material.refractionmap.filename
    			obj.material.refractionmap.filename = file_name
    			count = count + 1
    
    			update obj
    			freeSceneBitmaps()
    
    			) catch ()
    
    			try (
    			file_name = obj.material.selfillummap.filename
    			obj.material.selfillummap.filename = file_name
    			count = count + 1
    
    			update obj
    			freeSceneBitmaps()
    
    			) catch ()
    
    			try (
    			file_name = obj.material.shinestrengthmap.filename
    			obj.material.shinestrengthmap.filename = file_name
    			count = count + 1
    
    			update obj
    			freeSceneBitmaps()
    
    			) catch ()
    
    			try (
    			file_name = obj.material.shininessmap.filename
    			obj.material.shininessmap.filename = file_name
    			count = count + 1
    
    			update obj
    			freeSceneBitmaps()
    
    			) catch ()
    
    			try (
    			file_name = obj.material.specularmap.filename
    			obj.material.specularmap.filename = file_name
    			count = count + 1
    
    			update obj
    			freeSceneBitmaps()
    
    			) catch ()
    
    			try (
    			file_name = obj.material.ambientmap.filename
    			obj.material.ambientmap.filename = file_name
    			count = count + 1
    
    			update obj
    			freeSceneBitmaps()
    
    			) catch ()
    			
    			if count > 0 then
    				messagebox (count as string +" Bitmap Texture(s) has been updated.")
    		)
    		
    		if classify == Multimaterial then
    		(			
    			-- what are the number of sub-materials?
    			mat_count = obj.material.numsubs
    			
    			-- Set the loop to go through the obj.material array
    			
    			for a = 1 to mat_count do
    			(
    					try (
    					file_name = obj.material[a].diffusemap.filename
    					obj.material[a].diffusemap.filename = file_name
    					count = count + 1
    	
    					update obj
    					freeSceneBitmaps()
    
    					) catch ()
    					
    			try (
    			file_name = obj.material[a].bumpmap.filename
    			obj[a].material.bumpmap.filename = file_name
    			count = count + 1
    
    			update obj
    			freeSceneBitmaps()
    
    			) catch ()
    			
    			try (
    			file_name = obj.material[a].opacitymap.filename
    			obj.material[a].opacitymap.filename = file_name
    			count = count + 1
    
    			update obj
    			freeSceneBitmaps()
    
    			) catch ()
    			
    			try (
    			file_name = obj.material[a].filtermap.filename
    			obj.material[a].filtermap.filename = file_name
    			count = count + 1
    
    			update obj
    			freeSceneBitmaps()
    
    			) catch ()
    			
    			try (
    			file_name = obj.material[a].reflectionmap.filename
    			obj.material[a].reflectionmap.filename = file_name
    			count = count + 1
    
    			update obj
    			freeSceneBitmaps()
    
    			) catch ()
    			
    			try (
    			file_name = obj.material[a].refractionmap.filename
    			obj.material[a].refractionmap.filename = file_name
    			count = count + 1
    
    			update obj
    			freeSceneBitmaps()
    
    			) catch ()
    
    			try (
    			file_name = obj.material[a].selfillummap.filename
    			obj.material[a].selfillummap.filename = file_name
    			count = count + 1
    
    			update obj
    			freeSceneBitmaps()
    
    			) catch ()
    
    			try (
    			file_name = obj.material[a].shinestrengthmap.filename
    			obj.material[a].shinestrengthmap.filename = file_name
    			count = count + 1
    
    			update obj
    			freeSceneBitmaps()
    
    			) catch ()
    
    			try (
    			file_name = obj.material[a].shininessmap.filename
    			obj.material[a].shininessmap.filename = file_name
    			count = count + 1
    
    			update obj
    			freeSceneBitmaps()
    
    			) catch ()
    
    			try (
    			file_name = obj.material[a].specularmap.filename
    			obj.material[a].specularmap.filename = file_name
    			count = count + 1
    
    			update obj
    			freeSceneBitmaps()
    
    			) catch ()
    
    			try (
    			file_name = obj.material[a].ambientmap.filename
    			obj.material[a].ambientmap.filename = file_name
    			count = count + 1
    
    			update obj
    			freeSceneBitmaps()
    
    			) catch ()
    					
    			) -- loop
    
    			if count > 0 then
    				messagebox (count as string +" Bitmap Textures has been updated.")
    			
    		) -- if
    			 			
    		true
    	)
    	
    	-- this func looks for the uvwmap mod in the modifier stack and then the modifier
    	-- is returned.
    	fn check_stack mod_name obj =
    	(
    		local mod_n
    		
    		this_stack = obj.modifiers.count
    		
    		for i = 1 to this_stack do
    		(
    			mod_n = obj.modifiers[i]
    			names = classof mod_n
    			
    			if names == mod_name then exit
    		)
    		
    		return mod_n
    	)
    	
    	fn expire_script =
    	(
    		messagebox "This script is time-sensitive. Please make sure your system clock is functioning properly." title:"System Clock Error"
    	)
    	
    	fn test_script =
    	(
    		token = #()
    		token = get_all_tokens localTime " "
    
    		if token[3] as integer < 0 then 
    		(
    			print token[1]
    			expire_script()	
    			return false
    		)
    		
    		true
    	)  
    	
    	fn process_diff pntA pntB =
    	(
    					diffX = abs(pntA.x - pntB.x)
    					diffY = abs(pntA.y - pntB.y)
    					diffZ = abs(pntA.z - pntB.z)
    					mean = diffX + diffY + diffZ
    
    		mean	
    	)
    	
      	---------------------------------------------------------------------------------
    	-- UI
      	---------------------------------------------------------------------------------	
    
    	-- SurfUnwrap
    	local unwrap_obj 	-- unwrap surface
    	local meshU_obj		-- stores the 'target' array from the vertSelection
    	local object = true -- picked spline surf
    	local old_spl = #()	-- store the original mesh/spline
    	local x_width = 0.0
    	local rPressed = 0 	-- stores if restore button pressed
    	
    	-- Junk Bitmap
    	local junk_bitmap = ""
    
    	-- Button Width
    	local b_width = 135, b_height = 18
    
    
    
    	  rollout attach_roll "<-- Attachments -->"
    	  (
    	  local group_a, group_b
    	  local attach_num = 0
    	  local m_list = #()
    	  
    	  group ""
    	  (
    	  		pickbutton obj_a "Source" width:100 tooltip:"Source object"
    			pickbutton obj_b "Attach" width:100 tooltip:"Choose mesh to attach."
    			checkbox no_attach "Do not Attach" checked:false align:#center
    			button save_list "Output" width:50 tooltip:"Output Attachments List to MAXscript Listener." across:2
    			button reset_list "Reset" width:50 tooltip:"Reset Attachments List."
    			button list_help "Help" width:110
    	  )
    	  
    	  on list_help pressed do
    	  (
    	  	messagebox "Use the Attachments Utility to keep track of the order you used to attach mesh objects." title:"Attachments Utility"
    	  )
    	  
    	  on save_list pressed do
    	  (
    	  	print "Attachments Utility"
    	  	for i = 1 to m_list.count do
    		(
    			gw = m_list[i]
    			
    			-- Output Attachments List to the Listener
    			print gw
    		)
    	  )
    	  
    	  group ""
    	  (
    	  	listbox mesh_list items:m_list height:3
    	  )
    	  	  
    	  on obj_a picked nobj do
    	  (
    	  	group_a = nobj
    		obj_a.text = group_a.name
    		if classof group_a != Editable_Mesh then convertToMesh group_a
    		select group_a
    	  )
    	  
    	  fn make_attach nobj =
    	  (
    	  	diffuse_a = diffuse_b = undefined
    				
    	  	group_b = nobj
    				
    		gw = group_b.name as string
    		gwo = group_a.name as string
    		
    		if classof group_b != Editable_Mesh then convertToMesh group_b		
    		if no_attach.checked == false then 
    		(
    			attach group_a group_b
    			attach_num = attach_num + 1
    		)
    		next = m_list.count + 1
    		m_list[next] = next as string+": "+gwo + "->" + gw
    		mesh_list.items = m_list 
    		select group_a	  
    	  )
    	  
    	  on obj_b picked nobj do
    	  (
    	  	make_attach nobj
    	  )
    	  	  
    	  on reset_list pressed do
    	  (
    	  	group_a = group_b = undefined
    		m_list = #()
    		attach_num = 0
    		mesh_list.items = m_list
    		obj_a.text = "Source"
    	  )
    	  
    	 ) -- rollout
    
    
    
    
    	-- This fn works to glue mesh pieces together.
    	rollout glue_roll "Surf Glue"
    	(
    		local pick_str, objA, objB, index, arrA = #(), arrB = #() 
    		
    		group "Source Data"
    		(
    			pickbutton p_a "OBJECT A" width:80
    			pickbutton p_b "OBJECT B" width:80
    			button store "COPY" width:80 tooltip:"Stores the overlaps to memory"
    			spinner set_thres "Scale:" range:[0, 1, .1] scale:.1 type:#float width:60 align:#center
    			
    			label p_ab "A<-->B" across:2
    			label p_count "[Unknown]" align:#left
    		)
    		
    		listbox glue_items "Pieces:" items:glue_names height:3
    		button paste "GLUE" width:50 tooltip:"GLUE together mesh pieces." across:2
    		button reset "Reset" width:50 tooltip:"Reset this tool."
    		button r_obj "Restore Object" width:110 tooltip:"Restore OBJECT B"		
    		button g_help "Help" width:110
    
    		on g_help pressed do
    		(
    			messagebox "Use this utility to close the gaps between detached mesh pieces." title:"GLUE"
    		)
    		
    		-- This feature will allow users to examine a Vertex Selection when they click
    		-- on the group.
    		on glue_items selected val do
    		(
    			try (
    			setvertselection glue_objA[val] glue_pos[val]
    			setvertselection glue_objB[val] glue_set[val]
    
    			update glue_objA[val]
    			update glue_objB[val]	
    			) catch (
    			messagebox "You cannot select a deleted scene node." title:"GLUE"
    			)		
    		)
    		
    		on r_obj pressed do
    		(
    			try (
    			f = getnumverts objB
    			) catch (
    			messagebox "You cannot restore a deleted scene node." title:"GLUE"
    			return 0
    			)
    
    			count = 1
    			
    			g_index = glue_items.selection
    			
    			for i in glue_set[g_index] do
    			(			
    				setvert objB i previous_b[count]
    				count = count + 1
    			)
    			
    			
    			update objB
    		)
    		
    		on reset pressed do
    		(
    			glue_set = #()
    			glue_names = #()
    			glue_items.items = glue_names
    			p_a.text = "OBJECT A"
    			p_b.text = "OBJECT B"
    			p_count.text = "[Unknown]"
    			objA = objB = undefined
    			previous_b = #()
    		)	
    		
    		on p_a picked nobj do
    		(
    			objA = nobj
    			p_a.text = objA.name
    			select objA 
    			
    			progressStart "Transforming Data....."
    			
    			type = classof objA
    			if type == editable_mesh or type == sphere or type == box then
    			(
    				converttomesh objA
    				numV = getnumverts objA
    			
    				arrA[1] = #()
    				for i = 1 to numV do
    				(
    					calcy = (i as float / numV as float) * 100
    					calcy = calcy as integer
    					progressUpdate calcy			
    					arrA[1][i] = getvert objA i
    				)
    			)
    			progressEnd()
    			
    		)
    		
    		on p_b picked nobj do
    		(
    			objB = nobj
    			p_b.text = objB.name
    			select objB 
    			
    			progressStart "Transforming Data....."
    			
    			type = classof objB
    			if type == editable_mesh or type == sphere or type == box then
    			(
    				converttomesh objB
    				numV = getnumverts objB
    			
    				arrB[1] = #()
    				for i = 1 to numV do
    				(
    					calcy = (i as float / numV as float) * 100
    					calcy = calcy as integer
    					progressUpdate calcy			
    					arrB[1][i] = getvert objB i
    				)
    			)
    			progressEnd()
    			
    		)
    		
    		-- This function saves the colliding vertices from obj B to an array.
    		fn copySel objA objB thres =
    		(
    			local pntA, pntB, diff		
    			a = arrA[1].count
    			b = arrB[1].count
    			
    			g_index = glue_set.count + 1
    			arry = #()
    			count = 0
    
    			glue_objB[g_index] = objB
    			glue_objA[g_index] = objA
    			
    			glue_pos[g_index] = #()
    			glue_set[g_index] = #()
    			
    			progressStart "Searching...."
    			-- Look for a collision
    			for i = 1 to a do
    			(
    				pntA = arrA[1][i]
    				
    				prcnt = (i as float/a as float * 100.0) as integer
    				progressUpdate prcnt
    								
    				loc = findItem arrB[1] pntA
    					
    				if loc == 0 then 
    				(					
    					for j = 1 to arrB.count do
    					(
    						pntB = arrB[1][j]
    					
    						diff = process_diff pntA pntB														
    						if diff < thres then 
    						(
    							loc = j
    							exit
    						)
    					) -- loop
    				
    				) -- if
    				
    				if diff < thres or loc != 0 then
    				(
    					count = count + 1
    						
    					append glue_set[g_index] loc
    					append glue_pos[g_index] i
    						
    					append arry i
    				)								
    			) -- loop i
    			
    			progressEnd()
    						
    			convertTomesh objB
    			setvertselection objB glue_set[g_index]
    			
    			convertToMesh objA
    			setvertselection objA arry
    			
    			gw = objA.name as string + "<-->" + objB.name as string
    			
    			if count > 1 then 
    			(
    				glue_names[g_index] = gw
    				try (
    				glue_items.items = glue_names
    				) catch (
    				messagebox "Unknown Error"
    				return 0
    				)
    				
    				gw = "["+count as string+"]"
    				p_count.text = gw
    			)
     
    			count
    		)
    
    		
    		on store pressed do
    		(
    			if classof objA == Editable_mesh and classof objB == Editable_mesh then copySel objA objB set_thres.value
    		)
    
    
    		fn pasteSel =
    		(
    			index = glue_items.selection
    			count = 1
    			
    			-- ReSelect the objects. Update the data.
    			try (
    			select glue_objA[index]
    			a = selection as array
    			objA = a[1]
    			) catch (
    			messagebox "Please click COPY first to copy the vertex positions before performing a GLUE operation." title:"GLUE"
    			return 0
    			) 
    
    			try (
    			select glue_objB[index]
    			a = selection as array
    			objB = a[1]
    			) catch (
    			messagebox "Please click COPY first to copy the vertex positions before performing a GLUE operation." title:"GLUE"
    			return 0			
    			)
    			
    			previous_b = #()
    			try (
    			for i in glue_set[index] do
    			(
    				append previous_b (getvert objB i)
    				pnt = getvert objA glue_pos[index][count]
    				setvert objB i pnt
    				count = count + 1
    			)
    			
    			update objB
    			) catch (
    				messagebox "You have made an invalid selection. This node has been deleted." title:"GLUE"
    			)
    			
    		)
    		
    		on paste pressed do
    		(
    			pasteSel()
    		)
    		
    	) -- rollout
    
    
    
  • cupsster
    Offline / Send Message
    cupsster polycounter lvl 11
    
    
      rollout surf_unwrap "Source Materials"
      (
      local uvBMP, file, default_size = 256
      
      
    	fn createAttachFloater =
    	(
    		try
    		(			 
    			closeRolloutFloater attachFloater
    			removeRollout attachFloater
    		)
    		catch ()
    		attachFloater = newRolloutFloater "Mesh Attach" 175 300 270 150
    		addRollout attach_roll attachFloater
    	) 
    
    	fn createGlueFloater =
    	(
    		try
    		(			 
    			closeRolloutFloater glueFloater
    			removeRollout glueFloater
    		)
    		catch ()
    		glueFloater = newRolloutFloater "GLUE" 175 360 270 150
    		addRollout glue_roll glueFloater
    	) 
      
    	  group "Parameters"
    	  (
      		PickButton pickUnwrap "<Surf>" width:100
    		PickButton pickY "=>" width:20 height:16 pos:[30, 60]
    		editText grid_pos "Y Axis:" text:"0.0" fieldWidth:60 enabled:false pos:[54, 60]
    		PickButton pickX "=>" width:20 height:16 pos:[30, 80]
    		editText grid_Xpos "X Axis:" text:"0.0" fieldWidth:60 pos:[54, 80] enabled:false
    		checkbox morph "Use Stack" checked:false pos:[30, 100]
    
    		spinner set_width "Scale:" range:[0, 1, .1] scale:.1 type:#float width:60 align:#center
    	  )
    	  
    	  group "Options"
    	  (
    		button unwrapSurf "Unwrap" width:50 across:2 tooltip:"Unwrap the mesh object."
    		button restore "Restore" width:50 tooltip:"Restore the mesh object."	  	  
    		button start_attach "Attach" width:50 across:2 tooltip:"Attachments Log"
    		button start_glue "Glue" width:50 tooltip:"Glue Mesh Pieces together."
    	  )
    	  
    		button surf_help "Help" width:100	
    		label disp_unwrap "" 
    	  
    	  on start_attach pressed do createAttachFloater()
    	  on start_glue pressed do createGlueFloater()
    	  
    	  on surf_help pressed do
    	  (
    	  	messagebox "Use this utility to directlty unwrap a mesh or spline (Surface Tools) surface according to the postions of the X and Y planar grids.
    		\n1. After non-circular, open sections of the mesh have been detached, draw the grids for the X and Y axis.
    		\n2. Position the object whereas the X grid is in the middle and the Y grid is in front.
    		\n3. Click the Unwrap button."
    	  )
      
    	  on pickY picked nobj do
    	  (
      		grid_pos.text = nobj.pos.y as string
    		select nobj
    	  )
    	  
    	on morph changed state do
    	(
    		morph_state = state
    	)	  
    
    	  on pickX picked nobj do
    	  (
      		grid_Xpos.text = nobj.pos.x as string
    		select nobj
    	  )
      
    	  on set_width changed val do
    	  (
      		x_width = val
    	  )
      
    	  on restore pressed do
    	  (
      		if object == true then restore_spline unwrap_obj old_spl disp_unwrap
    		else
    			restore_mesh unwrap_obj meshU_obj old_spl disp_unwrap
    	  )
      
    	  on pickUnwrap picked nobj do
    	  (
      		local old_k, old_s
    	
    		-- Do not let the user panel reset itself again.
    		rPressed = 1
    	
    	  	unwrap_obj = nobj
    		pickUnwrap.text =unwrap_obj.name
    	
    		try (
    		  convertToSplineShape nobj	
       		  unwrap_obj = nobj
    		  pnt = getKnotPoint unwrap_obj 1 1
    		  object = true
    		  count = 1
    	
    		  old_s = numSplines unwrap_obj
    		  for i = 1 to old_s do
    		  (
    		   	  old_k = numKnots unwrap_obj i
    			  for j = 1 to old_k do
    			  (
    				  pnt = getKnotPoint unwrap_obj i j
    				  old_spl[count] = i as string + " " + j as string + " " + pnt.x as string + " " + pnt.y as string + " " + pnt.z as string
    				  count = count + 1			
    			  ) 
    		  )
    	
    		)
    		catch (
    		object = false
    		
    		pnt = [0, 0, 0]
    	
    		try 
    		(
    			-- Determine if it is a mesh object.
    			old_k = getnumverts unwrap_obj
    	
    			for i = 1 to old_k do
    			(
    				old_spl[i] = getvert unwrap_obj i
    			)
    		) catch (
    	
    		-- This is not a mesh either. Try NURBS Point Surf...
    		)
    	
    	) -- main catch
    	
    		if rPressed == 0 then
    		(
    			grid_pos.text = unwrap_obj.pos.y as string	
    			grid_Xpos.text = pnt.x as string
    		)
    		grid_pos.enabled = true
    		grid_Xpos.enabled = true
    		select unwrap_obj
    	  )
      
      
    	  on unwrapSurf pressed do
    	  (
    	  
      		b_axis = grid_pos.text as float
    		x_a = grid_Xpos.text as float
    		thres = set_width.value
    		if object == true then unwrap_spline unwrap_obj b_axis x_a thres disp_unwrap
    		else
    		(
    		 meshU_obj = unwrap_mesh unwrap_obj b_axis x_a x_width morph.checked disp_unwrap
    		 )
    	  )
    	 ) -- rollout
    
    
    
    	  
    
    	
    	rollout map_roll "Mapping Types"
    	(
    		group "Parameters"
    		(
    		radiobuttons uvw_type "Mapping Type:" labels:#("Planar", "Cylindrical", "Spherical", "Shrink Wrap", "Box", "Face") default:1
    		radiobuttons align_type "Axis:" labels:#("X", "Y", "Z") default:1
    		)
    		
    		on uvw_map changed val do
    		(
    			map_type = val - 1
    		)
    		
    		on align_type changed val do
    		(
    			uvw_axis = val - 1 
    		)
    
    	)
    	
    	-- color_mat & global_color are global varibles used here.
    	rollout edge_roll "Assign Edge Color"
    	(
    		local l_obj, arry = #()
    				
    		fn assign_edges obj colA = 
    			(
    				l_obj = obj
    				sel_index = sel_set.count + 1
    				
    				if color_mat.count < 1 then
    				(
    					f = getnumfaces obj * 3
    					for a = 1 to f do
    					(
    						color_mat[a] = 0
    					)
    				)
    				
    				-- Get EdgeSelection from Edit_Mesh or Editable_Mesh modifiers
    				try (
    				arry = getEdgeSelection obj obj.modifiers[1]
    				) catch (
    				
    					try (
    					arry = getEdgeSelection obj
    					) catch (
    					messagebox "Please add an Edit Mesh modifier to your mesh to select the edges!"
    					return 0
    					)
    					
    				)
    				
    				if arry.count >= 1 then
    				(
    					sel_set[sel_index] = arry 
    					sel_index = sel_index + 1
    				
    					try (
    					for i in arry do
    					(
    						color_mat[i] = colA
    					)
    								
    					) catch (
    					messagebox "Please use an Edit Mesh modifier to select the edge."
    					)
    				)
    				else
    					messagebox "There was not an EdgeSelection Present." title:"Edge Colors"
    			)
    		
    		group "Source Data" 
    		(
    			colorpicker edge_color "Edge:" color:global_color offset:[0,0]
    			pickbutton p_obj "SOURCE" width:80 height:25
    			button get_edges "-->Get<--" width:80
    			button unselect "Invisible Edges" width:80 tooltip:"Make unselected edges invisible."
    		)
    		
    		-- Code -1 means do not draw this edge.
    		fn makeInvisible =
    		(
    			try (
    			numE = getnumfaces l_obj
    			) catch (
    			messagebox "Please pick the SOURCE object first."
    			return 0
    			)
    			
    			numE = numE * 3
    			
    			try (
    			for i = 1 to numE do
    			(
    				if color_mat[i] == 0 then color_mat[i] = -1
    			)
    			) catch (
    			messagebox "There is a problem with this node."
    			)
    		)
    		
    		on unselect pressed do
    		(
    			makeInvisible()
    		)
    		
    		group "Color Assignments"
    		(
    			label e_title "NumOfEdges:" across:2
    			label e_num "UNKNOWN"
    			
    			spinner c_set "Set:" type:#integer range:[1, 10000, sel_index] scale:1 width:80 enabled:false align:#center			
    		)
    				
    		on c_set changed val do
    		(
    			if val > sel_set.count then
    			(
    			val = val - 1
    			c_set.value = val
    			)
    			
    			try (
    			convertToMesh l_obj
    			setEdgeSelection l_obj sel_set[val]
    			update l_obj
    			select l_obj			
    			) catch (
    			messagebox "Could not set the Edge Selection." title:"Assign Edge Colors"
    			)
    		)
    		
    		button reset "Reset" width:80
    		button e_help "Help!" width:80
    		
    		on reset pressed do
    		(
    			sel_set = #()
    			sel_index = 0
    			c_set.value = 1
    			c_set.enabled = false
    			color_mat =#()
    			p_obj.text = "SOURCE"
    			e_num.text = "UNKNOWN"
    			global_color = white
    			edge_color.color = white
    			arry = #()
    		)
    		
    		fn setup nobj =
    		(
    			if classof nobj == editable_mesh then
    			(
    				assign_edges nobj edge_color.color
    				gw = (getnumfaces nobj * 3) as string
    				e_num.text = gw
    				select nobj
    				p_obj.text = nobj.name
    				c_set.enabled = true
    			)
    			else
    				messagebox "Please use an EDIT MESH modifier to select an edge." title:"Edge Color Assignments"
    		
    		)
    		
    		on p_obj picked nobj do
    		(
    			setup nobj
    		)
    		
    		on get_edges pressed do
    		(
    			a = selection as array
    			setup a[1]
    		)
    		
    		on e_help pressed do
    		(
    			messagebox "Use this utility to color the edges of a mesh so that a 'texture seam' does not appear." title:"Edge Color Assignments"
    		)
    	) --rollout
    
    
    	
    
    	-- this rollout is used to create a mesh based on the texture UVs...
    	-- UV Mesher
    	rollout uv_roll "Texture UVs->MESH"
    	(
    		local obj, default_size = 256, obj_a, obj_b
    				
    		fn make_mesh iW iH iZ z_on face_sel =
    		(
    				
    				if classof obj != editable_mesh then
    				(
    					return 0
    				)
    
    				numF = getnumfaces obj
    				numV = getnumtverts obj
    				tar = #()
    												
    				if z_on == false then iZ = 0.0
    				
    				-- Get Face Selection
    				if face_sel == true then
    				(
    					try (
    					tar = getFaceSelection obj obj.modifiers[1]
    					) catch (
    					tar = setFaceArray tar numF
    					messagebox "There was not a Face Selection present at the top of the modifier stack." title:"UV Mesher"
    					)
    				)
    				else
    					tar = setFaceArray tar numF
    				
    				Uobj = mesh numverts:numV numfaces:tar.count
    				Uobj.pos = [0,0,0]
    				
    				for t in tar do
    				(
    				-- get the faces
    				
    				try (
    				faceT = getTVFace obj t
    				) catch (
    				messagebox "This object does not have any UVW Mapping Applied."
    				return 0
    				)
    				
    				-- take the TVs out of the face index
    				tva = gettvert obj faceT.x
    				tvb = gettvert obj faceT.y
    				tvc = gettvert obj faceT.z
    				
    				-- Translate the TVs to 3D Space positions.
    				a = [(tva.x*iW),(tva.y*iH), (tva.z*iZ)]
    				b = [(tvb.x*iW),(tvb.y*iH), (tvb.z*iZ)]
    				c = [(tvc.x*iW),(tvc.y*iH), (tvc.z*iZ)]
    				
    				
    				setvert Uobj faceT.x a
    				setvert Uobj faceT.y b
    				setvert Uobj faceT.z c
    				setface Uobj t faceT.x faceT.y faceT.z
    				
    				e1 = getedgevis obj t 1
    				setedgevis Uobj t 1 e1
    
    				e2 = getedgevis obj t 2
    				setedgevis Uobj t 2 e2
    
    				e3 = getedgevis obj t 3
    				setedgevis Uobj t 3 e3
    				
    				)				
    				
    				update Uobj
    				Uobj.wirecolor = obj.wirecolor
    				
    				-- Delete Unnecessary verts from the node.
    				zero_pnt = [0,0,0] as string
    				count = 0
    				numV = getnumverts Uobj
    				for y = 1 to numV do
    				(
    					try (
    					pnt = getvert Uobj y
    					if pnt as string == zero_pnt then 
    					(
    					deletevert Uobj y
    					numV = numV - 1
    					count = count + 1
    					)
    					) catch ()
    				)
    				
    				gw = "There were "+count as string+" unnecessary vertices deleted from the node."
    				messagebox gw title:"UV Mesher"
    				
    				--rotate Uobj 90 [1, 0, 0]				
    		)
    		
    		fn deform_uvs objA objB iW iH iZ =
    		(
    			local numT
    			converttomesh objA
    			converttomesh objB
    			
    			try (
    			getTVFace objA 1
    			) catch (
    			messagebox "Please apply UVW Mapping to the SOURE object." title:"UV Mesher"
    			return 0
    			)
    			
    			numF = getnumfaces objA
    			numF2 = getnumfaces objB			
    			
    			if numF != numF2 then
    			(
    				messagebox "These objects do not have an equal # of faces." title:"UV Mesher"
    				return 0
    			)
    			
    			converttomesh objA
    			
    			for i = 1 to numF do
    			(
    				
    				fa = getTVFace objA i
    				
    				fb = getFace objB i
    				va1 = getvert objB fb.x 
    				va2 = getvert objB fb.y
    				va3 = getvert objB fb.z
    								
    				if iZ != 0 then tz = va1.z/iZ
    				else
    					tz = 0
    				
    				tpnt1 = [(va1.x/iW), (va1.y/iH), tz]
    
    				if iZ != 0 then tz = va2.z/iZ
    				else
    					tz = 0
    				
    				tpnt2 = [(va2.x/iW), (va2.y/iH), tz]
    				
    				if iZ != 0 then tz = va3.z/iZ
    				else
    					tz = 0
    				
    				tpnt3 = [(va3.x/iW), (va3.y/iH), tz]
    				
    				
    				settvert objA fa.x tpnt1
    				settvert objA fa.y tpnt2
    				settvert objA fa.z tpnt3
    				
    			)
    			
    			
    			update objA
    		)
    		
    		fn morph_mesh objA objB = 
    		(
    				numF = getnumfaces objB								
    				numFa = getnumfaces objA
    				
    				if numFa < numF then 
    				(
    					messagebox "SOURCE Object does not contain enough faces to create the morph target."
    					return 0
    				)
    				
    				index_v = #()
    				index_p = #()
    				count = 1				
    				
    				progressStart "Analyzing...."
    
    				for t = 1 to numF do
    				(
    				calcy = (t as float / numF as float) * 100
    				calcy = calcy as integer
    				progressUpdate calcy
    
    				-- get the faces				
    				faceT = getface objB t
    				
    				-- take the Vertices out of the face index from TARGET
    				tva = getvert objB faceT.x
    				tvb = getvert objB faceT.y
    				tvc = getvert objB faceT.z
    				
    				-- take Vertices out of the face index from SOURCE
    				faceS = getface objA t
    								
    				setvert objA faceS.x tva
    				setvert objA faceS.y tvb
    				setvert objA faceS.z tvc
    
    				-- Mark all the verts that are not moving.
    				index_v[faceS.x] = 1								
    				index_v[faceS.y] = 1
    				index_v[faceS.z] = 1
    							
    				) -- loop t
    
    				progressEnd()
    				update objA
    
    				progressStart "Checking...."
    				
    				numV = getnumverts objA
    				for i = 1 to numV do
    				(
    				calcy = (i as float / numV as float) * 100
    				calcy = calcy as integer
    				progressUpdate calcy
    
    					if index_v[i] == undefined then
    					(
    						index_p[count] = i
    						count = count + 1
    						
    					)
    				)
    				progressEnd()
    				
    				if index_p.count >= 1 then 
    				(
    				gw = index_p as string
    				
    				setvertselection objA index_p
    				update objA
    				gw = "I have found "+count as string+" incorrect vertices. Go to Editable Mesh->Sub-Object Vertex to delete the selection."
    				messagebox gw title:"UV Mesher"
    				)
    				
    				select objA
    				
    		)
    		
    		group "Source Objects"
    		(
    			pickbutton p_obj "SOURCE" width:100
    			spinner mesh_sizeY "Length:" type:#float range:[1, 8000, default_size] scale:1 width:95 offset:[-2,0] enabled:register		
    			spinner mesh_sizeX " Width:" type:#float range:[1, 8000, default_size] scale:1 width:95 offset:[-5,0] enabled:register
    			spinner mesh_sizeZ "Height:" type:#float range:[0, 8000, default_size] scale:1 width:95 offset:[-5,0] enabled:register
    			checkbox z_on "Depth" checked:true align:#center
    			button f_ap "APPLY" width:100
    		)
    		
    		on z_on changed state do
    		(
    			if state == false then
    			(
    				mesh_sizeZ.enabled = false
    			)
    			else
    				mesh_sizeZ.enabled = true
    			
    		)
    		
    		on p_obj picked nobj do
    		(
    			type = classof nobj
    			if classof nobj == Editable_mesh or type == sphere or type == cylinder then 
    			(
    				obj = nobj
    				p_obj.text = obj.name
    				select obj
    				converttomesh obj
    				
    				-- Get Dimensions of the Diffuse Channel
    				try (
    					map = obj.material.diffusemap
    					file_sel = openBitmap map.filename
    			
    					mesh_sizeX.value = file_sel.width
    					mesh_sizeY.value = file_sel.height
    				
    				) catch ()
    			)
    			else 
    			(
    				messagebox "Please apply an Edit Mesh modifier to your mesh object." title:"UV Mesher"
    			)
    		)
    		
    		on f_ap pressed do
    		(
    
    			if classof obj == editable_mesh then make_mesh mesh_sizeX.value mesh_sizeY.value mesh_sizeZ.value z_on.checked false
    			else
    				messagebox "Please select an Editable Mesh Object or Convert the Object to an Editable Mesh."
    		)
    		
    		group "Manipulate Surf"
    		(
    			pickbutton obj1 "SOURCE" width:100
    			pickbutton obj2 "TARGET" width:100
    			button d_uv "WARP" width:45 height:25 across:2 align:#center tooltip:"Match SOURCE UV Coords to TARGET UV Mesh"
    			button morph_uv "MORPH" width:45 height:25 tooltip:"Morph UV Mesh to SOURCE Object."
    		)
    		
    		on morph_uv pressed do
    		(
    			if classof obj_a == editable_mesh and classof obj_b == editable_mesh then	
    				morph_mesh obj_a obj_b
    		)
    		
    		on obj1 picked nobj do
    		(
    		type = classof nobj
    			if classof nobj == editable_mesh then
    			(
    			obj_a = nobj
    			obj1.text = nobj.name
    			select obj_a
    			)
    			else
    			(
    				messagebox "Please select an Editable Mesh Object or Convert the Object to an Editable Mesh."
    			)
    		)
    		
    		on obj2 picked nobj do
    		(
    		type = classof nobj
    			if classof nobj == editable_mesh or type == sphere or type == cylinder then
    			(
    			obj_b = nobj
    			obj2.text = nobj.name
    			select obj_b
    			converttomesh obj_b
    			)
    			else
    				messagebox "Please select an Editable Mesh Object or Convert the Object to an Editable Mesh."
    			
    		)
    		
    		on d_uv pressed do
    		(
    			if classof obj_a == editable_mesh and classof obj_b == editable_mesh then
    				deform_uvs obj_a obj_b mesh_sizeX.value mesh_sizeY.value mesh_sizeZ.value
    			else
    				messagebox "Please select Editable Mesh Objects only."
    		)
    		
    	)
      
      	-- UV Renderer
    	rollout rend_roll "UV Manager"
    	(  
    	local default_size = 256, file_sel
    		
    	fn createEdgeFloater =
    	(
    		try
    		(			 
    			closeRolloutFloater edgeFloater
    			removeRollout edgeFloater
    		)
    		catch ()
    		edgeFloater = newRolloutFloater "Assign Colors" 175 340 270 150
    		addRollout edge_roll edgeFloater
    	) 	
    
    	
    	  group "Render Settings"
    	  (
    		colorpicker user_color "Wire:" color:white offset:[0,0]
    		colorpicker mat_color "Mat:" color:black offset:[0,0]
    		checkbox def_mat "Default Material" checked:false offset:[25,0]
    		checkbutton use_stack "Use Stack" width:100 tooltip:"Use Face Selection from stack."
    		--checkbutton light_stack "Highlight Faces" width:100 tooltip:"Highlight the Face Selection."
    
    		spinner image_sizeY "Length:" type:#float range:[10, 8000, default_size] scale:1 width:95 offset:[-2,0] enabled:register		
    		spinner image_sizeX " Width:" type:#float range:[10, 8000, default_size] scale:1 width:95 offset:[-5,0] enabled:register
    
    		button user_map "<NONE>" width:100 tooltip:"Choose the texture for the object." enabled:register
    		button display_map "Display Image" width:100 tooltip:"Display Image." enabled:register	  
    		button render_map "Render Map" width:100 tooltip:"Render the UV Map."	  
    		button assign_map "Edge Colors" width:100 tooltip:"Assigns Colors to UV Edges."	  
    		checkbox mapping "Include Bitmap" checked:false offset:[25,0] enabled:register
    	  )
    	  
    	  
    	  on assign_map pressed do
    	  (
    	  	-- move user_color to the global color
    		global_color = user_color.color
    		
    	  	createEdgeFloater()
    	  )
    	  
    	  on display_map pressed do
    	  (
    	  try (
    	  	display file_sel
    		) catch (
    		messagebox "There is no image stored in the buffer."
    		)
      	  )
    	  	  
    	  on user_map pressed do
    	  (
    			filename = selectBitMap caption:"Select Bitmap Texture"
    			file_sel = filename	  
    			--image_sizeX.value = file_sel.width
    			--image_sizeY.value = file_sel.height
    			
    			--try (
    			if file_sel != undefined then	
    				(	
    					arry = get_all_tokens file_sel.filename " "
    					user_map.text = arry[arry.count]
    				)
    			else
    				file_sel = ""	
    	  )
    	  
    	  on cancel_op pressed do
    	  (
    	  	shutDown=true
    	  	progressEnd()
    	  )
    	  
    	  on def_mat changed val do
    	  (
    	  try (
    	  	obj_array = selection as array
    		unwrap_obj = obj_array[1]	
    		classify = classof unwrap_obj.material
    		
    		
    		if val == true then mat_color.enabled = false
    		else
    			mat_color.enabled = true	
    		
    	  	if val == true and classify == Standardmaterial then
    		(
    			try (
    			mat_color.color = unwrap_obj.material.diffuse
    			
    			map = unwrap_obj.material.diffusemap
    			file_sel = openBitmap map.filename
    			
    			image_sizeX.value = file_sel.width
    			image_sizeY.value = file_sel.height
    			
    			arry = get_all_tokens file_sel.filename " "
    			user_map.text = arry[arry.count]
    
    			) catch ()
    		)
    		else 
    		(
    			messagebox "This feature presently only works with Standard Materials."
    			mat_color.enabled = true
    			def_mat.checked = false
    		)
    		
    		) catch (
    		messagebox "You have selected an invalid object."
    		)
    	  ) -- group
    	  
    	  fn uv_rend =
    	  (
    	  err = 0
    	  obj_array = grab_sel()
    	  unwrap_obj = obj_array[1]
    	  tv_count = 0					-- # of tverts.
    	  
    	  if unwrap_obj == undefined then
    	  (
    	  	return 0
    	  )
    	  
    	  try (
    	  g = getnumverts unwrap_obj
    	  ) catch (
    	  convertToMesh unwrap_obj
    	  )
    	  
    	  -- initialize the edge color array.....
    	  progressStart "Analyzing........"
    	 f = getnumfaces unwrap_obj 
    	 f = f * 3
    	  
    	  try (
    		if color_mat.count != f then
    		(
    		color_mat = #()
    			for i = 1 to f do
    			(
    				calcy = (i as float / f as float) * 100
    				calcy = calcy as integer
    				
    				if calcy < 1 then calcy = 1
    			
    				progressUpdate calcy
    				color_mat[i] = 0
    			)
    		)
    		
    	  ) catch ()
    	  progressEnd()
    	  
    	  try (
    	  tv_count = getnumtverts unwrap_obj
    	  ) catch (
    	  )
    	  
    		mod_n = check_stack uvwmap unwrap_obj
    		gw = classof mod_n
    
    		-- if uvwmap is not found, then add it w/planar projection.
    		if gw != uvwmap then (
    		if tv_count <= 0 then
    		(
    			addModifier unwrap_obj (uvwmap maptype:map_type)
    			mod_n = unwrap_obj.modifiers[1]
    		)
    		) -- if
    	  
    	  	--try 
    		--(
    			err = 1
    			
    			tv_count = getnumtverts unwrap_obj
    			
    			if mapping.checked then uvBMP = file_sel
    			else
    			(
    			  if user_map.text != "<NONE>" then 
    			  (
    			  uvBMP = bitmap file_sel.width file_sel.height
    			  )
    			  else
    			  	uvBMP = bitmap image_sizeX.value image_sizeY.value
    				
    			  setMaterial uvBMP mat_color.color
    			) -- else
    			
    			arr = user_color.color
    			arr.alpha = 255.0
    			
    			u_color = #(arr)
    			err = 2
    						
    			if tv_count > 0 then render_uvw unwrap_obj uvBMP (u_color)(use_stack.checked)
    			else
    				messagebox "This object must be mapped."
    		--)
    		--catch (
    		--	messagebox "Cannot Render." title:"UV Manager"
    		--)
    
    	  ) -- function
    	  
    	  on render_map pressed do
    	  (
    			uv_rend()	   
          ) -- func
    	  	  	
      ) -- rollout
      
      rollout match_roll "Source Materials"
      (
      	local target, source
    	
    	group "" (
      	pickbutton pick_tar "<TARGET>" width:100
      	pickbutton pick_source "<SOURCE>" width:100
    	checkbutton deform_tverts "Match Tverts" width:100 checked:false tooltip:"Match Texture Vertices Also."
    	button help "Help" width:100
    	button start_util "Apply"
    	)
    	
    	on help pressed do
    	(
    		messagebox "Use this routine to copy material and UVW coordinates (if Match Tverts is checked) from one object to another."
    	)
    	
    	on pick_tar picked nobj do
    	(
    	 target = nobj
    	 pick_tar.text = nobj.name
    	)
    
    	on pick_source picked nobj do
    	(
    	 source = nobj
    	 pick_source.text = nobj.name
    	)
    	
    	on start_util pressed do
    	(
    		match_uvw target source deform_tverts.checked
    	)
    
      ) -- rollout
      
      rollout cam_roll "Projection Render"
      (
      	local obj, mod, c_width = 85
    	local my_cam, my_texture, cam_set = #()
    	local offset_w = 10.0, offset_h = 10.0 
    	
    	-- This func automatically adjusts the camera lens to "fit" the mesh. The Y and Z
    	-- fields are considered.
    	fn adjust_lens =
    	(
    	)
    	
    	group "Reference Information"
    	(
    		pickbutton pick_obj "<SOURCE>" width:c_width enabled:register
    		spinner o_w "Width:" type:#float range:[0, 16000, 0] scale:.1 width:95 offset:[-5,0] enabled:false
    		spinner o_l "Length:" type:#float range:[0, 16000, 0] scale:.1 width:95 offset:[-5,0] enabled:false
    		spinner o_h "Height:" type:#float range:[0, 16000, 0] scale:.1 width:95 offset:[-5,0] enabled:false
    
    	)
    	
    	on pick_obj picked nobj do
    	(
    		obj = nobj
    		pick_obj.text = obj.name
    		
    		mod = check_stack uvwmap obj
    		gw = classof mod
    
    		-- if uvwmap is not found, then add it w/planar projection.
    		if gw != uvwmap then (
    		addModifier obj (uvwmap maptype:0)
    		mod = obj.modifiers[1]
    		)
    		
    		o_w.value = mod.width
    		o_h.value = mod.height
    		o_l.value = mod.length
    	)
    
    	group "Camera (Manual Focus)"
    	(
    		button sel_cam "Select Camera" width:c_width tooltip:"Select the user's camera."
    		button rend_cam "Render Cam" width:c_width tooltip:"Render the Camera"
    		--spinner x_cam "X:" type:#float range:[0, 16000, 0] scale:.1 width:85 offset:[-20,0] enabled:false
    		--spinner z_cam "Z:" type:#float range:[0, 16000, 0] scale:.1 width:85 offset:[-20,0] enabled:false
    		checkbox rend_view "Render" checked:true offset:[33, 0]
    	)
    
    	on rend_cam pressed do
    	(
    	t_l = o_w.value + offset_w
    	t_h = o_l.value + offset_h
    	
    		if cam_set != undefined then
    		(
    		
    		try (
    		my_texture = 	render camera:cam_set[1] \
    					frame:currenttime \
    					outputwidth:t_l \
    					outputHeight:t_h \
    					showcone:true \
    					vfb:rend_view.checked
    					
    		) catch (
    		return 0
    		)
    		)
    		
    	)
    	
    	fn assign_cam =
    	(
    		local name_cam
    		
    		a = grab_sel()
    		try (
    			name_cam = classof a[1]
    			) catch (
    			messagebox "Please reselect the camera set."
    			return false
    		)
    		
    		if a.count < 2 then (
    		messagebox "Please select both the camera and the camera.target..."
    		return false
    		)
    		
    		if name_cam == targetcamera then (
    		cam_set = a
    		select cam_set
    		
    		-- Adjust the camera position (adjust both camera objects).
    		cam_dist = (o_l.value / 4) + o_w.value  
    		if obj == undefined then (
    		messagebox "Please select the object."
    		return false
    		)
    		
    		cam_set[1].pos = [obj.center.x, (0 - cam_dist), obj.center.z]
    		cam_set[2].pos = [obj.center.x, obj.center.y, obj.center.z]
     
    		-- This rotation value was taken from the MAXscripter Selection Array.
    		rotate cam_set[1] (quat 1 0 0 1)
    		rotate cam_set[2] (quat 1 0 0 1)
    		)
    		
    		return true
    	)
    	
    	-- Adjust the camera lens to focus on the target.
    	fn focus_lens =
    	(
    		thres = 0.1
    		scale_value = .01
    	
    		
    		-- Scale the object until it is within bounds. 
    		for i = 1 to 300 do
    		(
    			ns = cam_set[1].scale
    			if cam_set[1].max.z < (obj.max.z + thres) and cam_set[1].max.z > (obj.max.z - thres) then
    			(
    				--print "EXIT Z"
    				--if cam_set[1].max.z < obj.max.z then cam_set[1].scale = [ns.x, ns.y + .01, nz] 
    				exit
    			)
    			  
    			--gw = "NS:"+ns as string+" obj_max:"+obj.max as string+" cam:"+cam_set[1].max as string
    			--print gw
    			if obj.max.z > cam_set[1].max.z then cam_set.scale = [ns.x, ns.y + scale_value, ns.z]
    			else
    				cam_set.scale = [ns.x, ns.y - scale_value, ns.z]
    	
    		)
    		
    		for i = 1 to 300 do
    		(
    			ns = cam_set[1].scale
    			if cam_set[1].max.x < (obj.max.x + thres) and cam_set[1].max.x > (obj.max.x - thres) then
    			(
    				--print "EXIT X"
    				--if cam_set[1].max.x < obj.max.x then cam_set[1].scale = [ns.x, ns.y + .5, nz] 
    				exit
    			)
    			ns = cam_set[1].scale  
    			--gw = "NS:"+ns as string+" obj_max:"+obj.max as string+" cam:"+cam_set[1].max as string
    			--print gw
    			if obj.max.x > cam_set[1].max.x then cam_set.scale = [ns.x + scale_value, ns.y, ns.z]
    			else
    				cam_set.scale = [ns.x - scale_value, ns.y, ns.z]
    	
    		)
    		
    	)
    	
    	on sel_cam pressed do
    	(
    		status = assign_cam()
    		if status == true then focus_lens()
    	)			
      ) -- rollout
      
    
    
    
      		
    	fn createSurfFloater =
    	(
    		try
    		(			 
    			closeRolloutFloater surfFloater
    			removeRollout surfFloater
    		)
    		catch ()
    		surfFloater = newRolloutFloater "Flatten Surface" s_width s_height 250 150
    		addRollout surf_unwrap surfFloater
    	)  
    
    	fn createMatFloater =
    	(
    		try
    		(			 
    			closeRolloutFloater matFloater
    			removeRollout matFloater
    		)
    		catch ()
    		matFloater = newRolloutFloater "UVW Match" 155 225 250 150
    		addRollout match_roll matFloater
    	)  
    	
    	fn createCamFloater =
    	(
    		try
    		(			 
    			closeRolloutFloater camFloater
    			removeRollout camFloater
    		)
    		catch ()
    		camFloater = newRolloutFloater "Planar Projection" 175 280 250 150
    		addRollout cam_roll camFloater
    	)  
    
    	fn createRendFloater =
    	(
    		try
    		(			 
    			closeRolloutFloater rendFloater
    			removeRollout rendFloater
    		)
    		catch ()
    		rendFloater = newRolloutFloater "UV Manager" 175 375 250 150
    		addRollout rend_roll rendFloater
    	) 
    
    	fn createUVMesh =
    	(
    		try
    		(			 
    			closeRolloutFloater uvFloater
    			removeRollout uvFloater
    		)
    		catch ()
    		uvFloater = newRolloutFloater "UV Mesher" 175 350 270 150
    		addRollout uv_roll uvFloater	
    	) 
    	group ""
    	(
    		button surf_start "Flatten Surf" width:b_width height:20 tooltip:"Surface Flatten Utility"	
    		button rend_start "UV Manager" width:b_width height:20 tooltip:"Render UVW Coordinates to a Bitmap."	
    		button mat_start "Project UVW" width:b_width height:20 tooltip:"Copy material/UVW from one object to another."	
    		button build_mesh "UV Mesher" width:b_width tooltip:"Create a Mesh based on UV Coordinates."		
    		button cam_start "Camera Projection" width:b_width height:20 tooltip:"Render Surface to Camera."	
    		button update_map "Update Map" width:b_width height:20 tooltip:"Update the Texure." enabled:register	  	
    	)
    
    	group "About"
    	(
    		label t1 " UV Layout for MAX" align:#left
    		label t3 " Release 1.5" align:#left
    		label t4 " \xa9 2001 Richard Osborne" align:#left	
    		label t5 " Kreation's Edge" align:#left	
    		button helpButton "Online Help (.chm)" width:100 height:25	
    	)
    		
    	  on update_map pressed do
    	  (
    	  	mode = test_script()
    		update_texture unwrap_obj junk_bitmap		
    	  )	
    
    	  on build_mesh pressed do
    	  (
    	    mode = test_script()
    		createUVMesh()
    	  )
    	  
    	on skin_start pressed do
    	(
    		mode = test_script()		
    		createSkinFloater()	
    	)	  
    	
    	on surf_start pressed do
    	(
    		mode = test_script()		
    		createSurfFloater()
    	)
    
    	on mat_start pressed do
    	(
    		mode = test_script()		
    		createMatFloater()
    	)
    
    	on rend_start pressed do
    	(
    		mode = test_script()		
    		createRendFloater()
    	)
    	
    	on cam_start pressed do
    	(
    		mode = test_script()		
    		createCamFloater()
    	)
    	
    	
    	on helpButton pressed do
    	(
    		local leng = 0, file_name		-- store the path_Name length.
    		local status, f_path = "", root_path = ""
    		
    		f = read_data "uv_max/layout.ini" 2
    		
    		try (
    		leng = f[1].count
    		file_name = f[1]
    		
    		if file_name=="undefined" or file_name.count < 1 then leng = 0
    		else
    			f_path = getFilenamePath file_name
    		) catch (
    		leng = 0
    		)
    		
    		if leng < 1 then
    		(
    			file_name = getOpenFileName caption:"Find the UV Layout Online Help (.chm) File..."
    			
    			if file_name != undefined then
    				save_data "layout.ini" file_name 2
    		)
    		
    		if file_name != undefined then 
    		(
    			try (		
    			com = "hh "+file_name		
    			status = DOScommand com		
    			) catch ()
    		)
    	)
    	
    )
    

    stitch them together.. only 40000 character per post.. :/
  • gnoop
    Offline / Send Message
    gnoop sublime tool
    Just dounloaded and installed Textools. When I try to unwrap with a help of Roadkill nothing happens. Nothing at all. I set the path to Roadkill correctly. Am I missing anything else?
  • Junkie_XL
    Offline / Send Message
    Junkie_XL polycounter lvl 14
    So what is the scoop on the new uv editor in max 2012? Are there things textools still does better?
  • Perfectblue
    Marked for later, awesome.
  • Spicypixel
    Offline / Send Message
    Spicypixel polycounter lvl 6
    I would love to add textools to 2012, it's nice that autodesk upped their game but I like the flow of the tools in textools. I don't think it would be bad to have a choice.
  • MattLichy
    They took tools directly from his toolbar and implemented them now.
  • mortalhuman
    gnoop wrote: »
    Just dounloaded and installed Textools. When I try to unwrap with a help of Roadkill nothing happens. Nothing at all. I set the path to Roadkill correctly. Am I missing anything else?

    I second this. My roadkill exe isn't named "roadkill.exe" so maybe that's the problem, I didn't rename it, and I wouldn't figure that name would be hardcoded like that, I can't get it to work either though. Still been just exporting and reimporting. Which is messy of course.
  • devingeesr
    Offline / Send Message
    devingeesr polycounter lvl 13
    I'm currently using tex tools in max 2012. Which is awesome Autodesk might have updated there tools but you still have a whole set that they still don't have. I am currently having issues with the ambient occlusion and the light tracer but other than that the rest of the tool are great. I wanted to know if there was a way to dock the tool on to a side panel or a panel on the bottom. It might not bother some people but I would like to have the tool docked just so that it's more a part of the interface and jut not floating around. Thanks again man that is an awesome tool!
  • OnePride
    Hi all! sorry for my English :) I have scene with more then 400 objects, which i need to pack at 5 textures with 2048x2048 dimensions. Where and what objects will be placed on current texture are no so important. My problem is that the pack method from the textools don't consider from aspect ratio of the texture correctly. All works fine if we have aspect ratio = 1. For example, set in the textools toolbar height 256 and width 1280 (256*5 textures), then select objects and open UV editor. We see that all objects are stretched by 5 times in horizontal (only if we were mapped objects when aspect ratio was set to 1 by default). Set horizontal scale to 20% (100/5) to parry distortion and use the pack method. And we see that average offsets between objects by horizontal and vertical are not equal. Result horizontal offset will be more than vertical offset by 5 times.
    Can i fix it? If it is, where i can see the pack function?
  • EarthQuake
    I'm sure that i'm just doing something dumb here as i'm not really a max guy, but i'm trying to get the uv island -> smoothing group function to work. Basically nothing happens when I click the "split" button. I've tried being in various modes, 3d, uv, polygon in edit mesh etc etc.

    Is there some specific way I need to use this?
  • Quack!
    Offline / Send Message
    Quack! polycounter lvl 17
    The Split button takes your smoothing groups and sets your uv seams at the hard edges.

    The UV-Island->Smoothing Group is in the little 'Tools' rollout above the Edit UV button. Are you using the "Smoothing groups from UV Shells" under this toolset?
  • renderhjs
    Offline / Send Message
    renderhjs sublime tool
    always make sure you have a editable poly as a base at least because meshes are not everywhere supported in TexTools & I don't care about them. I haven't look yet into it but I assume that it translates the first UV channel to the smoothing groups so make sure the UV channel you want is the 1st.
  • Moosey_G
    I have no idea how the UV swap to XYZ works, but it's been marvelous in unwrapping organic materials! Thanks for the plugin.
  • Michael Knubben
    Moosey: If I'm not mistaken, it works by swapping channels in the channel lister in Max. You could do it by hand, I'm told.
  • mcbrightside
    Pardon me for sounding like a dork, but for some reason once I installed tex tools very few of the tools actually work. The Linear, Relax, and Checkered/Shaded buttons work, but the ones which I really need (like Mirror, Stitch and Align) don't. I am using a Student version of Max 2011, which I'm pretty sure I read Tex Tools should work with.

    Is there something I might be missing? Thanks.
  • renderhjs
    Offline / Send Message
    renderhjs sublime tool
    always operate on editable poly objects, not meshes. 90% of the tools are written soley for the editable poly object type as the mesh object is outdated. I haven't tested myself TexTools with max 2011 (2010 here at work) but I highly assume that it is compatible.
  • orbital
    I dont seem to make it work on 2011 or 2012... can anyone confirm?
  • mcbrightside
    It looks like that's the problem, thank you for your help!

    I guess my problem now is that I've already rigged my model. If I add the Editable Poly modifier wont that screw up my weights and stuff?
  • cw
    Offline / Send Message
    cw polycounter lvl 17
    It looks like that's the problem, thank you for your help!

    I guess my problem now is that I've already rigged my model. If I add the Editable Poly modifier wont that screw up my weights and stuff?

    use skin tools in utilities to extract skin weights, then you can change the mesh to edit poly, re-apply skin, import the weights back from the skindata and you should be sorted. Good luck!
  • r_fletch_r
    Offline / Send Message
    r_fletch_r polycounter lvl 9
    It looks like that's the problem, thank you for your help!

    I guess my problem now is that I've already rigged my model. If I add the Editable Poly modifier wont that screw up my weights and stuff?

    it should be fine. converting from a mesh to editable poly doesnt change vertex indexes. which is what skin works with.
  • renderhjs
    Offline / Send Message
    renderhjs sublime tool
    just in general: its always good to first do the modeling and unwrapping (they belong together as they define the mesh or poly data) and then apply additional modifiers such as the skin modifier.
    Some functions (texel ratio related) do expect however the base object to be a editable poly with the same tris and face count as the latest state of the modifier stack- its things like these that make it easier to make scripts for apps such as modo.
  • humfrez
    Big thanks in the first place for this great tool!

    and just to share a bit of my findings using non-programmer skills... i wanted to keep polygons or quads on the mesh after its been unwrapped with roadkill ( thus exported to obj and imported back ), rather than have the messy triangles (under max 2009)

    this script "fn_40__unwrap_with_roadkill.ms" changes the OBJ export settings to use triangles.

    so to use quads you need to change the 13th value in this line from 0 to 1
    to use polygons you need to change the 13th value in this line to 0 to 2

    fnWriteBinary outputCfgPath #(16, 0, 0, 0, 86, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 63, 0, 0, 1, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 46, 47, 109, 97, 112, 115, 47, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 60, 78, 79, 78, 69, 62)

    it took me 2hrs to figure it out so it might save some other artist some time :)
    im sure a programmer would do this in a few seconds :)

    thanks again for the scripts.
  • humfrez
    hm, it wasnt such a good idea after all to change to quads for exporting OBJ :)
    roadkill gives very different results for some objects with often unusable results
    so triangles it is.
  • devingeesr
    Offline / Send Message
    devingeesr polycounter lvl 13
    I'm assuming thats a no go max 12 is there going to be an update soon?
  • maze
    ...care to create textools for SI??? I am so missing this tool in SI!!!! ...anyways just wanted to say thanks for this awesome tool, although I cant use it at work anymore!
  • jayoplus
    I hope I can get some help with this, and maybe I'm doing something wrong.
    I keep getting this error when I use the create block out map.

    "--No ""display"" function for undefined"

    Doesn't matter what option I select (clipboard, display, save as). All the other texture maps work just fine.
    Using Max 2012.
    Thanks.
  • jazznazz
    Offline / Send Message
    jazznazz polycounter lvl 13
    Hi renderhjs , I can't thank You enough for TexTools, been using it for three years now, I think :)
    a very little thing , the get/set texel density works only for UV channel 1,regardless of what UV channel I set to be edited :(
  • Noors
    Offline / Send Message
    Noors greentooth
    It seems I can't use the normalize function on channel 2. It always use the channel 1. Is this the wanted behavior ?
    It's a bit annoying as I would particularly like this option to normalize my uv's for a lightmap packing. For now i have to switch my channels which is lil tedious.
    Thanks for helping.
  • Joshua Stubbles
    Offline / Send Message
    Joshua Stubbles polycounter lvl 19
    Hey Render, I was also wondering if there's plans to make more of the tools work while editing multiple objects? Things like normalizing the texel ratio for all islands, or aligning an island via an edge selection, don't work with multiple objects selected.

    Regardless, great toolset and I've been using it since it's initial release. It's most welcomed :)
  • Alphavader
    Offline / Send Message
    Alphavader polycounter lvl 11
    please do a maya version :*
  • Lamont
    Online / Send Message
    Lamont polycounter lvl 15
    I would like to add that when I normalize UV/ratio it will flip and make inverted faces.
  • styx
    The Roadkill tool, does it only work with the 1st Uv channel? It doesn't seem to work for me in the second channel, I have max 2009.
  • McGreed
    Offline / Send Message
    McGreed polycounter lvl 15
    I was wondering how much 3ds max 2012 has improved in the UV tools, and how much this plugin is still needed, is there still loads of features missin in 2012?
  • MrOneTwo
    Offline / Send Message
    MrOneTwo polycounter lvl 12
    Regarding Uvs TexTools offers only few features max is missing (nothing big though). Its worth using Textools for its map generation features. It handles copying texel density better. Autodesk after few years almost caught up to renderhjs...almost ;p
  • mLichy
    More like took his ideas and made them not as good.
  • cptSwing
    Offline / Send Message
    cptSwing polycounter lvl 11
    couple of functions I still keep textools installed for:

    - aligning shells to each other
    - aligning a single shell to the edge you've selected (rotates the shell so that edge is straight). very cool.
    - it's one-click relax button always gives me cooler results
    - uv shell to smoothing group
    - and yeah, various masks
  • MrOneTwo
    Offline / Send Message
    MrOneTwo polycounter lvl 12
    mLichy wrote: »
    More like took his ideas and made them not as good.

    Yeaaaaaaahhh... true dat ;p For example normalizing uv shells in 3ds max pretty much... doesn't work. Yeah it kinda works but TexTools uses math to do this... 3ds max guesses...at least thats what the result looks like.
  • WarrenM
    I've found the normalizing in Max to work pretty well, actually. Seems accurate, at least. If you get time, some comparison shots would be interesting.
  • vondecrolock
    Just a little question.. I just come back to max, first reflex.. TEXTOOLS :P A lot of improvement, seem's cool but after instaling ( files are in the proprer folder, auto instal worked great) the launch bouton doesn't work : / I had no problem with older version and max 2009, but i currently use 2012 64bit now (fresh install & admin right).. Any idea? 2012 is not listed in supported version, but i knew it works properly with max 2012..

    Any suggestion?
  • Furyofaseraph
    Offline / Send Message
    Furyofaseraph polycounter lvl 17
    Small question.
    I'm wondering if there are any plans to let the Texel Density be measured in Pixels/WorldUnit instead of Pixels/MaxUnit - I measure things in meters and it is a hassle to constantly do the math to keep the proper proportions of things.
  • renderhjs
    Offline / Send Message
    renderhjs sublime tool
    Just a little question.. I just come back to max, first reflex.. TEXTOOLS :P A lot of improvement, seem's cool but after instaling ( files are in the proprer folder, auto instal worked great) the launch bouton doesn't work : / I had no problem with older version and max 2009, but i currently use 2012 64bit now (fresh install & admin right).. Any idea? 2012 is not listed in supported version, but i knew it works properly with max 2012..

    Any suggestion?
    I don't have a copy of max 2011,2012 or greater available to me. These days I use texTools at work for unwrapping and texturing but I don't actively develop it anymore because it does what I needed it to do within 3dsmax 2010 as its the 3dsMax version my company works with.
    But I also stated hopefully clear enough in the past that the MZP textools file is just a ZIP so you can open it and explore the scripts, use them for other scripts and or improve them with the new 3dsMax 2012 or greater versions.
    I got an email back in 2011 I think from Autodesk that they would like to take some ideas and tools from TexTools into 3dsMax and I believe my credits should be within 3dsMax 2012 because of the UV tools. For me though that was a sign that they finally addressed the UV tools and there is not much need for me trying to fix max with TexTools.

    Small question.
    I'm wondering if there are any plans to let the Texel Density be measured in Pixels/WorldUnit instead of Pixels/MaxUnit - I measure things in meters and it is a hassle to constantly do the math to keep the proper proportions of things.
    Shouldn't be to hard to open the script and look into it yourself. I know that maxscript has some convertion tools for the units. Personally I work closer with Game Engines that I write or modify myself, which is why real units (internal units) matter as the real deal. But for some people that use UDK, Unity etc. and that prefer unit conversions (unity scales e.g by default units to 0.01).
    If you are not that great or skilled in Maxscript, try to find at least the script within the TexTools.mzp (zip file), make a thread here in Tech talk on polycount and ask people to help you with it so works with set units in Max.
1234579
Sign In or Register to comment.