-- Vertex Colour Toolkit -- try (destroyDialog RsVertClrToolRoll) catch () callbacks.removeScripts id:#RsVertClrTool RSTA_LoadCommonFunction #("fn_RSTA_vertexColours.ms") filein (::RsConfigGetWildwestDir() + "Script/3dsMax/Maps/Materials/vertexColour_blender.ms") --------------------------------------------------------------------------------------------------------------- --ROLLOUT DEFINITIONS --------------------------------------------------------------------------------------------------------------- -- Controls common to all tabs: rollout RsVertClrToolCommonRoll "" ( local keepOpenState = true -- Used to keep edit-rollout's colour-selection on changing tab: local rememberClr = blue dropDownList lstChans "Use Channel:" align:#left width:305 pos:[13,4] local btnWidth = 80 local btnHeight = 18 button btnShowChan "Show Channel" align:#right tooltip:"Show this vertex channel on selected objects" width:btnWidth height:btnHeight offset:[0,-4] button btnShowOff "Show Off" align:#right tooltip:"Don't show vertex channel on selected objects" width:btnWidth height:btnHeight offset:[0,-3] button btnShowVertPaint "VertexPaint" align:#right tooltip:"Show VertexPaint modifier for selected channel" width:btnWidth height:btnHeight offset:[0,-3] groupbox displayShadedGrp "Current Display Mode:" width:213 height:55 pos:(lstChans.pos + [0,22]) radioButtons rdoShaded "" labels:#("Material Colour (Textures)", "Object Colour (Colours)") align:#left offset:[5,-43] columns:1 fn getChan = ( return (lstChans.selection - 3) ) fn getShowClr = ( local showClr = copy rememberClr if (getChan() < 0) then ( local greyVal = (showClr.r + showClr.g + showClr.b) / 3.0 showClr = color greyVal greyVal greyVal ) return greyVal ) -- Set colour-set control's colour, if rollout is shown: fn SetClrCtrl = ( if (::RsVertClrToolEditRoll.Open) do ( RsVertClrToolEditRoll.ShowClr() ) ) fn SetupChanList namedChannels:#() = ( local namedVertChans = RsNamedMeshVertChannels + namedChannels local namedChanIds = for item in namedVertChans collect item.id local newItems = for n = -2 to (aMax namedChanIds) collect ((n as string) + ": ") local knownChans = #{} knownChans.count = newItems.count for item in namedVertChans do ( local chanIdx = item.id + 3 newItems[chanIdx] += item.name knownChans[chanIdx] = true ) for chanIdx = -knownChans do ( newItems[chanIdx] += "[unused channel]" ) lstChans.items = newItems ) -- Update 'Display Shaded' radiobuttons to match current viewport-setting: fn ShowDisplayShaded = ( rdoShaded.state = case displayColor.shaded of ( #material:1 #object:2 ) ) -- Set list/radiobutton selections to match requested values: fn SetChanControls chan: chanName: shaded: = ( local isValidChan = True if (chan == unsupplied) then ( -- Get channel-index from list: chan = getChan() ) else ( -- We'll choose this list-item: local newSel = (chan + 3) isValidChan = (newSel > 0) if isValidChan do ( -- Make sure we have enough list-items if (newSel > lstChans.items.count) do ( local newItems = lstChans.items for n = (lstChans.items.count + 1) to newSel do ( append newItems (((n - 3) as string) + ": [unused channel]") ) lstChans.items = newItems ) -- Select requested item: lstChans.selection = newSel ) ) -- Rename selected list-item: if isValidChan and (chanName != unsupplied) do ( local selChanStr = (lstChans.selection - 3) as String local items = lstChans.items items[lstChans.selection] = (selChanStr + ": " + chanName) lstChans.items = items ) -- Update 'Display Shaded' radiobuttons: ShowDisplayShaded() return OK ) fn ShowChannel chan: chanName: shaded: = ( -- Get channel-index from list: if (chan == unsupplied) do ( chan = GetChan() ) RsShowObjVertChannel chan updateListSel:False SetChanControls chan:chan chanName:chanName ) on LstChans selected val do ( setClrCtrl() ) on BtnShowChan pressed do ( ShowChannel() ) on btnShowOff pressed do ( ShowChannel chan:-3 ) on btnShowVertPaint pressed do ( local chan = (GetChan()) local chanName = ("Chan" + lstChans.selected) RsShowVertPaintMod chan chanName:chanName ) -- Auto-selects the channel shown on selected object(s) fn ShowCurrentObjChannel = ( local showChanObjs = for obj in selection where obj.showVertexColors collect obj local chanIdxs = for obj in showChanObjs collect ( case obj.vertexColorType of ( #alpha:(1) #illum:(2) #color:(3) #map_channel:(obj.vertexColorMapChannel + 3) Default:DontCollect ) ) chanIdxs = makeUniqueArray chanIdxs if (chanIdxs.count == 1) do ( lstChans.selection = chanIdxs[1] setClrCtrl() ) ) fn showShaded state = ( displayColor.shaded = case state of ( 1:#material 2:#object ) -- Trigger vertex-colours update: objects.showVertexColors = False if (displayColor.shaded == #object) do ( objects.showVertexColors = True ) return OK ) on rdoShaded changed state do ( showShaded state ) on RsVertClrToolCommonRoll open do ( chanIds = for item in RsNamedMeshVertChannels collect item.id setupChanList() -- Set selection to default channel: lstChans.selection = 3 ShowDisplayShaded() ShowCurrentObjChannel() callbacks.addScript #viewportChange "RsVertClrToolCommonRoll.ShowDisplayShaded()" id:#RsVertClrTool ) on RsVertClrToolCommonRoll close do ( callbacks.removeScripts id:#RsVertClrTool ) on RsVertClrToolCommonRoll rolledUp down do ( if (keepOpenState != Down) do (RsVertClrToolCommonRoll.open = keepOpenState) ) ) rollout RsVertClrWorkChannels "Split into Work Channels" ( button btnToWorkChans "Split RGB" width:120 height:20 across:2 \ tooltip:"Copies each of the selected channel's colours into channel 20, 21 and 22" button btnFromWorkChans "Combine RGB" width:120 height:20 \ tooltip:"Overwrites this channel by combining channel 20, 21 and 22 getting Red, Green and Blue from them respectively" label showRGB "Show:" align:#left pos:(btnToWorkChans.pos + [3,24]) across:4 button BtnShowRed "Red" align:#left width:20 height:20 pos:(showRGB.pos + [33,-3]) \ images:#((bitmap 16 16 color:(Red*0.8+ white*0.2)), undefined, 1, 1, 1, 1, 1, false) \ tooltip:"Show the Red channel created by Split RGB (Channel 20)" button BtnShowGreen "Green" align:#left width:20 height:20 pos:(showRGB.pos + [53,-3]) \ images:#((bitmap 16 16 color:(Green*0.8+ white*0.2)), undefined, 1, 1, 1, 1, 1, false) \ tooltip:"Show the Green channel created by Split RGB (Channel 21)" button BtnShowBlue "Blue" align:#left width:20 height:20 pos:(showRGB.pos + [73,-3]) \ images:#((bitmap 16 16 color:(Blue*0.8 + white*0.2)), undefined, 1, 1, 1, 1, 1, false) \ tooltip:"Show the Blue channel created by Split RGB (Channel 22)" -- 'Split/Combine RGB' use these working-channels: local workChanItems = #( (dataPair id:20 name:"Working Channel: Red"), \ (dataPair id:21 name:"Working Channel: Green"), \ (dataPair id:22 name:"Working Channel: Blue") ) local workChans = for chan in workChanItems collect chan.id on btnToWorkChans pressed do ( -- Rename list-items: RsVertClrToolCommonRoll.setupChanList namedChannels:workChanItems local chan = RsVertClrToolCommonRoll.getChan() RsSplitVertRgbToChannels (GetCurrentSelection()) chan rgbChans:workChans ) on btnFromWorkChans pressed do ( local chan = RsVertClrToolCommonRoll.getChan() RsCombineVertRgbChannels (GetCurrentSelection()) chan rgbChans:workChans ) on BtnShowRed pressed do ( local chanItem = workChanItems[1] RsVertClrToolCommonRoll.showChannel chan:chanItem.id chanName:chanItem.name ) on BtnShowGreen pressed do ( local chanItem = workChanItems[2] RsVertClrToolCommonRoll.showChannel chan:chanItem.id chanName:chanItem.name ) on BtnShowBlue pressed do ( local chanItem = workChanItems[3] RsVertClrToolCommonRoll.showChannel chan:chanItem.id chanName:chanItem.name ) ) rollout RsVertClrToolsRoll "Tools" ( local btnWidth = 160 local btnHeight = 22 button btnChanClearer "Vertex Channel Clearer" width:btnWidth height:btnHeight offset:[0,-3] button btnVertexPaintMgr "VertexPaint Manager" width:btnWidth height:btnHeight offset:[-1,-3] -- button btnInitChannels "Activate Missing Channels" width:btnWidth height:btnHeight offset:[-1,-3] \ -- tooltip:"Find and activate channels on selected objects that are required by used materials" on btnChanClearer pressed do ( fileIn (::RsConfigGetWildWestDir() + "script/3dsMax/Maps/Materials/uvChannelClearer.ms") ) on btnVertexPaintMgr pressed do ( fileIn (::RsConfigGetWildWestDir() + "script/3dsMax/Maps/Materials/VertexPaintMgr.ms") ) fn ArrayToString arr = ( local outStr = (StringStream "") for n = 1 to arr.count do ( Format "%" (arr[n] as string) to:outStr if (n != arr.count) do ( Format ", " to:outStr ) ) return (outStr as String) ) on btnInitChannels pressed do ( -- Collect channels required by each object's materials, and which channels are currently active: struct sObjChans (obj, requiredChans, missingChans) local chansPerObj = #() for obj in (GetCurrentSelection()) do ( -- Get channels used by materials applied to object: local requiredChans = #() local objMats = (RsGetMaterialsOnObjFaces obj) for thisMat in objMats where (IsKindOf thisMat Rage_Shader) do ( local matChans = (RstGetMaterialMapChannels thisMat) for chan in matChans do ( AppendIfUnique requiredChans chan ) ) if (requiredChans.count != 0) do ( Sort requiredChans -- Which channels need to be activated for this object? local objChansUsed = RsGetActiveChannels obj local missingChans = for chan in requiredChans where (FindItem objChansUsed chan == 0) collect chan Sort missingChans Append chansPerObj (sObjChans obj:obj requiredChans:requiredChans missingChans:missingChans) ) ) if (chansPerObj.count == 0) do ( MessageBox "No valid RageShader materials were found on selected objects" title:"Invalid Selection" return OK ) -- Sort items with inactive channels to the top, otherwise sort by object-name: fn SortInactiveToTop v1 v2 = ( local inactiveA = (v1.missingChans.count != 0) local inactiveB = (v2.missingChans.count != 0) case of ( (inactiveA and inactiveB):(StriCmp v1.obj.name v2.obj.name) (inactiveA):-1 (inactiveB):1 Default:(StriCmp v1.obj.name v2.obj.name) ) ) Qsort chansPerObj SortInactiveToTop local listTitles = #("", "Object Name", "Required Channels", "Missing Channels") local listItems = #() local listChecked = #{} for n = 1 to chansPerObj.count do ( local item = chansPerObj[n] local nameStr = (item.obj.name) local requiredChansStr = (ArrayToString item.requiredChans) local missingChansStr = (ArrayToString item.missingChans) Append listItems #(nameStr, requiredChansStr, missingChansStr) listChecked[n] = (item.missingChans.count != 0) ) local msg = "Object materials require these vertex channels.\n\nActivate missing channels with their default colours?" local title = "Activate Missing Channels?" local btnLabels = #("Activate Missing Channels", "Cancel") local checkLabels = #("Collapse Modifiers") local checkStates = #{1} local queryVal = RsQueryBoxMultiBtn msg title:title timeout:-1 width:500 labels:btnLabels \ listItems:listItems listTitles:listTitles listCheckStates:listChecked checkLabels:checkLabels checkStates:checkStates -- If cancelled: if (queryVal == 2) do return OK local doCollapse = checkStates[1] -- Filter list to checked items with missing channels: chansPerObj = for n in listChecked collect chansPerObj[n] chansPerObj = for item in chansPerObj where (item.missingChans.count != 0) collect item if (chansPerObj.count == 0) do return OK SuspendEditing() undo "Activate Missing Channels" on ( local selObjs = (GetCurrentSelection()) try ( for item in chansPerObj do ( local obj = item.obj local missingChans = item.missingChans -- Collect channel-edit definitions: local clrEdits = for chan in missingChans collect ( -- Get default colour for required channel: local chanClr = (RsGetDefaultChannelColour chan) (RsVertClrsEditDef chan:chan inputVal:chanClr modName:("Init [channel " + (Chan as string) + "]")) ) -- Apply edit(s) to whole object: Select obj SubObjectLevel = 0 RsApplyVertClrChanges clrEdits if doCollapse do ( CollapseStack obj ) ) ) catch () ResumeEditing() Select selObjs ) return OK ) ) rollout RsVertClrCopyRoll "Copy Colour/Mapping Channels" ( Dotnetcontrol LstCopyFrom "ComboBox" Align:#Left Width:146 Height:20 Offset:[-7,0] Across:3 Button BtnSwapChans "<->" Tooltip:"Swap Channels" Align:#Center Width:20 Height:20 Dotnetcontrol LstCopyTo "ComboBox" Align:#Right width:146 Height:20 Offset:[7,0] Button BtnCopyChan "> Copy Channel >" Width:160 offset:[-2,-1] fn GetChannelNum ThisList = ( return (ThisList.SelectedIndex - 2) ) fn SetBtnEnabled = ( BtnCopyChan.Enabled = (LstCopyFrom.SelectedIndex != LstCopyTo.SelectedIndex) BtnSwapChans.Enabled = BtnCopyChan.Enabled ) on LstCopyFrom SelectionChangeCommitted Sender Args do ( SetBtnEnabled() ) on LstCopyTo SelectionChangeCommitted Sender Args do ( SetBtnEnabled() ) on BtnSwapChans Pressed do ( local FromWas = LstCopyFrom.SelectedIndex LstCopyFrom.SelectedIndex = LstCopyTo.SelectedIndex LstCopyTo.SelectedIndex = FromWas ) on BtnCopyChan Pressed do ( local ChanFrom = (GetChannelNum LstCopyFrom) local ChanTo = (GetChannelNum LstCopyTo) for Obj in (GetCurrentSelection()) do ( local ObjOp = (RsMeshPolyOp Obj) if (ObjOp != undefined) and (ObjOp.GetMapSupport Obj ChanFrom) do ( -- Collect existing paste-modifiers: local PasteMods = for ThisMod in Obj.Modifiers where (isKindOf ThisMod UVW_Mapping_Paste) collect ThisMod -- Copy/paste channel: ChannelInfo.CopyChannel Obj 3 ChanFrom ChannelInfo.PasteChannel Obj 3 ChanTo -- Find new paste-modifier: local PasteMod = undefined for ThisMod in Obj.Modifiers while (PasteMod == undefined) do ( if (isKindOf ThisMod UVW_Mapping_Paste) and (AppendIfUnique PasteMods ThisMod) do ( PasteMod = ThisMod ) ) -- Edit paste-modifier's name/mapId values: if (PasteMod != undefined) do ( PasteMod.Name = ("UV Paste [Chan " + (ChanTo as string) + "]") PasteMod.MapId = ChanTo -- Make sure renames are shown in list: local CurrMod = ModPanel.GetCurrentObject() if (CurrMod != undefined) do ( ModPanel.SetCurrentObject CurrMod Node:Obj UI:True ) ) ) ) ) on RsVertClrCopyRoll open do ( for Lst in #(LstCopyFrom, LstCopyTo) do ( Lst.DropDownStyle = Lst.DropDownStyle.DropDownList Lst.DropDownWidth = 320 Lst.Items.Addrange RsVertClrToolCommonRoll.LstChans.Items Lst.SelectedIndex = 2 ) SetBtnEnabled() ) ) rollout RsVertClrProjectionRoll "Vertex Colour Projection" ( Dotnetcontrol LstCopyFrom "ComboBox" Align:#Left Width:146 Height:20 Offset:[-7,0] Across:3 Button BtnSwapChans "<->" Tooltip:"Swap Channels" Align:#Center Width:20 Height:20 Dotnetcontrol LstCopyTo "ComboBox" Align:#Right width:146 Height:20 Offset:[7,0] local selectedTargets = #() fn pickFilter arg = ( (classof arg.baseobject == Editable_Poly) or (classof arg.baseobject == Editable_mesh) ) pickButton pickSource "Pick Source" filter:pickFilter width:150 height:23 across:2 button pickTargetBtn "Set Target(s)" width:150 height:23 label pickedSrc "" width:150 offset:[5,0] across:2 label pickedTgt "" width:150 offset:[5,0] group "" ( checkBox chkSampleBomb "Average Sample" tooltip:"Take more samples to average the colour transfer, better job, longer time" across:2 spinner spnPushPos "Push Value" type:#Float scale:0.1 range:[-9.99, 9.99, 0.0] tooltip:"Push the position values. Can help with meshes that are very close topographically" label lblChannels "Channels:" tooltip:"Enable a channel to have it projected" across:4 checkBox chkRChan "R" checked:true checkBox chkGChan "G" checked:true checkBox chkBChan "B" checked:true ) button btnProject "Project!" width:300 fn GetChannelNum ThisList = ( return (ThisList.SelectedIndex - 2) ) on BtnSwapChans Pressed do ( local FromWas = LstCopyFrom.SelectedIndex LstCopyFrom.SelectedIndex = LstCopyTo.SelectedIndex LstCopyTo.SelectedIndex = FromWas ) on btnProject pressed do ( --Everything set right? if (pickSource.object == undefined) or (selectedTargets.count == 0) do ( messageBox "Your selection is not complete. Set a source and one or more targets" return ok ) if (findItem selectedTargets pickSource.object) != 0 do ( messagebox "Source object cannot also be a target" return ok ) --source channel is? local sourceChan = (GetChannelNum LstCopyFrom) --target channel is? local targetChan = (GetChannelNum LstCopyTo) --average sample is selected? local doSampleBomb = chkSampleBomb.state --push value local pushVal = spnPushPos.value --what channels are active local redSet = if chkRChan.checked then "r" else "" local greenSet = if chkGChan.checked then "g" else "" local blueSet = if chkBChan.checked then "b" else "" local channelSetting = redSet + greenSet + blueSet if (channelSetting == "") or (channelSetting == "rgb") do channelSetting = "all" --format "ChannelSetting: % \n" channelSetting for target in selectedTargets do ( --call the projector RsProjectVertexMap \ pickSource.object \ target \ SRCchannel:sourceChan TGTchannel:targetChan \ subChannels:channelSetting sampleBomb:doSampleBomb \ pushVal:pushVal ) ) ----------------------- on pickSource picked obj do ( if (obj != undefined) do ( pickedSrc.text = obj.name ) ) ----------------------- on pickTargetBtn pressed do ( selectedTargets = for each in (GetCurrentSelection()) where isEditPolyMesh each collect each if (selectedTargets.count == 1) then pickedTgt.text = selectedTargets[1].name else if (selectedTargets.count > 1) do pickedTgt.text = selectedTargets[1].name + " and " + \ ((selectedTargets.count-1) as string) + " more" ) on RsVertClrProjectionRoll open do ( for Lst in #(LstCopyFrom, LstCopyTo) do ( Lst.DropDownStyle = Lst.DropDownStyle.DropDownList Lst.DropDownWidth = 320 Lst.Items.Addrange RsVertClrToolCommonRoll.LstChans.Items Lst.SelectedIndex = 2 ) ) ) rollout RSProjectClrMapRoll "Terrain Channel Transfer" ( local wpfString = " " local sourceMesh = undefined local targetMesh = undefined local theComboBox local transferList = #() local controls = Dictionary() local maxNetGeo struct ControlItem ( stackpanel, textblock, checkbox ) group "Channels" ( DotNetControl XamlControl "Integration.ElementHost" Align:#Left Width:260 Height:20 Offset:[0,0] Across:2 checkbox chkAll "All" align:#right offset:[0, 3] ) fn pickFilter obj = ( return ((classof obj == editable_mesh) or (classof obj == editable_poly)) ) group "Selection" ( label lblSource "Source: " align:#left across:4 pickbutton pckSource "Pick" filter:pickFilter width:100 offset:[-20, -3] label lblTarget "Target: " offset:[-20, 0] pickbutton pckTarget "Pick" filter:pickFilter width:100 offset:[-20, -3] ) group "" ( checkbox chkDistCut "Distance Cutoff: " across:2 align:#left spinner spnMaxDist enabled:false Range:[0.1,100, 0.1] Scale:0.01 Type:#Float width:50 align:#left offset:[-45, 0] ) button btnTransfer "Transfer" width:160 ------------------------------------------------------------------------------------------------- fn updateList item = ( --get the channel idx local mapIdxs = for chan in RsNamedMeshVertChannels where (chan.name == item) collect chan.id local mapIdx if (mapIdxs.count != 0) then mapIdx = mapIdxs[1] --update state local transferSet = finditem transferList mapIdx if (transferSet != 0 ) then --its already set so switch it ( deleteItem transferList transferSet ) else --add it ( append transferList mapIdx ) ) ------------------------------------------------------------------------------------------------- fn doTransfer sourceMesh targetMesh channels:#all meshesWerePoly: = ( if (maxNetGeo == undefined) then ( maxNetGeo = dotnetobject "RSG.TechArt.Max.Geometry.Geo" ) --check if the meshes are in containers, if they are then temporarily remove them whilst the imprinting is done local sourceContainer = Containers.IsInContainer sourceMesh local targetContainer = Containers.IsInContainer targetMesh if(sourceContainer != undefined) then ( sourceContainer.removeNodeFromContent sourceMesh true ) if(targetContainer != undefined) then ( targetContainer.removeNodeFromContent targetMesh true ) try ( for chan in transferList do ( format "Transfering Chan %\n" chan PushPrompt ("Transferring channel: " + chan as String) local distanceVal = if spnMaxDist.enabled then spnMaxDist.value else -1 if (maxNetGeo == undefined) do ( print "No Max Geo!" continue ) local hasMapSupport = true local success = false local sourceObjOp = RsMeshPolyOp sourceMesh local targetObjOp = RsMeshPolyOp targetMesh if not ((sourceObjOp.getMapSupport sourceMesh chan) \ and (targetObjOp.getMapSupport targetMesh chan)) do ( format "\nThe chosen channel does not exist in one or both of the objects.\n" format "Source 1: %\nTarget 2: %\nChannel: %\n" sourceMesh targetMesh chan hasMapSupport = false ) if (hasMapSupport) do ( success = maxNetGeo.TransferMapChannel sourceMesh.handle #(targetMesh.handle) chan chan distanceVal ) if not success then ( format "Problem transferring: %\n" chan as String ) ) replacePrompt "" update targetMesh --convert the meshes back to poly if thats what they were before if (meshesWerePoly != unsupplied) do ( if meshesWerePoly.source do convertToPoly sourceMesh if meshesWerePoly.target do convertToPoly targetMesh ) if(sourceContainer != undefined) then ( sourceContainer.AddNodeToContent sourceMesh ) if(targetContainer != undefined) then ( targetContainer.AddNodeToContent targetMesh ) ) catch --readd items to thier relative containers ( if(sourceContainer != undefined) then ( sourceContainer.AddNodeToContent sourceMesh ) if(targetContainer != undefined) then ( targetContainer.AddNodeToContent targetMesh ) ) ) ----------------------- on pckSource picked obj do ( if (obj != undefined) do ( if (obj != targetMesh) then ( sourceMesh = obj pckSource.text = obj.name ) ) ) ----------------------- on pckTarget picked obj do ( if (obj != undefined) do ( if (obj != sourceMesh) then ( targetMesh = obj pckTarget.text = obj.name ) ) ) ----------------------- on chkDistCut changed active do ( if active then ( spnMaxDist.enabled = True ) else ( spnMaxDist.enabled = False ) ) ----------------------- on btnTransfer pressed do ( local sourceWasPoly = classof sourceMesh.baseobject == Editable_Poly local targetWasPoly = classof targetMesh.baseobject == Editable_Poly if (sourceMesh != undefined) and (targetMesh != undefined) then ( if (classof sourceMesh != Editable_mesh) then ( ConvertToMesh sourceMesh ) if (classof targetMesh != Editable_mesh) then ( ConvertToMesh targetMesh ) local channelList = #() if chkAll.state then ( local ObjOp = (RsMeshPolyOp sourceMesh) channelList = for item in RsNamedMeshVertChannels where (ObjOp.GetMapSupport sourceMesh item.id) collect item.id ) else ( -- channelSel = (LstCopyFrom.SelectedIndex - 2) channelList = #() local ObjOp = (RsMeshPolyOp sourceMesh) for channelSel in transferList do ( if (ObjOp != undefined) and (ObjOp.GetMapSupport sourceMesh channelSel) do ( append channelList channelSel ) ) ) if (channelList.count != 0) then ( --check channels exist on source and target objects missingSourceChannels = #() missingTargetChannels = #() for channelIdx in channelList do ( local actualChan = channelIdx + 1 --Check map channel support on the target mesh if not (meshop.getMapSupport targetMesh channelIdx) then ( if ((meshop.getNumMaps targetMesh) < actualChan) then ( meshop.setNumMaps targetMesh actualChan ) meshop.setMapSupport targetMesh channelIdx true for mv = 1 to (meshop.getNumMapVerts targetMesh channelIdx) do ( meshop.setMapVert targetMesh channelIdx mv [0,0,0] ) update targetMesh ) if not (meshop.getMapSupport sourceMesh channelIdx) then ( append missingSourceChannels channelIdx ) if not (meshop.getMapSupport targetMesh channelIdx) then ( append missingTargetChannels channelIdx ) ) if (missingSourceChannels.count > 0) or (missingTargetChannels.count > 0) then ( local list = NewScript() format "SourceMesh Channels:\n" to:list for idx in missingSourceChannels do ( --get long name from index local name = (for chan in RsNamedMeshVertChannels where chan.id == idx collect chan.name)[1] format "Channel: %\n" ((idx as String) + ":" + name) to:list ) format "TargetMesh Channels:\n" to:list for idx in missingTargetChannels do ( --get long name from index local name = (for chan in RsNamedMeshVertChannels where chan.id == idx collect chan.name)[1] format "Channel: %\n" ((idx as String) + ":" + name) to:list ) messageBox "There are missing map channels, see the list" title:"Missing Map Channels" return false ) doTransfer sourceMesh targetMesh channels:channelList meshesWerePoly:(DataPair source:sourceWasPoly target:targetWasPoly) ) else ( messageBox "None of the channels selected have map support in the source object." title:"No Map Support" ) if (transferList.count > channelList.count) and (channelList.count > 0) do ( local difference = transferList.count - channelList.count format "% Channels were not transfered due to lack of enabled MapSupport for those channels.\n" difference format "Channels to transfer: %\n" transferList format "Channels available: %\n" channelList ) ) ) -------------------------- on chkAll changed checked do ( --if its on disable the dropdown if checked then ( transferList = for chan in RsNamedMeshVertChannels collect chan.id local scb = dotnetobject "Windows.Media.SolidColorBrush" scb.Color = ((dotNetclass "System.Windows.Media.Color").FromArgb 0 0 0 0) for item in controls.values() do ( boolFalse = dotnetobject "System.Boolean" false item.checkbox.IsChecked = boolFalse item.stackpanel.Background = scb ) theComboBox.Visibility = (dotnetclass "System.Windows.Visibility").Hidden ) else ( transferList = #() theComboBox.Visibility = (dotnetclass "System.Windows.Visibility").Visible ) ) ------------------------------------------------------------------------------------------------- on RSProjectClrMapRoll open do ( dotnet.loadAssembly (RsConfigGetTechArtDir() + "dcc/3dsMax/RSG.TechArt.Max.dll") dotNet.loadAssembly @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.0\WindowsFormsIntegration.dll" XamlReader = (dotNetClass "Windows.Markup.XamlReader").Parse wpfString XamlControl.child = XamlReader dotNet.setLifetimeControl XamlReader #dotnet theCanvas = XamlControl.Child theComboBox = theCanvas.FindName "Channels" fn chkClickFn sender ev = ( updateList sender.Tag local controlItem = controls.getValue sender.Tag local sp = controlItem.stackpanel if (controlItem.checkbox.IsChecked) then ( -- if controlItem.stackpanel.Background local scb = dotnetobject "Windows.Media.SolidColorBrush" scb.Color = ((dotNetclass "System.Windows.Media.Color").FromArgb 255 64 96 0) controlItem.stackpanel.Background = scb ) else ( local scb = dotnetobject "Windows.Media.SolidColorBrush" scb.Color = ((dotNetclass "System.Windows.Media.Color").FromArgb 0 0 0 0) controlItem.stackpanel.Background = scb ) --theComboBox.IsDropDownOpen = false ) for item in RsNamedMeshVertChannels do ( --theComboBox.Items.Add item.name stackpanel = dotnetobject "Windows.Controls.StackPanel" stackpanel.orientation = dotnetclass "System.Windows.Controls.Orientation.Horizontal" textblock = dotnetobject "Windows.Controls.TextBlock" textblock.text = item.name + " [" + (item.id as String) + "]" checkboxCtrl = dotnetobject "Windows.Controls.CheckBox" th = dotnetobject "System.Windows.Thickness" 10 0 0 0 checkboxCtrl.Margin = th checkboxCtrl.Tag = item.name checkboxCtrl.IsThreeState = false dotnet.AddEventHandler checkboxCtrl "Click" chkClickFn -- append checkBoxes checkboxCtrl stackpanel.Children.Add textblock stackpanel.Children.Add checkboxCtrl theComboBox.Items.Add stackpanel controls.addKey item.name (ControlItem stackpanel:stackpanel textblock:textblock checkbox:checkboxCtrl) ) theComboBox.SelectedIndex = 0 /* LstCopyFrom.DropDownStyle = LstCopyFrom.DropDownStyle.DropDownList LstCopyFrom.DropDownWidth = 320 local listItems = #() for item in RsVertClrToolCommonRoll.LstChans.Items do ( local chkBox = dotnetobject "CheckBox" chkBox.text = item chkBox.AccessibleName = item append listItems chkBox ) -- LstCopyFrom.Items.Addrange RsVertClrToolCommonRoll.LstChans.Items LstCopyFrom.Items.Addrange listItems LstCopyFrom.SelectedIndex = 2 */ --Set channels 5(Terrain Uber Masking) and 9(Terrain Shader Lookup) by default ( local channelIllum = RsNamedMeshVertChannels[2].name local channel5 = RsNamedMeshVertChannels[8].name local channel9 = RsNamedMeshVertChannels[12].name local scb = dotnetobject "Windows.Media.SolidColorBrush" scb.Color = ((dotNetclass "System.Windows.Media.Color").FromArgb 255 64 96 0) updateList channelIllum local controlItem = controls.getValue channelIllum controlItem.checkbox.IsChecked = (dotnetobject "System.Boolean" true) controlItem.stackpanel.Background = scb updateList channel5 local controlItem = controls.getValue channel5 controlItem.checkbox.IsChecked = (dotnetobject "System.Boolean" true) controlItem.stackpanel.Background = scb updateList channel9 local controlItem = controls.getValue channel9 controlItem.checkbox.IsChecked = (dotnetobject "System.Boolean" true) controlItem.stackpanel.Background = scb ) ) ) rollout RsMapVertClrToolsRoll "Map Tools" ( local btnWidth = 160 local btnHeight = 22 button btnSceneBaker "Scene Baker" width:btnWidth height:btnHeight offset:[-1,0] button btnMeshTint "Mesh Tinting Tool" width:btnWidth height:btnHeight offset:[-1,-3] button btnTerrain "Terrain Paint" width:btnWidth height:btnHeight offset:[-1,-3] button btnChanClearer "Vertex Channel Clearer" width:btnWidth height:btnHeight offset:[0,-3] button btnVertPaintTools "Vertex Paint Tools" width:btnWidth height:btnHeight offset:[-1,-3] button btnVertPaintMgr "VertexPaint Manager" width:btnWidth height:btnHeight offset:[-1,-3] button btnRandomPainter "Random Painter" width:btnWidth height:btnHeight offset:[-1,-3] on btnSceneBaker pressed do ( filein "rockstar/util/scenebaker/rsn_scenebaker.ms" ) on btnMeshTint pressed do ( fileIn (::RsConfigGetWildWestDir() + "script/3dsMax/Props/MeshTint_tool.ms") ) on btnTerrain pressed do ( filein (RsConfigGetWildwestDir() + "Script/3dsMax/Maps/Materials/terrain_painter.ms") ) on btnChanClearer pressed do ( fileIn (::RsConfigGetWildWestDir() + "script/3dsMax/Maps/Materials/uvChannelClearer.ms") ) on btnVertPaintTools pressed do ( fileIn (::RsConfigGetWildWestDir() + "script/3dsMax/Characters/Materials/Vertex_Bake_Painter.ms") ) on btnVertPaintMgr pressed do ( fileIn (::RsConfigGetWildWestDir() + "script/3dsMax/Maps/Materials/VertexPaintMgr.ms") ) on btnRandomPainter pressed do ( fileIn (::RsConfigGetWildWestDir() + "script/3dsMax/Maps/Materials/RandomPainter.ms") ) ) rollout RsPedVertClrToolsRoll "Ped Tools" ( local btnWidth = 160 local btnHeight = 22 button btnVertPaintTools "Vertex Paint Tools" width:btnWidth height:btnHeight button btnChanClearer "Vertex Channel Clearer" width:btnWidth height:btnHeight offset:[1,-3] button btnVertexPaintMgr "VertexPaint Manager" width:btnWidth height:btnHeight offset:[0,-3] button btnPedDirtBaker "Ped Dirt Baker" width:btnWidth height:btnHeight offset:[1,-3] on btnVertPaintTools pressed do ( fileIn (::RsConfigGetWildWestDir() + "script/3dsMax/Characters/Materials/Vertex_Bake_Painter.ms") ) on btnChanClearer pressed do ( fileIn (::RsConfigGetWildWestDir() + "script/3dsMax/Maps/Materials/uvChannelClearer.ms") ) on btnVertexPaintMgr pressed do ( fileIn (::RsConfigGetWildWestDir() + "script/3dsMax/Maps/Materials/VertexPaintMgr.ms") ) on btnPedDirtBaker pressed do ( fileIn (::RsConfigGetWildWestDir() + "script/3dsMax/Characters/Materials/pedDirtBaker.ms") ) ) rollout RsVertClrToolEditRoll "Edit Vert/Face Colours" ( local clrFuncs = #( dataPair label:"Set Colour" action:#set, dataPair label:"Colourise (Set Hue/Sat)" action:#colourise, dataPair label:"Set Hue" action:#hue, dataPair label:"Set Saturation" action:#saturation, dataPair label:"Set Luminosity" action:#luminosity, dataPair label:"Multiply" action:#multiply, dataPair label:"Screen" action:#screen, dataPair label:"Overlay" action:#overlay ) local btnHeight = 20 local btnWidth = 30 local bmHeight = btnHeight-4 local bmWidth = btnWidth-4 group "Quick Pick/Apply (L/R-click):" ( button btnBlk width:btnWidth height:btnHeight across:9 button btnWht width:btnWidth height:btnHeight button btnGry width:btnWidth height:btnHeight button btnRed width:btnWidth height:btnHeight button btnYlw width:btnWidth height:btnHeight button btnGrn width:btnWidth height:btnHeight button btnTel width:btnWidth height:btnHeight button btnBlu width:btnWidth height:btnHeight button btnPur width:btnWidth height:btnHeight ) local grey = Color 128 128 128 local teal = Color 0 255 255 local purple = Color 255 0 255 local btnColours = \ #( DataPair button:btnBlk colour:Black, DataPair button:btnWht colour:White, DataPair button:btnGry colour:Grey, DataPair button:btnRed colour:Red, DataPair button:btnYlw colour:Yellow, DataPair button:btnGrn colour:Green, DataPair button:btnTel colour:Teal, DataPair button:btnBlu colour:Blue, DataPair button:btnPur colour:Purple ) fn GetColourForButton inBtn= ( local outColour = Undefined for item in btnColours while (outColour == Undefined) do ( if (item.button == inBtn) do outColour = item.colour ) return outColour ) local clrSize = 122 local btnWidth = 150 checkButton btnPickFace "Pick Colour from Mesh" across:2 width:btnWidth align:#left offset:[0,0] button btnObjPicker "Get Colour from Selected" width:btnWidth align:#right offset:[0,0] tooltip:"Pick Colour from selected object/sub-object selection, from \"Use Channel\"" button btnInvertColours "Invert Colours" across:2 width:btnWidth align:#left offset:[0,-3] tooltip:"Invert colours for selected subobjects" button btnVertAverage "Average Per Vert" width:btnWidth align:#Right offset:[0,-3] tooltip:"Set average colour for selected verts - smooths over sharp seams" button btnCurveMask "Curvature Mask" width:btnWidth align:#left offset:[0,-3] tooltip:"Bake curvature to active channel\n(Black: Flat, White: Max Curve)" colorPicker clrPicker width:clrSize height:clrSize across:3 offset:[-10,0] checkButton btnSyncToVpaint "Sync => VertexPaint" checked:False width:(clrSize - 3) height:28 pos:(clrPicker.pos + [0, clrSize + 3]) \ tooltip:"Send chosen colours to VertexPaint modifier" radioButtons rdoSelEdit "" labels:(for item in clrFuncs collect item.label) pos:(clrPicker.pos + [clrSize + 4, 0]) button btnApply "Apply" tooltip:"Apply colour/action to selection" width:100 height:30 pos:[RsVertClrToolEditRoll.width - 106, rdoSelEdit.pos.Y + clrSize - 34] spinner spnOpacity "Opacity:" range:[0,1,1] FieldWidth:40 pos:(btnApply.Pos + [7,33]) local clrBtnWidth = 16 local clrBmps = for clr in #(Red, Green, Blue) collect #((Bitmap 9 9 color:clr), Undefined, 1, 1, 1, 1, 1, True) Label lblRGB "Edit Components:" Across:5 Align:#Right Offset:[193,-3] CheckButton chkRed "" images:clrBmps[1] border:False checked:True align:#Right width:clrBtnWidth height:clrBtnWidth pos:(lblRGB.pos + [88,0]) CheckButton chkGreen "" images:clrBmps[2] border:False checked:True align:#Right width:clrBtnWidth height:clrBtnWidth pos:(chkRed.pos + [17,0]) CheckButton chkBlue "" images:clrBmps[3] border:False checked:True align:#Right width:clrBtnWidth height:clrBtnWidth pos:(chkGreen.pos + [17,0]) ColorPicker clrShowMix align:#Right width:8 height:16 pos:(chkBlue.pos + [13,0]) enabled:False local subChanCtrls = #(chkRed, chkGreen, chkBlue) Group "Select Subobjects with Matching Colour:" ( button btnSelSubobjs "Select" tooltip:"Select verts/faces using this colour" width:80 align:#left offset:[-3,-1] across:2 spinner spnSelectDist "Match-range %" range:[0,256,10] type:#integer fieldwidth:30 pos:(btnSelSubobjs.pos + [80 + 8, 4]) ) -- Returns active rgb subchannels: fn GetSubChans = ( local retVal = #{} for n = 1 to 3 do ( retVal[n] = SubChanCtrls[n].Checked ) return retVal ) -- Transfer colour/opacity to VertexPaint floater: fn sendToVpaint = ( -- Get VertexPaint floater: local vPaintTool = VertexPaintTool() -- Set VertexPaint colour/opacity: vPaintTool.paintColor = (clrPicker.color) vPaintTool.brushOpacity = (100.0 * spnOpacity.value) -- Trigger toolkit-update: vPaintTool.keepToolboxOpen = vPaintTool.keepToolboxOpen ) -- Modify chosen colour to match channel/subchannel settings: fn ShowClr = ( -- Is this a greyscale channel? (alpha/luminosity) local isGreyScale = (RsVertClrToolCommonRoll.getChan() < 0) -- Get unmodified chosen colour from Common rollout: local theShowClr = Copy rsVertClrToolCommonRoll.rememberClr -- Disable subchannel- controls for greyscale: SubChanCtrls.Enabled = (not isGreyScale) if (isGreyScale) then ( -- Set control to greyscale version of RememberClr: local greyVal = (theShowClr.r + theShowClr.g + theShowClr.b) / 3.0 theShowClr = Color greyVal greyVal greyVal ) else ( -- Modify RememberClr to mask out unwanted subchannels: local maskedChans = -(GetSubChans()) if MaskedChans[1] do (theShowClr.r = 0) if MaskedChans[2] do (theShowClr.g = 0) if MaskedChans[3] do (theShowClr.b = 0) ) -- Show colour: ClrPicker.Color = theShowClr -- Transfer new colour to VertexPaint floater: if (btnSyncToVpaint.checked) do (sendToVpaint()) ) fn setThisClr newClr = ( if (newClr != undefined) do ( rsVertClrToolCommonRoll.rememberClr = newClr -- Show colour in clrPicker, modified as necessary: ShowClr() ) ) on clrPicker changed newClr do ( setThisClr newClr ) on spnOpacity changed newVal do ( -- Transfer new opacity to VertexPaint floater: if (btnSyncToVpaint.checked) do (sendToVpaint()) ) on btnSyncToVpaint changed newState do ( -- Transfer colour/opacity to VertexPaint floater: if newState do (sendToVpaint()) ) fn UpdateComponentMix = ( local clr = Black if chkRed.checked do (clr += Red) if chkGreen.checked do (clr += Green) if chkBlue.checked do (clr += Blue) clrShowMix.color = clr ) -- Update colour whenever rgb checkboxes are changed: on chkRed changed State do (UpdateComponentMix(); ShowClr()) on chkGreen changed State do (UpdateComponentMix(); ShowClr()) on chkBlue changed State do (UpdateComponentMix(); ShowClr()) on chkRed rightclick do (#(chkRed, chkGreen, chkBlue).checked = True; UpdateComponentMix()) on chkGreen rightclick do (#(chkRed, chkGreen, chkBlue).checked = True; UpdateComponentMix()) on chkBlue rightclick do (#(chkRed, chkGreen, chkBlue).checked = True; UpdateComponentMix()) on btnObjPicker pressed do ( local chan = (RsVertClrToolCommonRoll.getChan()) local getClr = RsChooseColourFromSelObjs chan:chan setThisClr getClr ) on btnPickFace changed state do ( -- Pick colour from selected object's mesh: local chan = (RsVertClrToolCommonRoll.getChan()) local getClr = RsPickColourFromObj ($) chan:chan showOptions:True -- Show picked colour: setThisClr getClr btnPickFace.checked = False ) fn QuickSetVertColor aColour= ( RsApplyVertColourChange chan:(RsVertClrToolCommonRoll.getChan()) action:#set\ inputVal:aColour opacity:1 SubChans:(GetSubChans()) AllowSoftSelect:True ) fn QuickSetColourPicker aColour= ( setThisClr aColour ) on btnBlk rightClick do QuickSetVertColor (GetColourForButton btnBlk) on btnWht rightClick do QuickSetVertColor (GetColourForButton btnWht) on btnGry rightClick do QuickSetVertColor (GetColourForButton btnGry) on btnRed rightClick do QuickSetVertColor (GetColourForButton btnRed) on btnYlw rightClick do QuickSetVertColor (GetColourForButton btnYlw) on btnGrn rightClick do QuickSetVertColor (GetColourForButton btnGrn) on btnTel rightClick do QuickSetVertColor (GetColourForButton btnTel) on btnBlu rightClick do QuickSetVertColor (GetColourForButton btnBlu) on btnPur rightClick do QuickSetVertColor (GetColourForButton btnPur) on btnBlk pressed do QuickSetColourPicker (GetColourForButton btnBlk) on btnWht pressed do QuickSetColourPicker (GetColourForButton btnWht) on btnGry pressed do QuickSetColourPicker (GetColourForButton btnGry) on btnRed pressed do QuickSetColourPicker (GetColourForButton btnRed) on btnYlw pressed do QuickSetColourPicker (GetColourForButton btnYlw) on btnGrn pressed do QuickSetColourPicker (GetColourForButton btnGrn) on btnTel pressed do QuickSetColourPicker (GetColourForButton btnTel) on btnBlu pressed do QuickSetColourPicker (GetColourForButton btnBlu) on btnPur pressed do QuickSetColourPicker (GetColourForButton btnPur) on btnApply pressed do ( local chan = RsVertClrToolCommonRoll.getChan() local action = clrFuncs[rdoSelEdit.state].action local inputVal = clrPicker.color local opacity = spnOpacity.Value local SubChans = (GetSubChans()) --format "chan: %\naction: %\ninputVal: %\nopacity: %\nSubChans: %\n" chan action inputVal opacity SubChans RsApplyVertColourChange chan:chan action:action inputVal:inputVal opacity:opacity SubChans:SubChans AllowSoftSelect:True ) on btnInvertColours pressed do ( local chan = RsVertClrToolCommonRoll.GetChan() local subChans = (GetSubChans()) RsApplyVertColourChange chan:chan action:#invert SubChans:SubChans ) on btnVertAverage pressed do ( local chan = RsVertClrToolCommonRoll.GetChan() local subChans = (GetSubChans()) RsApplyVertColourChange chan:chan action:#VertAverage subChans:subChans ) on btnCurveMask pressed do ( local chan = RsVertClrToolCommonRoll.GetChan() local subChans = (GetSubChans()) RsApplyVertColourChange chan:chan action:#Curvature subChans:subChans ) on btnSelSubobjs pressed do ( local findClr = clrPicker.color local matchDist = spnSelectDist.value local obj = $ if (not isEditPolyMesh obj) do return false obj = obj.baseObject local subObjType = RsGetSubObjLevelName() if (subObjType != #face) do (subObjType = #vertex) setCommandPanelTaskMode #modify modPanel.setCurrentObject obj ui:True -- Get colour/subobj lists: local chan = RsVertClrToolCommonRoll.getChan() local objClrs = #() local clrVerts = #() local clrFaces = #() RsGetColourSubobjLists obj chan:chan colours:objClrs verts:clrVerts faces:clrFaces -- Find matching colours: (convert to CIE-L*ab for better matching) local findClrVal = (RsXYZtoCIELAB (RsRGBtoXYZ findClr)) local searchClrVals = for clr in objClrs collect (RsXYZtoCIELAB (RsRGBtoXYZ clr)) local searchSubObjs = if (subObjType == #face) then clrFaces else clrVerts local matchedSubObjs = #{} -- Find subobjects with matching colours: for clrIdx = 1 to objClrs.count do ( if (distance findClrVal searchClrVals[clrIdx]) <= matchDist do ( matchedSubObjs += searchSubObjs[clrIdx] ) ) -- Set subobject selection case subObjType of ( #vertex: ( subObjectLevel = 1 case (classOf obj) of ( Editable_Poly:(polyop.setVertSelection obj matchedSubObjs) Editable_Mesh:(setVertSelection obj matchedSubObjs) ) ) #face: ( case (classOf obj) of ( Editable_Poly:(polyop.setFaceSelection obj matchedSubObjs) Editable_Mesh:(setFaceSelection obj matchedSubObjs) ) ) ) completeRedraw() return matchedSubObjs ) on RsVertClrToolEditRoll open do ( for item in btnColours do item.button.images = #((Bitmap bmWidth bmHeight color:item.colour), Undefined, 1, 1, 1, 1, 1, True) clrPicker.color = RsVertClrToolCommonRoll.rememberClr UpdateComponentMix() ) ) rollout RsVertClrToolVertMatcherRoll "Copy Edge-Vertex Colours" ( label copyEdgeVertClrLbl "Copy the vertex colour of source to matching verts on selection" button btnMatchEdgeVerts "Copy matching verts:" across:2 align:#right tooltip:"Colours are copied from verts on source-object, onto matching verts on selected objects" pickButton btnPickMatchObj "Pick Source Object" filter:isEditPolyMesh autoDisplay:true align:#left offset:[2,0] on btnPickMatchObj rightClick do (btnPickMatchObj.object = undefined) on btnMatchEdgeVerts pressed do ( local chan = RsVertClrToolCommonRoll.getChan() local sourceObj = btnPickMatchObj.object if (not isValidNode sourceObj) do ( messageBox "Please pick a Source Object" title:"Error: No source-object picked" return false ) local targetObjs = for obj in selection where (isEditPolyMesh obj) and (obj != sourceObj) collect obj if (targetObjs.count == 0) do ( messageBox "Please select at least one Target Object" title:"Error: No target-objects selected" return false ) for obj in targetObjs do ( local tempObj = RsVertClr_makeTempObj obj copyChan:chan RsCopyVertColours sourceObj tempObj matchChannel:chan RsVertClr_applyTempData tempObj obj chan ) ) ) rollout RsVertClrToolFaceCopyRoll "Copy Face-Colours" ( group "Copy face-colours:" ( button btnCopyClr "Copy to selected:" across:2 align:#right tooltip:"Colours are copied from faces on source-object onto nearest faces (in local space) on selected objects" pickButton btnPickSrcObj "Pick Source Object" filter:isEditPolyMesh autoDisplay:true align:#left offset:[2,0] ) button btnMeshTintToSlods "Copy MeshTint to ComboLod sources" tooltip:"MeshTint colours are copied from faces on selected HD objects onto nearest faces (in local space) on their linked ComboLodder-source meshes" on btnPickSrcObj rightClick do (btnPickSrcObj.object = undefined) fn copyFaceColours sourceObjs targetObjLists chan:(RsVertClrToolCommonRoll.getChan()) = ( local modName = "ColourCopy [chan " + (chan as string) + "]" progressStart "Copying face-colours..." local copyNum = 0 local copyCount = 0 for list in targetObjLists do (copyCount += 1) local keepGoing = True for n = 1 to sourceObjs.count while keepGoing do ( local sourceObj = sourceObjs[n] local targetObjs = targetObjLists[n] for targetObj in targetObjs while keepGoing = (progressupdate ((100.0 * (copyNum += 1)) / copyCount)) do ( local tempObj = RsVertClr_makeTempObj targetObj copyChan:chan RsCopyFaceColours sourceObj tempObj chan:chan showProgress:False RsVertClr_applyTempData tempObj targetObj chan modName:modName ) ) progressEnd() ) on btnCopyClr pressed do ( local sourceObj = btnPickSrcObj.object if (not isValidNode sourceObj) do ( messageBox "Please pick a Source Object" title:"Error: No source-object picked" return false ) local targetObjs = for obj in selection where (isEditPolyMesh obj) and (obj != sourceObj) collect obj if (targetObjs.count == 0) do ( messageBox "Please select at least one Target Object" title:"Error: No target-objects selected" return false ) copyFaceColours #(sourceObj) #(targetObjs) ) on btnMeshTintToSlods pressed do ( local selObjs = for obj in selection where (isEditPolyMesh obj) collect ( local slodChildren = #() local slodParents = #() RsSceneLink.GetChildren LinkType_CombinerMesh obj &slodChildren RsSceneLink.GetParents LinkType_CombinerMesh obj &slodParents if (slodChildren.count != 0) or (slodParents.count == 0) then dontCollect else obj ) if (selObjs.count == 0) do ( messageBox "Please select at least one high-def prop with linked ComboLod-sources" title:"Error: Invalid Selection" return False ) local sourceObjs = #() local targetObjLists = #() for sourceObj in selObjs do ( local slodMeshes = #() RsSceneLink.GetParents LinkType_CombinerMesh sourceObj &slodMeshes local slodNum = 0 -- Get rest of objects from slod-source hierarchy: while (slodNum < slodMeshes.count) do ( slodNum += 1 local moreSlods = #() RsSceneLink.GetParents LinkType_CombinerMesh slodMeshes[slodNum] &moreSlods join slodMeshes moreSlods ) append sourceObjs sourceObj append targetObjLists slodMeshes ) -- Do face-colour copy: copyFaceColours sourceObjs targetObjLists chan:gRsMeshTintFuncs.tintChannel ) ) rollout RsVertClrToolWeldVertsRoll "Weld Mapping-Verts" ( Label LblWeld "Welds mapping-border verts for selected geometry-verts\nor object, on mapping-channel set as 'Use Channel'" Align:#Left Height:28 Spinner SpnThreshold "Threshold:" Range:[0.001,2.0,0.01] Scale:0.001 FieldWidth:40 Offset:[0,3] Across:2 Align:#Right Button BtnWeldVerts "Weld Selected" Offset:[4,0] Align:#Left on BtnWeldVerts pressed do ( local SelObjs = for Obj in GetCurrentSelection() where (isEditPolyMesh Obj) collect Obj if (SelObjs.Count == 0) do return False -- Get weld-channel from common rollout: local Chan = RsVertClrToolCommonRoll.GetChan() -- Get verts from subobject-selection, or Unsupplied if we're applying weld to whole object(s) local SelVerts = if (SelObjs.Count > 1) or ((RsGetSubObjLevelName()) == #object) then unsupplied else (RsGetSelVertNums SelObjs) for Obj in SelObjs do ( RsWeldMapBorderVerts Obj Chan Verts:SelVerts Threshold:SpnThreshold.Value ) ) ) rollout RsVertClrToolRoll "Vertex Colour Toolkit" ( local rollWidth dotNetControl RsBannerPanel "Panel" pos:[0,0] height:32 width:RsVertClrToolRoll.width local bannerStruct = makeRsBanner dn_Panel:RsBannerPanel versionNum:1.54 versionName:"Acrid Frustrum" dotNetControl dnTabs "system.windows.forms.tabControl" width:(RsVertClrToolRoll.width + 2) height:25 align:#left pos:[-1, (RsBannerPanel.height + 2)] subRollout theSubRollout width:(RsVertClrToolRoll.width + 1) pos:[-1, dnTabs.pos.y + dnTabs.height] local rolloutPages = #( DataPair name:"Edit" rollouts:#(RsVertClrWorkChannels, RsVertClrToolEditRoll, RsVertClrToolsRoll, RsVertClrToolWeldVertsRoll, RsVertClrCopyRoll, RsVertClrProjectionRoll) ) local rolloutCurrentPages = #() fn SetPage idx = ( if ( idx <= rolloutPages.count ) then ( for roll in rolloutCurrentPages do ( removeSubRollout theSubRollout roll ) rolloutCurrentPages = #() for roll in rolloutPages[idx].rollouts do ( addSubRollout theSubRollout roll append rolloutCurrentPages roll ) -- Don't show common-controls tab if current tab doesn't use it: local showCommon = TRUE -- (idx != 1) RsVertClrToolCommonRoll.keepOpenState = showCommon RsVertClrToolCommonRoll.open = showCommon ) else ( MessageBox "Internal Error. Tabs misconfigured. Contact tools." ) ) on dnTabs Click do ( local tabNum = dnTabs.SelectedIndex + 1 RsSettingWrite "RsVertClrToolRoll" "tabNum" tabNum SetPage tabNum ) fn arrangeCtrls = ( theSubRollout.height = RsVertClrToolRoll.height - theSubRollout.pos.y - theSubRollout.pos.x ) -- Only allow vertical resizing: on RsVertClrToolRoll Resized newSize do ( if (newSize.x != rollWidth) do ( RsVertClrToolRoll.width = rollWidth ) RsSettingWrite "RsVertClrToolRoll" "height" newSize.y arrangeCtrls() ) on RsVertClrToolRoll open do ( -- Initialise tech-art banner: bannerStruct.setup() rollWidth = RsVertClrToolRoll.width arrangeCtrls() dnTabs.tabPages.clear() for item in rolloutPages do ( dnTabs.tabPages.add item.name ) local tabNum = RsSettingsReadInteger "RsVertClrToolRoll" "tabNum" 1 if (tabNum > dnTabs.tabPages.count) do ( tabNum = 1 ) dnTabs.SelectedIndex = (tabNum - 1) addSubRollout theSubRollout RsVertClrToolCommonRoll SetPage tabNum ) fn create = ( destroyDialog RsVertClrToolRoll local rollHeight = RsSettingsReadInteger "RsVertClrToolRoll" "height" 712 CreateDialog RsVertClrToolRoll modal:false width:342 height:rollHeight style:#(#style_resizing, #style_titlebar, #style_border, #style_sysmenu ) ) ) -- End rollout RsVertClrToolRoll.create()