[Closed] How to sort subarrays for Mat ID swapping
Hi,
I am scripting a tool that will permit users to swap material IDs on a selected editable poly.
First the user clicks on a button that gets the current material IDs on the object and displays them with spinners. The user can then set the “target ID” manually for each set.
The problem I am having is in special cases where the user-set target IDs are identical to the source IDs. I was thinking of sorting the sets in descending order using the target value in subarrays, but I am not able to get the sorting to work. I commented out parts I can’t get to work.
PS: I have more of a beginner to intermediate knowledge of maxscript and scripting in general
Here are parts of the code:
/*fn fnCompareFN v1 v2 MIDS_SwapSets: =
(
local d = MIDS_SwapSets[v2][2] - MIDS_SwapSets[v1][2]
case of
(
(d < 0): -1
(d > 0): 1
default: 0
)
)*/
fn fnCreateSwapSets =
(
clearSelection() -- Clear any existing selections
MIDS_SwapSets = #()
MIDS_SwapSetsTemp = #()
for spinner in MIDS_SpinnersArr do
(
if spinner.visible == true then appendIfUnique MIDS_SwapSetsTemp spinner
)
local sourceValue, targetValue
for i = 1 to MIDS_SwapSetsTemp.count do
(
sourceValue = i
targetValue = MIDS_SpinnersArr[i].Value
append MIDS_SwapSets (#(sourceValue, targetValue))
messageBox ("sourceValue:" +sourceValue as String+", " +targetValue sourceValue as String)
)
messageBox (MIDS_SwapSets as String)
-- Sort MIDS_SwapSets based on the target values in descending order
-- MIDS_SwapSets = qsort MIDS_SwapSets fnCompareFN
)
on btnSetMatIDs pressed do
(
try
(
if selection.count != 1 then messageBox ("Please select 1 object at a time")
else
(
fnRefresh 0
fnCreateSwapSets() --go through the sets of source+target IDs, and reorder them
-- Now MIDS_SwapSets contains sets for swapping in a logical order
for swapSet in MIDS_SwapSets do
(
sourceValue = swapSet[1]
targetValue = swapSet[2]
-- Apply the material ID swap
MIDS_CurO.EditablePoly.selectByMaterial sourceValue
MIDS_CurO.EditablePoly.setMaterialIndex targetValue 1
)
fnResetTool()
fnInitialize()
fnRefresh 1
)
)
catch (fnRedraw())
)
Perhaps something along these lines, which I find a bit simpler, could work?
(
try destroydialog ::RO_0X3350EE27 catch()
rollout RO_0X3350EE27 "" width:116 height:128
(
button bt_get "GET" pos:[ 8,8] width:44 height:24
button bt_set "SET" pos:[64,8] width:44 height:24 enabled:off
spinner sp_01a "" pos:[ 8, 40] fieldwidth:32 range:[1, 1000, 1] type:#integer indeterminate:on enabled:off
spinner sp_02a "" pos:[ 8, 60] fieldwidth:32 range:[1, 1000, 1] type:#integer indeterminate:on enabled:off
spinner sp_03a "" pos:[ 8, 80] fieldwidth:32 range:[1, 1000, 1] type:#integer indeterminate:on enabled:off
spinner sp_04a "" pos:[ 8,100] fieldwidth:32 range:[1, 1000, 1] type:#integer indeterminate:on enabled:off
spinner sp_01b "" pos:[64, 40] fieldwidth:32 range:[1, 1000, -1] type:#integer indeterminate:on
spinner sp_02b "" pos:[64, 60] fieldwidth:32 range:[1, 1000, -1] type:#integer indeterminate:on
spinner sp_03b "" pos:[64, 80] fieldwidth:32 range:[1, 1000, -1] type:#integer indeterminate:on
spinner sp_04b "" pos:[64,100] fieldwidth:32 range:[1, 1000, -1] type:#integer indeterminate:on
local SetFaceMatID = polyop.setfacematid
local GetFaceMatID = polyop.getfacematid
local spinners_get = #(sp_01a, sp_02a, sp_03a, sp_04a)
local spinners_set = #(sp_01b, sp_02b, sp_03b, sp_04b)
local node_matIDs = #()
fn UpdateUI =
(
spinners_get.indeterminate = spinners_set.indeterminate = on
for j = 1 to node_matIDs.count do
(
spinners_get[j].indeterminate = spinners_set[j].indeterminate = off
spinners_get[j].value = spinners_set[j].value = node_matIDs[j][2]
)
bt_set.enabled = on
)
fn GetNodeMatIDs node =
(
node_matIDs = #()
for j = 1 to node.numfaces do
(
id = GetFaceMatID node j
if node_matIDs[id] == undefined do node_matIDs[id] = #(#{}, id)
node_matIDs[id][1][j] = true
)
node_matIDs = for j in node_matIDs where j != undefined collect j
UpdateUI()
)
fn SetNodeMatIDs node =
(
for j = 1 to spinners_get.count do
(
if not spinners_get[j].indeterminate and not spinners_set[j].indeterminate do
(
sourceID = spinners_get[j].value
destID = spinners_set[j].value
for k = 1 to node_matIDs.count where node_matIDs[k][2] == sourceID do SetFaceMatID node node_matIDs[k][1] destID
)
)
completeredraw()
GetNodeMatIDs node
)
on bt_get pressed do GetNodeMatIDs selection[1]
on bt_set pressed do SetNodeMatIDs selection[1]
)
createdialog RO_0X3350EE27
)
Wow yes! Ok this is way way simpler, thanks a lot!
I’m going to take a look at your code now and see how I can populate the UI with the appropriate number of spinners by mat ID, then dynamically resize the window. I won’t know in advance how many mat IDs will be assigned on the selected object but I doubt there’d be more than 50 or so.
Again thanks, this unblocks me
You can use a dynamic MXS UI but perhaps I would go in a different direction using a .Net DataGridView or similar control, which you can resize and scroll as needed.
Since you don’t know the maximum amount of material IDs that will be used, if you hard code the spinners, you are limited to the controls you have and a dynamic MXS UI is going to be a painful work.
For the materials IDs you will get from the node, you just need a text to display them, so a spinner does not provide any advantage over a text box, and for setting the destination ID, entering them manually might be even faster than using a spinner. Additionally, using a .Net control, you can have colored cells if you wished to display the diffuse color of the material, or any other text information.
I have the feeling that such an instrument has no sense as an interactive tool. Of course, there may be a situation when it is necessary to replace one material ID with another, but this is usually not a tweaking needs, but a correction of some mistake or workflow issue…
In this case, there is no need to create a complex tool. Usually a simple script without user interface is enough.
This script is for a specific situation that happens when different artists are using different multi-materials, where the sub-materials are the same but the IDs are all different. It shouldn’t happen in theory but it does happen sometimes…and so I was thinking this will be useful to quickly remap the meshes in a level so that all the meshes are using the same ID assignments. We have a shared .mat but unfortunately it doesn’t always get used so its hard to “police”. Also sometimes while creating a level’s multi-material there are IDs we no longer need (after an optimization pass) so we have to re-order them.
On our project there wouldn’t be more than 30 IDs (usually) per multi-material so I can hard-code the limit to that…unless there is a better solution?
That’s what I meant…
Are ID numbers from 1 to 30 or no more than 30 IDs per object?
I don’t quite understand the mechanics of fixing incorrect IDs.
Let’s say we have an object, and we know it’s incorrect, and its IDs should be changed to : 1→3, 2→4, 3→2, 4→1…
Great, we do that.
But how do we know, when we open this file again, that none of the IDs are mixed up and no one needs to be fixed?
I remember a project with similar problems, but the main thing was to find these IDs misplacing, to select the corresponding faces…
global rol
try(destroydialog rol) catch ()
rollout rol "RO:01CC16FF" width:191
(
local map_rol_head =
"
rollout MapID_Rollout \"ID Mapping\"
(
fn changeID id = (format \"map id:%\\n\" id)
fn remapID id val = (format \"remap id:% val:%\\n\" id val)
"
local map_item_str =
"
button src_xx \"**\" width:60 height:18 align:#left offset:[0,-2] across:2
spinner trg_xx type:#integer range:[1,30,1] fieldwidth:40 align:#right offset:[0,0]
on src_xx pressed do changeID **
on trg_xx changed val do remapID ** val
"
local map_rol_end =
"
on MapID_Rollout close do ()
on MapID_Rollout open do ()
)
"
subrollout id_mapper_sub width:168 height:200
button all_ids "Remap All" width:172 align:#left offset:[-4,8]
local subrol
fn makeMapRollout ids =
(
try (removesubrollout id_mapper_sub subrol) catch()
ss = stringstream ""
format "%\n" map_rol_head to:ss
for id in ids do
(
str = copy map_item_str
str = substitutestring str "xx" (formattedprint id format:"02d")
str = substitutestring str "**" (id as string)
format str to:ss
)
format "%\n" map_rol_end to:ss
--print (ss as string)
subrol = execute (ss as string)
addsubrollout id_mapper_sub subrol
free ss
subrol
)
fn getMeshFaceMaterialIDs node ids: =
(
if ids == unsupplied do ids = #{}
if iskindof node GeometryClass do
(
mesh = copy node.mesh
for f=1 to mesh.numfaces do
(
id = getfacematid mesh f
--if ids[id] == undefined do ids[id] = #{}
append ids id
)
delete mesh
)
ids
)
fn collectIDs =
(
ids = #{}
for node in selection do
(
getMeshFaceMaterialIDs node ids:ids
)
makeMapRollout ids
)
on rol close do
(
callbacks.removescripts id:#matid_mapper
)
on rol open do
(
callbacks.removescripts id:#matid_mapper
callbacks.addscript #selectionSetChanged "::rol.collectIDs()" id:#matid_mapper
)
)
createdialog rol
--rol.makeMapRollout #(1,4,32)
Here’s a “dirty” solution on how to make a dynamic interface.
Perhaps later, when I have the time and interest, I’ll show you how to do it right…
I put a limit to a max of 999 for ID numbers because we almost always use at most 30-40 IDs per multi-material, but sometimes we use 999 as a test ID for temp textures. This is what I had done with what Polytools3D posted. Not elegant like what you guys do but it seems to do the job.
(
global rlSwapIDs
local SI_IniName = (“DT_SwapIDs”)
local SI_IniFile = (getdir #maxroot + “MacroScripts\DaveTools\DaveTools.ini”)
local SI_Position
local iMaxID = 30
try (destroyDialog rlSwapIDs) catch()
fn fnSetPosition =
(
try(setINISetting SI_IniFile SI_IniName "position" ((getdialogpos rlSwapIDs) as string)) catch()
gc()
)
fn fnGetPosition =
(
try
(
SI_IniFile = (getdir #maxroot + "MacroScripts\DaveTools\DaveTools.ini")
SI_Position = execute((getINISetting SI_IniFile SI_IniName "position") as string)
SI_Position[1]
)
catch (SI_Position = #(100,100))
)
fn fnRedraw =
(
enableSceneRedraw()
redrawViews()
)
fn fnRefresh iMode =
(
windows.processPostedMessages()
if iMode == 0 then setWaitCursor()
else if iMode == 1 then
(
redrawViews()
setArrowCursor()
redrawViews()
)
)
rollout rlSwapIDs "SwapID" width:103 height:52
(
local btnW = 42
local btnH = 20
local iPad = 3
local iUIbtm = 2
local iDefaultgbH = 50
local iFW = 32
local iFWb = 7
--Source IDs
groupBox gbA "" pos:[2,0] width:48 height:iDefaultgbH
button btnGetID "GET" pos:(gbA.pos + [iPad,iPad*3]) width:btnW height:btnH tooltip: "Get an object's Mat IDs (Up to a max of 35)"
spinner sp01a "" pos:(btnGetID.pos + [-iPad, btnH*1+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp02a "" pos:(btnGetID.pos + [-iPad, btnH*2+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp03a "" pos:(btnGetID.pos + [-iPad, btnH*3+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp04a "" pos:(btnGetID.pos + [-iPad, btnH*4+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp05a "" pos:(btnGetID.pos + [-iPad, btnH*5+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp06a "" pos:(btnGetID.pos + [-iPad, btnH*6+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp07a "" pos:(btnGetID.pos + [-iPad, btnH*7+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp08a "" pos:(btnGetID.pos + [-iPad, btnH*8+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp09a "" pos:(btnGetID.pos + [-iPad, btnH*9+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp10a "" pos:(btnGetID.pos + [-iPad, btnH*10+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp11a "" pos:(btnGetID.pos + [-iPad, btnH*11+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp12a "" pos:(btnGetID.pos + [-iPad, btnH*12+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp13a "" pos:(btnGetID.pos + [-iPad, btnH*13+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp14a "" pos:(btnGetID.pos + [-iPad, btnH*14+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp15a "" pos:(btnGetID.pos + [-iPad, btnH*15+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp16a "" pos:(btnGetID.pos + [-iPad, btnH*16+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp17a "" pos:(btnGetID.pos + [-iPad, btnH*17+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp18a "" pos:(btnGetID.pos + [-iPad, btnH*18+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp19a "" pos:(btnGetID.pos + [-iPad, btnH*19+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp20a "" pos:(btnGetID.pos + [-iPad, btnH*20+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp21a "" pos:(btnGetID.pos + [-iPad, btnH*21+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp22a "" pos:(btnGetID.pos + [-iPad, btnH*22+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp23a "" pos:(btnGetID.pos + [-iPad, btnH*23+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp24a "" pos:(btnGetID.pos + [-iPad, btnH*24+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp25a "" pos:(btnGetID.pos + [-iPad, btnH*25+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp26a "" pos:(btnGetID.pos + [-iPad, btnH*26+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp27a "" pos:(btnGetID.pos + [-iPad, btnH*27+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp28a "" pos:(btnGetID.pos + [-iPad, btnH*28+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp29a "" pos:(btnGetID.pos + [-iPad, btnH*29+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
spinner sp30a "" pos:(btnGetID.pos + [-iPad, btnH*30+iPad]) fieldwidth:iFW range:[1, 999, 1] type:#integer indeterminate:on enabled:off
--Target IDs
groupBox gbB "" pos:(gbA.pos + [gbA.width+iPad,0]) width:48 height:iDefaultgbH
button btnSetID "SET" pos:(gbB.pos + [iPad,iPad*3]) width:btnW height:btnH enabled:off tooltip: "Set an object's Mat IDs (Up to a max of 35)"
spinner sp01b "" pos:(btnSetID.pos + [-iPad, btnH+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp02b "" pos:(btnSetID.pos + [-iPad, btnH*2+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp03b "" pos:(btnSetID.pos + [-iPad, btnH*3+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp04b "" pos:(btnSetID.pos + [-iPad, btnH*4+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp05b "" pos:(btnSetID.pos + [-iPad, btnH*5+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp06b "" pos:(btnSetID.pos + [-iPad, btnH*6+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp07b "" pos:(btnSetID.pos + [-iPad, btnH*7+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp08b "" pos:(btnSetID.pos + [-iPad, btnH*8+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp09b "" pos:(btnSetID.pos + [-iPad, btnH*9+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp10b "" pos:(btnSetID.pos + [-iPad, btnH*10+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp11b "" pos:(btnSetID.pos + [-iPad, btnH*11+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp12b "" pos:(btnSetID.pos + [-iPad, btnH*12+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp13b "" pos:(btnSetID.pos + [-iPad, btnH*13+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp14b "" pos:(btnSetID.pos + [-iPad, btnH*14+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp15b "" pos:(btnSetID.pos + [-iPad, btnH*15+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp16b "" pos:(btnSetID.pos + [-iPad, btnH*16+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp17b "" pos:(btnSetID.pos + [-iPad, btnH*17+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp18b "" pos:(btnSetID.pos + [-iPad, btnH*18+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp19b "" pos:(btnSetID.pos + [-iPad, btnH*19+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp20b "" pos:(btnSetID.pos + [-iPad, btnH*20+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp21b "" pos:(btnSetID.pos + [-iPad, btnH*21+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp22b "" pos:(btnSetID.pos + [-iPad, btnH*22+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp23b "" pos:(btnSetID.pos + [-iPad, btnH*23+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp24b "" pos:(btnSetID.pos + [-iPad, btnH*24+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp25b "" pos:(btnSetID.pos + [-iPad, btnH*25+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp26b "" pos:(btnSetID.pos + [-iPad, btnH*26+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp27b "" pos:(btnSetID.pos + [-iPad, btnH*27+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp28b "" pos:(btnSetID.pos + [-iPad, btnH*28+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp29b "" pos:(btnSetID.pos + [-iPad, btnH*29+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
spinner sp30b "" pos:(btnSetID.pos + [-iPad, btnH*30+iPad]) fieldwidth:iFW range:[1, 999, 2] type:#integer indeterminate:on
local SetFaceMatID = polyop.setfacematid
local GetFaceMatID = polyop.getfacematid
local SI_CurrentMatIds = #()
local CurSel
local arrSpinners_all = #() --get all of the spinners in the rollout
local arrSpinners_all_a = #()
local arrSpinners_all_b = #()
local arrSpinners_get = #()
local arrSpinners_set = #()
local node_matIDs = #()
local idNum
local arrSpinners_all_aVal1 = #()
local arrSpinners_all_bVal2 = #()
fn fnResetSpinnerVals =
(
for a in arrSpinners_get do a.value = 1
for b in arrSpinners_set do b.value = 2
)
fn fnGetSpinners iMatID =
(
fnResetSpinnerVals()
idNum = iMatID
arrSpinners_all = for s in rlSwapIDs.controls where classOf s == SpinnerControl collect s
arrSpinners_all_a = for a in arrSpinners_all where a.value == 1 collect a
arrSpinners_all_b = for b in arrSpinners_all where b.value == 2 collect b
for f = 1 to (idNum) do appendIfUnique arrSpinners_get arrSpinners_all_a[f]
for f = 1 to (idNum) do appendIfUnique arrSpinners_set arrSpinners_all_b[f]
)
fn fnUpdateUI =
(
rlSwapIDs.height = iDefaultgbH+iUIbtm
idNum = node_matIDs.count
arrSpinners_get.indeterminate = arrSpinners_set.indeterminate = on
fnGetSpinners idNum
if idNum > 1 then
(
iExpand = (idNum - 1)
rlSwapIDs.height += (btnH)*iExpand
rlSwapIDs.gbA.height = rlSwapIDs.height - iUIbtm
rlSwapIDs.gbB.height = rlSwapIDs.gbA.height
)
for j = 1 to idNum do
(
arrSpinners_get[j].indeterminate = arrSpinners_set[j].indeterminate = off
arrSpinners_get[j].value = arrSpinners_set[j].value = node_matIDs[j][2]
)
btnSetID.enabled = on
)
fn fnGetNodeMatIDs node =
(
node_matIDs = #()
for j = 1 to node.numfaces do
(
id = GetFaceMatID node j
if node_matIDs[id] == undefined do node_matIDs[id] = #(#{}, id)
node_matIDs[id][1][j] = true
)
node_matIDs = for j in node_matIDs where j != undefined collect j
fnUpdateUI()
)
fn fnSetNodeMatIDs node =
(
for j = 1 to arrSpinners_get.count do
(
if not arrSpinners_get[j].indeterminate and not arrSpinners_set[j].indeterminate do
(
sourceID = arrSpinners_get[j].value
destID = arrSpinners_set[j].value
for k = 1 to node_matIDs.count where node_matIDs[k][2] == sourceID do SetFaceMatID node node_matIDs[k][1] destID
)
)
completeredraw()
fnGetNodeMatIDs node
)
on btnGetID pressed do
(
curSel = selection[1]
if selection.count == 0 then messageBox "Please select an Editable Poly object"
else if selection.count == 1 then
(
if classof curSel == Editable_Poly then
(
local facesCnt = polyop.getNumFaces curSel
SI_CurrentMatIds = #()
for f = 1 to facesCnt do
(
appendIfUnique SI_CurrentMatIds (GetFaceMatID curSel f)
)
if SI_CurrentMatIds.count > iMaxID then messageBox ("The selected object has more than " +iMaxID as String+ " Mat IDs, aborting!")
else fnGetNodeMatIDs curSel
)
)
else messageBox "Please select just one Editable Poly object at a time"
)
on btnSetID pressed do
(
local curSel2 = selection[1]
if curSel.name != undefined and curSel2.name != curSel.name then messageBox "The selection has changed, please set IDs to the same object"
else
(
if selection.count == 0 then messageBox "Please select an Editable Poly object"
else if selection.count == 1 then
(
if classof curSel == Editable_Poly then
(
fnSetNodeMatIDs curSel
)
)
else messageBox "Please select just one Editable Poly object at a time"
)
)
on rlSwapIDs close do
(
fnSetPosition()
)
)
fnGetPosition()
createDialog rlSwapIDs pos:[(SI_Position[1]),(SI_Position[2])] style:#(#style_titlebar, #style_border, #style_sysmenu)
)
I guess it’s happened so often in my career I just thought OK, I’ll have a script next time it happens (instead of taking a few days to manually correct tons of max files with multiple multi-materials with IDs all over the place).