Notifications
Clear all

[Closed] Maxscript ProBoolean Bug Workaround

Hey everyone

As mentioned in an old thread by denisT there is a Bug with ProBooleans in 3ds max.
He posted a nice workaround which works quite well. http://forums.cgsociety.org/showthread.php?t=806145

For my script, I also need to toggle the cookie option on and off depending on the task I´m performing which seems to have the same bug.
I can´t figure out how to use denisT method to set it.

Would be nice if someone can help me out.

Thanks,
Gerald

9 Replies

does ProBoolean.SetCookieCut not work?

mmm cookies… :bounce:

Thanks for your reply.
ProBoolean.SetCookieCut doesn´t seem to work using Max 2016.

Here´s the code with some cubes for testing:


fn getBooleanHWND =
	(
		 hwnd = undefined 
		 for c in (windows.getChildrenHWND #max) while hwnd == undefined where c[4] == "RollupPanelTitle" and c[5] == "Pick Boolean" do  (
			hwnd = UIAccessor.GetParentWindow c[1]
		 )
		hwnd
	)
	
fn setAddMethod method hwnd: update:on =  
	(
		 if hwnd == unsupplied do hwnd = getBooleanHWND()
		 if hwnd != undefined do
		 (
			  name = case method of
			  (
			   0: "Reference"
			   1: "Copy"
			   2: "Move"  
			   3: "Instance"
			   default: "Copy"
			  )
			  if (bt = windows.getChildHWND hwnd name) != undefined do UIAccessor.PressButton bt[1]
			  if update do select selection
			  ok
		 )
	)
			


fn doBooleanOp NodeA NodeB operation method isCookie = ( 
	
	ProBoolean.setoperandA NodeA
	select NodeA
	if getCommandPanelTaskMode() != #modify do setCommandPanelTaskMode mode:#modify
	if setAddMethod method == ok do
	( 
	ProBoolean.SetBoolOp NodeA operation
	ProBoolean.SetCookieCut NodeA isCookie
	ProBoolean.setoperandB NodeA NodeB method 0		
	)
	return NodeA
)


BoolA= Box position:[0,0,0] 
BoolB= Box position:[0,-10,0] width:10 height:15 length:15
BoolC= Box position:[40,0,0] 
BoolD= Box position:[40,-10,0] width:10 height:15 length:15
BoolE= Box position:[80,0,0] 
BoolF= Box position:[80,-10,0] width:10 height:15 length:15

doBooleanOp BoolA BoolB 2 2 false
doBooleanOp BoolC BoolD 2 2 true
doBooleanOp BoolE BoolF 2 2 false


use Boolean2 interface instead of PolyBoolean.


delete objects

BoolA = Box position:[0,0,0] 
BoolB = Box position:[0,-10,0] width:10 height:15 length:15
BoolC = Box position:[40,0,0] 
BoolD = Box position:[40,-10,0] width:10 height:15 length:15

(
	obj = boolObj.createBooleanObject BoolA BoolB 3 1
	boolObj.setBoolOp obj 3
	delete BoolB
--	converttopoly obj
)
(
	obj = boolObj.createBooleanObject BoolC BoolD 3 1
	boolObj.setBoolOp obj 5
	boolObj.setBoolCutType obj 3
	delete BoolD
--	converttopoly obj
)


Thanks for the reply and code, really appreciate the help.
Any chance to get this to work with ProBooleans?

Boolean2 is great for this simple example, but for the task, I want to perform ProBooleans give way better ( cleaner) results.

Not sure if its possible, but can´t we access the cookie checkbox with the hwnd workaround, like you did with the boolean method?

fn setProBooleanCookieCheck boolNode state = 
(
	BM_SETCHECKED = 0x00F1
	BM_UNCHECKED = 0x0000
	BM_CHECKED = 0x0001

	if modpanel.getcurrentobject() != bool do
	(
		max modify mode
		modpanel.setcurrentobject boolNode
	)
	obj = modpanel.getcurrentobject()
	if iskindof obj ProBoolean and obj == boolNode do
	(
		hwnd = windows.getchildhwnd #max "Cookie"
		if hwnd != undefined do
		(
			windows.SendMessage hwnd[1] BM_SETCHECKED (if state then BM_CHECKED else BM_UNCHECKED) 0
			return state
		)
	)
	undefined 
)
proboolean.SetOperandA BoolA
setProBooleanCookieCheck BoolA off

Unfortunately, it still doesn´t work. It seems the windows.SendMessage part doesn´t do anything.
Here´s the updated code:


