Files
2025-09-29 00:52:08 +02:00

423 lines
15 KiB
Plaintext
Executable File

--=============================================================--
-- AUTH: Kyle Hansen - Rockstar San Diego: kyle.hansen@rockstarsandiego.com
-- 1.0 - 06-21-2012
-- maps selected faces using a uvw modifier, then sets the length,
-- width, utile and vtile of the modifier to specific settings read in from an xml.
-- currently the XML lives here:
-- X:\project\tools\wildwest\etc\config\general\uvStructureToolSettings.xml
--=============================================================--
filein (RsConfigGetWildWestDir() + "script/3dsmax/_config_files/wildwest_header.ms")
dotnet.LoadAssembly "System.Xml.XPath.dll"
global projectUVToolInstance
try (projectUVToolInstance.Close()) catch()
(
--LOCAL VAR USED AS A GLOBAL THROUGH THE SCRIPT
local uvwProjectionType = 0
--=============================================================--
-- Catches any selection based errors
----- Errors when:
-- Object is not editpoly, or editmesh
-- More than one object selected, or no objects are selected
-- No Faces in selection
--=============================================================--
fn meshErrorChecking =
(
local errorMsg = ""
local retVar = true
local selectedObject = (getCurrentSelection() as array)
if selectedObject.count == 0 then
(
print "Error: No objects selected!"
errorMsg = "Error: No objects selected!"
retVar = false
)
else if selectedObject.Count > 1 then
(
print "Error: Multiple objects selected, please make a face selection on one object only!"
errorMsg = "Error: Multiple objects selected, please make a face selection on one object only!"
retVar = false
)
else
(
selectedObject = (getCurrentSelection() as array)[1]
-- Check for invalid scale.
if selectedObject.transform.scalepart != [ 1, 1, 1 ] then (
errorMsg = "The object (" + selectedObject.name + ") needs to have its transform reset! Cannot continue."
retVar = false
)
if classOf selectedObject == Editable_Mesh then
(
local selectedFaces = getFaceSelection (selectedObject) as array
)
else if classOf selectedObject == Editable_Poly then
(
local selectedFaces = polyOp.getFaceSelection (selectedObject) as array
)
-- if the object is not a mesh or poly, then error, as well as test for facial selections
if classOf selectedObject != Editable_Mesh and classOf selectedObject != Editable_Poly then
(
errorMsg = "Error: Object must be an Editable Poly or Editable mesh. Please convert your object, and make a face selection."
retVar = false
)
else if selectedFaces == undefined then
(
errorMsg = "Error: No faces selected, Please make a selection of faces!"
retVar = false
)
else if selectedFaces.Count == 0 then
(
errorMsg = "Error: No faces selected, Please make a selection of faces!"
retVar = false
)
)
if retVar == false then
(
messageBox errorMsg
)
retVar
)
--=============================================================--
------ Reads XML attribute
-- selectedSet = dotNet xml document navigator selection set, attributeName = Case sensitive XML attribute name
--=============================================================--
fn getXMLAttribute selectedSet attributeName =
(
-- use the passed in set of nodes to search for our attribute
local attributeIterator = selectedSet.Current.Select("@" + attributeName)
if attributeIterator.Count > 0 then
(
attributeIterator.MoveNext()
local returnValue = attributeIterator.Current.Value
--print ("Value: " + attributeIterator.Current.Value)
)
returnValue
)
--=============================================================--
------ Loads in the required XML, returns array of arrays holding the type and values
--=============================================================--
fn loadTextureSettingsXML =
(
local projToolsRoot = theProjectToolsRoot
local textureSettingsFilePath = (projToolsRoot + "wildwest\\etc\\config\\general\\uvStructureToolSettings.xml")
-- create an xml instance
local textureSettingsXML = XmlDocument()
textureSettingsXML.init()
textureSettingsXML.Load textureSettingsFilePath
-- now create a XML document instance to read from
local textureSettingsDocument = textureSettingsXML.Document
-- create our navigator which we use to survey the xml document
local textureSettingsNavigator = textureSettingsDocument.CreateNavigator()
textureSettingsNavigator.MoveToRoot()
-- find all of the specific nodes we are looking for
local settingsSelectionSet = textureSettingsNavigator.Select(textureSettingsNavigator.Compile("/textureSettings/Setting"))
local settingsFileFormatted = #()
-- lets loop through all of the found nodes and then search for each attribute we are looking for, compiling it in an array of values
while (settingsSelectionSet.MoveNext()) do
(
local nameAttribute = getXMLAttribute settingsSelectionSet "Name"
local uAttribute = getXMLAttribute settingsSelectionSet "U"
local vAttribute = getXMLAttribute settingsSelectionSet "V"
append settingsFileFormatted #(nameAttribute, uAttribute, vAttribute)
)
settingsFileFormatted
)
--=============================================================--
-- Main button callback
----------
-- senderControl = the button control object, e = the returned dotnet handle
-- DESC: Looks at the "Tag" on the passed in control object, and gets the
-- uv info. String is organized in (u, v)
--=============================================================--
fn projectUVFromSetting senderControl e =
(
if meshErrorChecking() == true then
(
local selectedObject = (getCurrentSelection() as array)[1]
local dataString = getProperty senderControl "Tag"
local dataTok = filterString dataString " "
local uWidth = dataTok[1] as float
local vLength = dataTok[2] as float
local projectionAxis = dataTok[3] as integer
if superclassof selectedObject == geometryClass then
(
local faceId = undefined
if uvwProjectionType == 0 then
(
if classof selectedObject == Editable_Mesh then (
faceId = ( ( getFaceSelection selectedObject ) as array )[ 1 ]
) else if classof selectedObject == Editable_Poly then (
faceId = ( ( polyop.getFaceSelection selectedObject ) as array )[ 1 ]
)
if faceId != undefined do (
local worldUpVec = [ 0, 0, 1 ]
local faceNormal = undefined
if classof selectedObject == Editable_Mesh then (
faceNormal = in coordsys selectedObject ( getFaceNormal selectedObject faceId )
) else if classof selectedObject == Editable_Poly then (
faceNormal = in coordsys selectedObject ( polyop.getFaceNormal selectedObject faceId )
)
local rightVec = normalize ( cross worldUpVec faceNormal )
local upVec = normalize ( cross rightVec faceNormal )
local normalMatrix = matrix3 rightVec upVec faceNormal [ 0, 0, 0 ]
local uvMod = Uvwmap()
uvMod.length = vLength
uvMod.width = uWidth
uvMod.height = uWidth
uvMod.utile = uWidth
uvMod.vtile = vLength
uvMod.maptype = uvwProjectionType
modPanel.addModToSelection uvMod ui:on
uvMod.gizmo.transform = normalMatrix
collapseStack selectedObject
local uvwUnwrapMod = Unwrap_UVW()
subobjectLevel = 4
modpanel.addmodtoselection uvwUnwrapMod
subobjectLevel = 3
uvwUnwrapMod.unwrap.edit ()
)
)
else
(
if classof selectedObject == Editable_Mesh then (
faceId = ( ( getFaceSelection selectedObject ) as array )[ 1 ]
) else if classof selectedObject == Editable_Poly then (
faceId = ( ( polyop.getFaceSelection selectedObject ) as array )[ 1 ]
)
if faceId != undefined do (
local worldUpVec = [ 0, 0, 1 ]
local faceNormal = undefined
if classof selectedObject == Editable_Mesh then (
faceNormal = in coordsys selectedObject ( getFaceNormal selectedObject faceId )
) else if classof selectedObject == Editable_Poly then (
faceNormal = in coordsys selectedObject ( polyop.getFaceNormal selectedObject faceId )
)
local rightVec = normalize ( cross worldUpVec faceNormal )
local upVec = normalize ( cross rightVec faceNormal )
-- Always project with z up and x forward from the face.
local normalMatrix = matrix3 faceNormal rightVec [0,0,1] [ 0, 0, 0 ]
local uvMod = Uvwmap()
-- make the length and width equal because of the box map. Height is new length.
uvMod.length = uWidth
uvMod.width = uWidth
uvMod.height = vLength
uvMod.utile = uWidth
uvMod.vtile = vLength
uvMod.wtile = vLength
uvMod.maptype = uvwProjectionType
modPanel.addModToSelection uvMod ui:on
uvMod.gizmo.transform = normalMatrix
collapseStack selectedObject
local uvwUnwrapMod = Unwrap_UVW()
subobjectLevel = 4
modpanel.addmodtoselection uvwUnwrapMod
subobjectLevel = 3
uvwUnwrapMod.unwrap.edit ()
)
)
)
)
)
fn changeProjectionType senderControl e=
(
uvwProjectionType = getProperty senderControl "Tag" as Integer
)
fn projectUVToolCreatUI =
(
local panelOffset = 40
local mainForm = dotNetObject "maxCustomControls.maxForm"
mainForm.Size = dotNetObject "System.Drawing.Size" 264 (96 + panelOffset)
mainForm.Location = dotNetObject "System.Drawing.Point" 0 0
mainForm.Text = "UV Structure Mapper"
--======== ADD THE BANNER TO THE TOOL =================--
local rsBannerPanel = dotNetObject "Panel"
rsBannerPanel.Dock = rsBannerPanel.Dock.Top
local banner = makeRsBanner dn_Panel:rsBannerPanel width:250 wiki:"SD_UV_Structure_Mapper" filename:(getThisScriptFilename())
banner.setup()
mainForm.Controls.Add rsBannerPanel
--==========================================================--
-- Create elements of the base form.
--Main Panel
local mainPanel = dotNetObject "System.Windows.Forms.Panel"
mainPanel.Dock = dockStyle_Fill
mainPanel.Size = dotNetObject "System.Drawing.Size" 242 7
mainPanel.Location = dotNetObject "System.Drawing.Point"3 (48 + panelOffset)
mainPanel.BorderStyle = (dotNetClass "System.Windows.Forms.BorderStyle").FixedSingle
local titleLabel = dotNetObject "System.Windows.Forms.Label"
titleLabel.Text = "Texture Types"
titleLabel.Width = 80
titleLabel.Height = 18
titleLabel.Location = dotNetObject "System.Drawing.Point" 25 (40 + panelOffset)
titleLabel.ForeColor = (dotnetclass "system.drawing.color").white
titleLabel.BorderStyle = (dotNetClass "System.Windows.Forms.BorderStyle").FixedSingle
mainForm.Controls.Add titleLabel
local titleLabel2 = dotNetObject "System.Windows.Forms.Label"
titleLabel2.Text = "Project UV Map"
titleLabel2.Width = 85
titleLabel2.Height = 15
titleLabel2.Location = dotNetObject "System.Drawing.Point" 155 (40 + panelOffset)
titleLabel2.ForeColor = (dotnetclass "system.drawing.color").white
titleLabel2.BorderStyle = (dotNetClass "System.Windows.Forms.BorderStyle").FixedSingle
mainForm.Controls.Add titleLabel2
--=======================
local radioGroup = dotNetObject "System.Windows.Forms.GroupBox"
radioGroup.Width = 150
radioGroup.Height = 35
radioGroup.Location = dotNetObject "System.Drawing.Point" 8 35
radioGroup.Text = "Projection Type"
radioGroup.ForeColor = (dotnetclass "system.drawing.color").white
mainForm.Controls.Add radioGroup
dotNet.setLifetimeControl radioGroup #dotNet
local rdoProjectionType0 = dotNetObject "System.Windows.Forms.RadioButton"
rdoProjectionType0.Text = "Planar"
rdoProjectionType0.Width = 60
rdoProjectionType0.Height = 15
rdoProjectionType0.Checked = True
rdoProjectionType0.Location = dotNetObject "System.Drawing.Point" 5 14
rdoProjectionType0.Tag = 0
radioGroup.Controls.Add rdoProjectionType0
dotNet.AddEventHandler rdoProjectionType0 "Click" changeProjectionType
dotNet.setLifetimeControl rdoProjectionType0 #dotNet
local rdoProjectionType4 = dotNetObject "System.Windows.Forms.RadioButton"
rdoProjectionType4.Text = "Box"
rdoProjectionType4.Width = 60
rdoProjectionType4.Height = 15
rdoProjectionType4.Location = dotNetObject "System.Drawing.Point" 80 14
rdoProjectionType4.Tag = 4
radioGroup.Controls.Add rdoProjectionType4
dotNet.AddEventHandler rdoProjectionType4 "Click" changeProjectionType
dotNet.setLifetimeControl rdoProjectionType4 #dotNet
--=========================
local settingsXMLFile = loadTextureSettingsXML()
local lineIndex = 20
local buttonArray = #()
local labelArray = #()
--local buttonNameArray = #("X/Y", "Z")
local buttonNameArray = #("MAP")
for xmlLine in settingsXMLFile do
(
for i = 1 to buttonNameArray.count do
(
append labelArray (dotNetObject "Label")
local labelIndex = labelArray.count
-- lets use the labels to display the type of texture setting
labelArray[labelIndex] = dotNetObject "System.Windows.Forms.Label"
labelArray[labelIndex] .Text = xmlLine[1]
labelArray[labelIndex] .Width = 140
labelArray[labelIndex] .Location = dotNetObject "System.Drawing.Point" 10 (lineIndex - 5)
mainPanel.Controls.Add labelArray[labelIndex]
append buttonArray (dotNetObject "Button")
buttonArrayIndex = buttonArray.count
buttonArray[buttonArrayIndex].Width = 65
buttonArray[buttonArrayIndex].Height = 25
buttonArray[buttonArrayIndex].Text = (buttonNameArray[i])
buttonArray[buttonArrayIndex].FlatStyle = dotNetObject "System.Windows.Forms.FlatStyle" Flat
buttonArray[buttonArrayIndex].FlatAppearance.BorderColor = (dotnetclass "system.drawing.color").gray
buttonArray[buttonArrayIndex].Location = dotNetObject "System.Drawing.Point" (((i - 1) * 68) + 30 + labelArray[labelIndex].Width) (lineIndex - 12)
-- add the xml elements we found to the tag to use as "arguments" in the click callback
buttonArray[buttonArrayIndex].Tag = (xmlLine[2] + " " + xmlLine[3] + " " + (i) as string)
dotNet.AddEventHandler buttonArray[buttonArrayIndex] "Click" projectUVFromSetting
dotNet.setLifetimeControl buttonArray[buttonArrayIndex] #dotNet
mainPanel.Controls.Add buttonArray[buttonArrayIndex]
)
lineIndex = lineIndex + 32
mainPanel.Height += 32
mainForm.Height += 32
)
mainForm.Controls.Add mainPanel
--Display the user interface.
mainForm.showModeless()
return mainForm
)
projectUVToolInstance = projectUVToolCreatUI()
)