Notifications
Clear all

[Closed] Maxscript that addresses dialogues?

Sorry to once again ask for assistance from all the excellent masters here but yet another question has confused me. I’m automating a rendering process that opens and renders files using a separate document. Some of the objects that I’m receiving to pass through the script are made with an older version of Vray and a dialogue box opens halting my process asking me if I want to update something like lights or materials on the objects, the answer will always be the same thing in the case of the project I’m working on so I wanted to know if I could automate the script to check if those dialogue boxes pop up, and if they do select the answers I want on them. Thank you all very much in advance!

8 Replies

It should be possible, but you’ll have to check for the details of the dialog that pops up.

Here’s the basic skeleton script code you’ll need…


fn checkDialog = (
	local hwnd = dialogMonitorOps.getWindowHandle()
	local dialogTitle = uiAccessor.getWindowText hwnd
	print dialogTitle
	true
)
dialogMonitorOps.interactive = false
dialogMonitorOps.unregisterNotification id:#test
dialogMonitorOps.registerNotification checkDialog id:#test
dialogMonitorOps.enabled = true
 

Run that code once, then open one of those files. The MaxScript Listener will then contain a list of all the titles of the dialogs that open. Stop the dialogMonitor so the 3ds Max interface doesn’t go wacky…

dialogMonitorOps.enabled = false

So let’s say the title of the dialog is called “Hello World”, and in that dialog is a button labeled “foo” that you want to press. You’d accomplish that with:


fn checkDialog = (
	local hwnd = dialogMonitorOps.getWindowHandle()
	local dialogTitle = uiAccessor.getWindowText hwnd
	if (dialogTitle == "Hello World") then (
		uiAccessor.pressButtonByName "foo"
	)
	true
)
dialogMonitorOps.interactive = false
dialogMonitorOps.unregisterNotification id:#test
dialogMonitorOps.registerNotification checkDialog id:#test
dialogMonitorOps.enabled = true

Try loading the file again, check if the button is pressed correctly, etc. Disable the dialogMonitor again.

If all is well, then you can just enable/disable the monitor in your file loading/rendering loop. E.g.


for somefile in someArrayOfFiles do (
	dialogMonitorOps.enabled = true
	loadMaxFile somefile
	dialogMonitorOps.enabled = false
)

And that should be all there is to it.

Thank you very much for your highly useful and detailed description! I’ll try this out and hopefully I have enough neurons in my skull to correctly interpret what you said.

Ok, running into a potential error while running this. Both of the two dialogues it opens are both called “V-Ray warning” the first has one button “Ok” But the second window has a “Yes” and “No” Will this script encounter errors because both of the dialogues have the exact same title?

tsk… same titles…

On the up side – no, that shouldn’t be a problem. .pressButtonByName doesn’t error out when you press a button that doesn’t exist… so the easy-but-unclean way out is to just attempt to press both buttons ( OK and Yes … or OK and No, whichever it is ).

The better way would be to figure out which dialog it actually is. The following code will not just print out the title of the dialog, but also the title (string, label, etc.) of any controls within that dialog. One of them is bound to be related to what you need to figure out which dialog it is.


 fn checkDialog = (
 	local hwnd = dialogMonitorOps.getWindowHandle()
 	local dialogTitle = uiAccessor.getWindowText hwnd
 	if (dialogTitle != undefined) then (
 	     print dialogTitle
		local hwnd_children = uiAccessor.getChildWindows hwnd
 		for i = 1 to hwnd_children.count do (
 			format "% = \"%\"
" i (uiAccessor.getWindowText hwnd_children[i])
 		)
 	)
 	true
 )
 
 dialogMonitorOps.interactive = false
 dialogMonitorOps.unregisterNotification id:#test
 dialogMonitorOps.registerNotification checkDialog id:#test
 dialogMonitorOps.enabled = true
 

So, for example, I tried to open a new file just now (expecting to get the file open dialog), and got the following because my current scene isn’t saved:


 "3ds Max"
 1 = "&Yes"
 2 = "&No"
 3 = "Cancel"
 4 = ""
 5 = "The scene has been modified.
 Do you want to save your changes?"
 

The title of the dialog is “3ds Max” – entirely too generic, but the 5th element within the dialog tells me what I need to know about the dialog.

So now I can change things to the following to automatically press the Yes button.


 dialogMonitorOps.enabled = false
 fn checkDialog = (
 	local hwnd = dialogMonitorOps.getWindowHandle()
 	local dialogTitle = uiAccessor.getWindowText hwnd
 	if (dialogTitle != undefined) then (
 		if (dialogTitle == "3ds Max") then (
 			local hwnd_children = uiAccessor.getChildWindows hwnd
 			for i = 1 to hwnd_children.count do (
 				local hwnd_child_title = uiAccessor.getWindowText hwnd_children[i]
 				if (findString hwnd_child_title "The scene has been modified." == 1) then (
 					uiAccessor.pressButtonByName hwnd "&Yes"
 				)
 			)
 		)
 	)
 	true
 )
 
 dialogMonitorOps.interactive = false
 dialogMonitorOps.unregisterNotification id:#test
 dialogMonitorOps.registerNotification checkDialog id:#test
 dialogMonitorOps.enabled = true
 

Note that

  • I find the “The scene has been modified” but using findString – this means I don’t have to worry about whether they used
    or
    for that newline in the dialog.
  • I use “&Yes” instead of just “Yes” because pressButtonByName goes by the internal label, not by what’s naturally displayed (the & makes the Y a hotkey in the dialog, so that just pressing the ‘Y’ key makes you choose the Yes option)
  • I check if dialogTitle != undefined. If dialogTitle == undefined, then you’re likely to hit the desktop. If you remove that if-test, and evaluate the earlier code, you’ll see a printout of pretty much anything you’ve got open… not useful for what you need