fn getBooleanHWND =
	(
		 hwnd = undefined 
		 for c in (windows.getChildrenHWND #max) while hwnd == undefined where c[4] == "RollupPanelTitle" and c[5] == "Pick Boolean" do  (
			hwnd = UIAccessor.GetParentWindow c[1]
		 )
		hwnd
	)
	
fn setAddMethod method hwnd: update:on =  
	(
		 if hwnd == unsupplied do hwnd = getBooleanHWND()
		 if hwnd != undefined do
		 (
			  name = case method of
			  (
			   0: "Reference"
			   1: "Copy"
			   2: "Move"  
			   3: "Instance"
			   default: "Copy"
			  )
			  if (bt = windows.getChildHWND hwnd name) != undefined do UIAccessor.PressButton bt[1]
			  if update do select selection
			  ok
		 )
	)
fn setProBooleanCookieCheck boolNode state = (
		BM_SETCHECKED = 0x00F1
		BM_UNCHECKED = 0x0000
		BM_CHECKED = 0x0001

		if modpanel.getcurrentobject() != boolNode do
		(
			max modify mode
			modpanel.setcurrentobject boolNode
		)
		obj = modpanel.getcurrentobject()
		
		if iskindof obj ProBoolean and obj == boolNode do
		(
			hwnd = windows.getchildhwnd #max "Cookie"
			if hwnd != undefined do
			(
				windows.SendMessage hwnd[1] BM_SETCHECKED (if state then BM_CHECKED else BM_UNCHECKED) 0
				return state
			)
		)
		undefined 
	)	
fn doBooleanOp NodeA NodeB operation method isCookie = ( 
	
	ProBoolean.setoperandA NodeA
	select NodeA
	if getCommandPanelTaskMode() != #modify do setCommandPanelTaskMode mode:#modify
	if setAddMethod method == ok do
	( 
	ProBoolean.SetBoolOp NodeA operation
	setProBooleanCookieCheck NodeA isCookie
	ProBoolean.setoperandB NodeA NodeB method 0		
	)
	return NodeA
)

BoolA= Box position:[0,0,0] 
BoolB= Box position:[0,-10,0] width:10 height:15 length:15
BoolC= Box position:[40,0,0] 
BoolD= Box position:[40,-10,0] width:10 height:15 length:15
BoolE= Box position:[80,0,0] 
BoolF= Box position:[80,-10,0] width:10 height:15 length:15

doBooleanOp BoolA BoolB 2 2 false
doBooleanOp BoolC BoolD 2 2 true
doBooleanOp BoolE BoolF 2 2 false


i knew that…
the setting of the checkbox doesn’t automatically update internal proboolean structures.
we can set in stimulating ‘mouse click’… in this case it will update, but… there are another issues which you will meet later.


fn confirmProBooleanCookieCheck boolNode state = 
(
	BM_GETCHECKED = 0x00F0
	BM_SETCHECKED = 0x00F1
	BM_UNCHECKED = 0x0000
	BM_CHECKED = 0x0001

	WM_LBUTTONDOWN = 0x201
	WM_LBUTTONUP = 0x202	
	
	if modpanel.getcurrentobject() != bool do
	(
		max modify mode
		modpanel.setcurrentobject boolNode
	)
	obj = modpanel.getcurrentobject()
	if iskindof obj ProBoolean and obj == boolNode do
	(
		hwnd = windows.getchildhwnd #max "Cookie"
		if hwnd != undefined do
		(
			hwnd = hwnd[1]
			check = (windows.sendmessage hwnd BM_GETCHECKED 0 0) == 1 
			
			if proboolean.GetCookieCut boolNode == state then
			(
				if check != state do windows.postMessage hwnd BM_SETCHECKED (if state then BM_CHECKED else BM_UNCHECKED) 0
			)
			else
			(
				windows.sendmessage hwnd WM_LBUTTONDOWN 0 0
				windows.sendmessage hwnd WM_LBUTTONUP 0 0
				check = (windows.sendmessage hwnd BM_GETCHECKED 0 0) == 1
			)
			return #(state, check, proboolean.GetCookieCut boolNode)
		)
	)
	undefined 
)


proboolean.SetOperandA BoolA
confirmProBooleanCookieCheck BoolA on
proboolean.SetBoolOp BoolA 2    


Thanks, denis.
Seems like it´s more complicated than I initially thought.
I will try this code and if I run into any issues I will revert back to Boolean2.