--=============================================================-- -- 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() )