I hope the above helps

Thanks for the great walkthru on the UIAccessor stuff Richard, i’m finding it useful

mugenxero i think you may just be looking for the SetVraysilentMode() function however

So, along the same vein, and thanks to you Richard and to Martjin’s thread, I’ve got it this far… but i seem to be stuck?

Basic Problem: IT has enforced a Screensaver password policy here now Now, with the D3D view port driver, when you come back from a locked workstation, it doesn’t always instantiate the DX display correctly. we’re noticing on our workstations that it will come back working to a point… IE: All of the geometry on screen is selectable, but only ~20% of it is displayed with edges in max.

a hack to fix it without having to restart max every time the computer locks on you, I’ve found i can Disable and then Enable the Direct3D Cached meshes… this works… in a crappy sort of way.

Here’s some code that toggles the d3d cached…


 
 toolTip="toggles the Use Cached D3DXMeshes Viewport Option"
 buttonText="toggles the Use Cached D3DXMeshes Viewport Option"
 
 --start macro
 
 -----------------------------------------------------------------------------------------------
 --
 -- toggles the "Use Cached D3DXMeshes" checkbox of the Viewport configuration
 --
 -----------------------------------------------------------------------------------------------
 
 --diable it while
  dialogMonitorOps.enabled = false
  
  fn toggleCachedD3DMeshes = (
 
 	
 	 --Constants for sendMessage method	
 	local BM_GETSTATE = 0xF2
 	local BM_CLICK = 0xF5
 	local BM_SETCHECK = 0xF1
 	local BST_CHECKED = 0x1	 
 
 	newState = #toggle
 
 	 local hwnd = dialogMonitorOps.getWindowHandle()
 	 local dialogTitle = uiAccessor.getWindowText hwnd
 	 if (dialogTitle != undefined) then (
 		 if (dialogTitle == "Preference Settings") then (
 			format "We're in the preferences dialog
" 
 			local hwnd_children = uiAccessor.getChildWindows hwnd
 			 for i = 1 to hwnd_children.count do (
 				 local hwnd_child_title = uiAccessor.getWindowText hwnd_children[i]
 				if (findString hwnd_child_title "Configure Driver..." == 1) then (
 					format "found config button... pressing
"
 					local hwnd_config = hwnd_children[i]
 					 uiAccessor.pressButton hwnd_config
 					)
 				)
 			)
 		else if (dialogTitle == "Configure Direct3D") then (
 			local hwnd_children = uiAccessor.getChildWindows hwnd
 			 for i = 1 to hwnd_children.count do (
 				 local hwnd_child_title = uiAccessor.getWindowText hwnd_children[i]
 				if (findString hwnd_child_title "Use Cached D3DXMeshes" == 1) then (
 					format "found the cached button
"
 					local hwnd_cached = hwnd_children[i]
 					local CheckState = windows.sendMessage hwnd_cached BM_GETSTATE 0 0
 					local IsChecked = bit.get CheckState BST_CHECKED
 					format "the checkbox was: %
" IsChecked
 					-- Uncheck it
 					if IsChecked then
 					(
 						windows.sendMessage hwnd_cached BM_CLICK 0 0
 						windows.sendMessage hwnd_cached BM_SETCHECK 0 0
 						format "Cached D3DXMeshes has been disabled.
"
 						format "Pressing OK on the ConfigureD3D page
"
 						uiAccessor.sendMessageID hwnd #IDOK
 -- 						format "Pressing OK on the Preferences page
"
 -- 						uiAccessor.pressButtonByName "OK"
 					)
 					-- Check it
 					else if not IsChecked then
 					(
 						windows.sendMessage hwnd_cached BM_CLICK 0 0
 						windows.sendMessage hwnd_cached BM_SETCHECK 1 0
 						format "Cached D3DXMeshes has been enabled.
"
 						format "Pressing OK on the ConfigureD3D page
"
 						uiAccessor.sendMessageID hwnd #IDOK
 -- 						format "Pressing OK on the Preferences page
"
 -- 						uiAccessor.pressButtonByName "OK"
 					)
 				 )
 			 )
 		 )
 	 )
 	 true
  )
 
 dialogMonitorOps.interactive = false
 dialogMonitorOps.unregisterNotification id:#test
 dialogMonitorOps.registerNotification toggleCachedD3DMeshes id:#test
 dialogMonitorOps.enabled = true
  
 --run it
 max file preferences
 
 --disable it!
 dialogMonitorOps.enabled = false
 dialogMonitorOps.unregisterNotification id:#test
 
 --"Preference Settings"
 --"Configure Driver..."
 --"Configure Direct3D"
 --"Use Cached D3DXMeshes"
  
  
  

The problem i’m having, is i can’t get it to close the max preferences dialog, because its loading the dialogmonitor function a second time when the viewport driver config dialog comes up, i’m losing the hwnd of the preferences?

Uncommenting the uiAccessor.pressButtonByName “OK” or trying the uiAccessor.sendMessageID hwnd #IDOK both come up with errors, and dont close the dialog…

This is about the point where someone says i can do it with a 3 second script somewhere!

Any thoughts?

Richard already wrote the DirectX Cache Enable/Disable script for me in this thread.

-Eric

Damn! knew i needed to search some more Thanks.!

Ah well, learned a lot about random innards of dialogs at least! heheh.