Bulk UV Tiling

Problem I’m solving

You can’t adjust the UV for multiple texture nodes from Slate Material all at once, which means that if you have the same maps for a wood texture, which has Diffuse, Normal, Glossiness, Reflection Map, etc, you’ll have to adjust the UV tiling for them 1 by one.

Solution

This script allows you to simply select all the map nodes (It only works with map, not material nodes because there’s no tiling in the material node itself) and change the value on the script to bulk adjust the value of tiling X and Y (or U and V). Additionally, you can also use the Real World Scale checkbox to change all the selected nodes to Real World Scale map coordinate, then change the value for each of them.

Installation

  1. Open 3Ds Max and go to Scripting > Run Scripts… > Choose the ‘BulkUVTiling_1.0.mzp‘ then click [Open]
  2. Right-click on the toolbar > Customize…
  3. Choose the tab ‘Toolbars’
  4. In the Category: dropdown, select ‘ManniiCode’
  5. Drag the script to the toolbar where ever you want!

Code (Maxscript)

macroscript BulkUVTiling
	Category:"ManniiCode"
	toolTip:"Bulk UV Tiling"
	icon: #("ManniiCode_BulkUVTiling",1)
(
	fn BulkUVadj adj_choice adj_value=
	(
		/*
		adj_choice = 
		1 = U <Float>
		2 = V <Float>
		3 = Realworld <Bool>
		*/
		
		viewNode = sme.GetView (sme.activeView)
		
		smeSelMats = #()
		
		for n = 1 to trackViewNodes[#sme][(sme.activeView)].numSubs do 
		(
			m = trackViewNodes[#sme][(sme.activeView)][n].reference 
			b = viewNode.GetNodeByRef m
			if b.selected and superclassof m == textureMap do append smeSelMats m
		)
		
		if adj_choice == 1 then
		(
			for i in smeSelMats do
			(
				try(i.coords.U_Tiling = adj_value)catch()
			)
		)
		
		if adj_choice == 2 then
		(
			for i in smeSelMats do
			(
				try(i.coords.V_Tiling = adj_value)catch()
			)
		)
		
		if adj_choice == 3 then
		(
			for i in smeSelMats do
			(
				try(i.coords.realWorldScale = adj_value)catch()
			)
		)

	)

	try(DestroyDialog BulkUVTiling) catch()
	rollout BulkUVTiling "Bulk UV Tiling"
	(
		local header_img = openBitmap((getdir #userIcons) + "\\SRCIMG\\" + "Header_BulkUVTiling.jpg")
		imgTag SaveMapProgressHeader "" bitmap:header_img height:70 width:350 pos:[0,0]
		
		local offset_x = 100
		local swap_pos_x = 228
		
		spinner spn_tiling_u_normal "Tiling U : " width:120 align:#left pos:[offset_x,85] range:[-99999,99999,1.0]
		spinner spn_tiling_v_normal "Tiling Y : " width:120 align:#left pos:[offset_x,105] range:[-99999,99999,1.0]
		spinner spn_tiling_u_realworld "Tiling U : " width:120 align:#left pos:[offset_x,1000] range:[-99999,99999,1.0] type:#worldunits
		spinner spn_tiling_v_realworld "Tiling Y : " width:120 align:#left pos:[offset_x,1500] range:[-99999,99999,1.0] type:#worldunits
		
		checkbox chkRealWorldScale "Real World Scale" align:#left pos:[offset_x,130]
		
		on spn_tiling_u_normal entered do
		(
			BulkUVadj 1 spn_tiling_u_normal.value
		)
		
		on spn_tiling_v_normal entered do
		(
			BulkUVadj 2 spn_tiling_v_normal.value
		)
		
		on spn_tiling_u_realworld entered do
		(
			result_val = 1/spn_tiling_u_realworld.value
			BulkUVadj 1 result_val
		)
		
		on spn_tiling_v_realworld entered do
		(
			result_val = 1/spn_tiling_v_realworld.value
			BulkUVadj 2 result_val
		)
		
		on chkRealWorldScale changed val do
		(
			BulkUVadj 3 val
			if val == true then
			(
				spn_tiling_u_normal.pos = [swap_pos_x,1000]
				spn_tiling_v_normal.pos = [swap_pos_x,1500]
				
				spn_tiling_u_realworld.pos = [swap_pos_x,85]
				spn_tiling_v_realworld.pos = [swap_pos_x,105]
			)
			else 
			(
				spn_tiling_u_normal.pos = [swap_pos_x,85]
				spn_tiling_v_normal.pos = [swap_pos_x,105]
				
				spn_tiling_u_realworld.pos = [swap_pos_x,1000]
				spn_tiling_v_realworld.pos = [swap_pos_x,1500]
			)
		)
		
	)CreateDialog BulkUVTiling 350 150
)

(Sink image by Skitterphoto from Pixabay)

Images