handling IRollupWindow


#1

Someone asked if it’s possible to have some rollups opened by default and others closed. That’s my attempt to tackle the issue.
While it seems to work overall, sometimes I get undefined trying to get IRollupPanel using IRollupWindow.GetPanel method (line:19). Any thoughts on what could be the cause of it?
And the main question is: How these IRollupWindow and IRollupPanel instances should be handled after work is done? Should I dispose them or what?

fn rollupDoorman forceOpenRollups: = (

    if forceOpenRollups == unsupplied do forceOpenRollups = #("Selection","Edit Vertices","Edit Edges","Edit Geometry","Edit Borders","Edit Polygons","Polygon: Smoothing Groups","Polygon: Material IDs")
    
    
    modPanelHWND = undefined
    for c in UIAccessor.GetChildWindows (windows.getMAXHWND()) while modPanelHWND == undefined where (d = windows.getHWNDData c)[4] == "ModifyTask" do modPanelHWND = d[1]
    rollupWindows = for w in windows.getChildrenHWND modPanelHWND where w[4] == "RollupWindow" collect w[1]

    for rollupWindowHWND in rollupWindows do (

        IRollupWindow = (dotnetclass "Autodesk.Max.GlobalInterface").Instance.getIRollup (dotnetobject "system.intptr" rollupWindowHWND)

--         format "
IRollupWindow.numpanels: %
" IRollupWindow.numpanels

        
        for i=0 to IRollupWindow.numpanels-1 do (
            
            IRollupPanel = IRollupWindow.GetPanel (IRollupWindow.GetPanelDlg i asdotnetobject:true)
            
            if IRollupPanel == undefined do (format "Failed at %
" i; continue)
                
            rollupName = UIAccessor.GetWindowText IRollupPanel.TitleWnd
            
--             format "%: %
" i rollupName
            
            if findItem forceOpenRollups rollupName > 0 then (
                
                if not IRollupWindow.IsPanelOpen i do IRollupWindow.SetPanelOpen i true false
                
            ) else (
                
                if IRollupWindow.IsPanelOpen i do IRollupWindow.SetPanelOpen i false false
                            
            )
            
        )
        
    )

)



fn weAreOpenHandler = (
    
    local base = modPanel.getCurrentObject()
    
    case classof base of (
        
        Editable_Poly: rollupDoorman()
        Edit_Poly:     rollupDoorman()
        Editable_Mesh: rollupDoorman()
        Edit_Mesh:     rollupDoorman()
        
        default:()        
        
    )    
    
)


callbacks.removeScripts #modPanelSelChanged id:#weAreOpen
callbacks.removeScripts #ModPanelSubObjectLevelChanged id:#weAreOpen
callbacks.addScript #modPanelSelChanged "weAreOpenHandler()" id:#weAreOpen
callbacks.addScript #ModPanelSubObjectLevelChanged "weAreOpenHandler()" id:#weAreOpen



#2

cool… but all these will not work in 2017+

i’m waiting for a complete UI solution in MAX. hopefully it will be 2018


#3

and IRollupWindow related question

I’ve looked in SDK… you are definitely can reorder rollups from SDK. IRollupWindow and IRollupPanel give access to that.
Reordering rollouts on the command panel

I’d like to add custom attributes rollout and make it first rollup.
Can somebody explain how to move/reorder rollouts using IRollupWindow and IRollupPanel methods correctly?
I’ve managed to move my rollup where I want it to be, but when I switch to create mode and then back to modify mode it stays where it was initially (if I manually place it second, third etc it will always keep this place when I change back to modify mode).
Should I save it’s state somehow?
I tried to, but SaveState fails… sdk sources lacks info about RollupState

Here’s my code



fn ReorderModpanelRollups titles indexes =
(
	local g = (dotNetClass "Autodesk.Max.GlobalInterface").Instance

	local modPanelHWND = undefined
	for c in windows.getChildrenHWND #max while modPanelHWND == undefined where c[4] == "ModifyTask" do modPanelHWND = c[1]
	
	local rollupWindows = for w in windows.getChildrenHWND modPanelHWND where w[4] == "RollupWindow" collect w[1]
	
	for rollupWindowHWND in rollupWindows do
	(
		local IRollupWindow = g.getIRollup (dotnetobject "system.intptr" rollupWindowHWND)

		format "\nIRollupWindow.numpanels: %\n" IRollupWindow.numpanels
		
		local reordered = false
		
		for i=0 to IRollupWindow.numpanels-1 do
		(			
			local IRollupPanel = IRollupWindow.GetPanel (IRollupWindow.GetPanelDlg i asdotnetobject:true)
			
			if IRollupPanel != undefined do
			(				
				local rollupName = UIAccessor.GetWindowText IRollupPanel.TitleWnd
				
				format "%: %   cat:%\n" i rollupName IRollupPanel.category
				
				local index = findItem titles rollupName
				if index > 0 and IRollupPanel.category != indexes[index] do
				(					
-- 					show IRollupPanel
					IRollupPanel.category = indexes[index]
					reordered = true					
				)
			)
			
		)
		
		
		if reordered do
		(
			IRollupWindow.updateLayout()

			-- try to save rollup states 
			for i=0 to IRollupWindow.numpanels-1 do
			(			
				local IRollupPanel = IRollupWindow.GetPanel (IRollupWindow.GetPanelDlg i asdotnetobject:true)
				
				if IRollupPanel != undefined do
				(
					try ( IRollupWindow.SaveState (dotNetObject "System.IntPtr" IRollupPanel.HInst) ) catch (format "save failed at %\n" i)
				)
				
			)			
			
		)	
		
		
		g.ReleaseIRollup IRollupWindow
		
	)		
	
)

t = Teapot()
addModifier t (Edit_Poly())
max modify mode
ReorderModpanelRollups #( "Paint Deformation", "Selection" ) #( 1, 2 )

#4

ok… looks like it must be saved like this

local current_mod = modPanel.getCurrentObject()
local cid  = g.Class_ID.create current_mod.classid[1] current_mod.classid[2]
local sid = (dotnetclass "Autodesk.Max.SClass_ID").Osm 

local rollupName = UIAccessor.GetWindowText IRollupPanel.TitleWnd
g.IRollupSettings.CatReg.UpdateCat sid cid rollupName IRollupPanel.Category

#5

Good catch! Thanks!

… probably you have to save it for next sessions of MAX if you want:

g.IRollupSettings.CatReg.Save()