All group members


#1

Hey, I need your help. Everything seams to be obvious, and very easy, but I can’t get to the solution.

I have a group of objects, and I have access only to the top head of this group, let’s say Dummy:Group01

How can I get all it’s members?

PS: this is not the situation when this group is selected. I should not select it.
I could select the head and automatically all it’s members could get selected and the solution is ready. But I need to keep at this moment other selection!


#2

easy solution is

allmembers = join #() groupheadnode

the right solution is different. but most likely you have to be OK with easy solution


#3

Thank you, Denis!
By the way, how to call correctly, to be understandable by all max users, Open Group Red Boxes?


#4

http://forums.cgsociety.org/showthread.php?f=98&t=1151850&highlight=isgrouphead
http://forums.cgsociety.org/showthread.php?f=98&t=1110844&highlight=isgrouphead

check these threads…
the easy way is not correct because it collects all “children” of a node. it’s true that all group members are children of group head, but it’s not true that all children are group members


#5

I’m not going to participate here.
The last time was painful. :slight_smile:


#6

The last time we learned something new and useful.


#7

I hope so. But Denis always has something to add and thread discussion goes crazy :slight_smile:
Just kidding. I like the way he motivates people to make the effort to learn something new.
With him is always a challenge :slight_smile: (ps. links above show that)


#8

so… :slight_smile: any idea how to find ALL and ONLY group members for “Group003” head in this setup:

delete objects
(
	b0 = box pos:[40,0,0] wirecolor:orange
	b1 = box pos:[80,0,0] wirecolor:orange

	g0 = group #(b0,b1)

	b2 = box pos:[40,40,0] wirecolor:green
	b3 = box pos:[80,40,0] wirecolor:green

	g1 = group #(b2,b3)
	g2 = group #(g0,g1)

	in (box pos:[0,0,40] wirecolor:blue) (g2.parent = box pos:[0,0,80] wirecolor:red)
	for g in #(g0,g1,g2) do setGroupOpen g on
	
	in b0 (box pos:[0,0,80] wirecolor:blue)
	in g0 (box pos:[0,0,120] wirecolor:blue)
	
	a0 = box pos:[0,40,80]
	a1 = box pos:[0,80,80]
	g3 = group #(a0,a1)
	g3.parent = g2
)

#9

And the challenge begins. First try


grp = datapair master:null slaves:#()
for o in objects where isgrouphead o do
(
	if canconvertto o.parent Editable_mesh then grp.master = o else append grp.slaves o 
)
grp


#10

here is right answer:


#11

there are might be any nodes… we don’t have to check if they are geometry or not.
you can change all boxes to points for example. it doesn’t matter.


#12

Hmmm… I hope that i’m not only one here :slight_smile:
This will be the long night :slight_smile:


#13

Something like this maybe ?


mapped fn open_close groups state: = setGroupOpen groups state
fn findRealGroupMembers groupNode = if isGroupHead groupNode do
(
	real_group_members = #()
	closed_groups = for g in groupNode where isgrouphead g and not isOpenGroupHead g collect g
	if closed_groups.count > 0 do open_close closed_groups state:on
	for grp in groupNode.children where isgrouphead grp and isOpenGroupMember grp do
	(
		for m in grp where isOpenGroupMember m do append real_group_members m
	)
	if closed_groups.count > 0 do open_close closed_groups state:off
	real_group_members
)
findRealGroupMembers $Group003


#14

no… it works just for a specific case. let’s change the combination:

delete objects
(
	c0 = box name:"c0" pos:[40,40,0] wirecolor:orange
	c1 = box name:"c1" pos:[40,80,40] wirecolor:orange
	c2 = box name:"c2" pos:[40,80,0] wirecolor:orange

	b0 = box name:"b0" pos:[40,0,0] wirecolor:orange
	b1 = box name:"b1" pos:[80,0,0] wirecolor:orange


	b2 = box name:"b2" pos:[40,40,0] wirecolor:green
	b3 = box name:"b3" pos:[80,40,0] wirecolor:green

	g4 = group #(c1,c2) name:"g4"
	g0 = group #(b0,b1)	name:"g0" 
	g4.parent = b0
	
	g1 = group #(b2,b3,g0) name:"g1" 
	g2 = group #(c0, g1) name:"g2" 
	
	in b0 (box name:"d0" pos:[0,0,80] wirecolor:blue)
	in g0 (box name:"d1" pos:[0,0,120] wirecolor:blue)
	
	a0 = box name:"a0" pos:[0,40,80]
	a1 = box name:"a1" pos:[0,80,80]
	g3 = group #(a0,a1) name:"g3"  
	g3.parent = g2
	
	for g in #(g0,g1,g2,g3,g4) do setGroupOpen g on
)

here are right members for “g2” and yours. yours is wrong.


#15

also opening and closing groups shouldn’t be used in method. it’s always better to not change scene state if it’s not necessary.


#16
delete objects
 (
 	fn getClRootGroupHead node = if node != undefined do
 	(
 		with undo on
 		(	
 			if isgroupmember node then
 			(
 				if isOpenGroupHead node.parent then 
 				(	
 					node.parent
 				)	
 				else	
 					getClRootGroupHead node.parent
 			)
 			else node
 		)
 	)
 	
 	fn getRootGroupHead node = if node != undefined do
 	(
 		if isgroupmember node then
 		(
 			getRootGroupHead node.parent
 		)
 		else node
 	)
 	
 	fn findRealGroupMembers allmembers node = 
 	(
 		real_group_members = #()
 		for s in allmembers do
 			if (getRootGroupHead s) == node and (not isgrouphead s) do
 		appendIfUnique real_group_members s
 		print real_group_members
 		select real_group_members
 	)		
 	
 	
 	c0 = box name:"c0" pos:[40,40,0] wirecolor:orange
 	c1 = box name:"c1" pos:[40,80,40] wirecolor:orange
 	c2 = box name:"c2" pos:[40,80,0] wirecolor:orange
 
 	b0 = box name:"b0" pos:[40,0,0] wirecolor:orange
 	b1 = box name:"b1" pos:[80,0,0] wirecolor:orange
 
 
 	b2 = box name:"b2" pos:[40,40,0] wirecolor:green
 	b3 = box name:"b3" pos:[80,40,0] wirecolor:green
 
 	g4 = group #(c1,c2) name:"g4"
 	g0 = group #(b0,b1)	name:"g0" 
 	g4.parent = b0
 	
 	g1 = group #(b2,b3,g0) name:"g1" 
 	g2 = group #(c0, g1) name:"g2" 
 	
 	in b0 (box name:"d0" pos:[0,0,80] wirecolor:blue)
 	in g0 (box name:"d1" pos:[0,0,120] wirecolor:blue)
 	
 	a0 = box name:"a0" pos:[0,40,80]
 	a1 = box name:"a1" pos:[0,80,80]
 	g3 = group #(a0,a1) name:"g3"  
 	g3.parent = g2
 	
 	for g in #(g0,g1,g2,g3,g4) do setGroupOpen g on
 	
 	clearlistener()
 	allmembers = join #() (getClRootGroupHead g2) 
 
 	
 	findRealGroupMembers allmembers (getClRootGroupHead g2) 
 )

#17

it’s very close to the right… but g1 and g0 are members too.


#18

and there is a way to do it without recursion which is faster :wink:


#19

it’s not working for every case… for example a new setup, but the same task - “all real members of g2”:

(
 	 f0 = box name:"f0" pos:[80,40,0] wirecolor:orange
 	 in f0 (f1 = box name:"f1" pos:[80,80,40] wirecolor:orange)
 	 in f1 (f2 = box name:"f2" pos:[80,80,0] wirecolor:orange)
 	 
 	 c0 = box name:"c0" pos:[40,40,0] wirecolor:orange
 	 c1 = box name:"c1" pos:[40,80,40] wirecolor:orange
 	 c2 = box name:"c2" pos:[40,80,0] wirecolor:orange
  
 	 b0 = box name:"b0" pos:[40,0,0] wirecolor:orange
 	 b1 = box name:"b1" pos:[80,0,0] wirecolor:orange
  
  
 	 b2 = box name:"b2" pos:[40,40,0] wirecolor:green
 	 b3 = box name:"b3" pos:[80,40,0] wirecolor:green
  
 	 g4 = group #(c1,c2) name:"g4"
 	 g0 = group #(b0,b1)	name:"g0" 
 	 g4.parent = b0
 	 
 	 g1 = group #(b2,b3,g0) name:"g1" 
 	 g2 = group #(c0, g1) name:"g2" 
 	 
 	 in b0 (box name:"d0" pos:[0,0,80] wirecolor:blue)
 	 in g0 (box name:"d1" pos:[0,0,120] wirecolor:blue)
 	 
 	 a0 = box name:"a0" pos:[0,40,80]
 	 a1 = box name:"a1" pos:[0,80,80]
 	 g3 = group #(a0,a1) name:"g3"  
 	 g3.parent = g2
 	 
 	g5 = group #(f0,f1,f2,g2) name:"g5"
 	
 	 for g in #(g0,g1,g2,g3,g4,g5) do setGroupOpen g on
 )

this is right members:


#20
delete objects
(
	fn getClRootGroupHead node = if node != undefined do
	(
		with undo on
		(	
			if isgroupmember node then
			(
				if isOpenGroupHead node.parent then 
				(	
					node.parent
				)	
				else	
					getClRootGroupHead node.parent
			)
			else node
		)
	)
	
	fn getRootGroupHead node = if node != undefined do
	(
		if isgroupmember node then
		(
			getRootGroupHead node.parent
		)
		else node
	)
	
	fn findRealGroupMembers node = 
	(
		allmembers = join #() node
		real_group_members = for s in allmembers where (getRootGroupHead s) == node and (not isgrouphead s) collect s
		return real_group_members
	)		
	
	
	c0 = box name:"c0" pos:[40,40,0] wirecolor:orange
	c1 = box name:"c1" pos:[40,80,40] wirecolor:orange
	c2 = box name:"c2" pos:[40,80,0] wirecolor:orange

	b0 = box name:"b0" pos:[40,0,0] wirecolor:orange
	b1 = box name:"b1" pos:[80,0,0] wirecolor:orange


	b2 = box name:"b2" pos:[40,40,0] wirecolor:green
	b3 = box name:"b3" pos:[80,40,0] wirecolor:green

	g4 = group #(c1,c2) name:"g4"
	g0 = group #(b0,b1)	name:"g0" 
	g4.parent = b0
	
	g1 = group #(b2,b3,g0) name:"g1" 
	g2 = group #(c0, g1) name:"g2" 
	
	in b0 (box name:"d0" pos:[0,0,80] wirecolor:blue)
	in g0 (box name:"d1" pos:[0,0,120] wirecolor:blue)
	
	a0 = box name:"a0" pos:[0,40,80]
	a1 = box name:"a1" pos:[0,80,80]
	g3 = group #(a0,a1) name:"g3"  
	g3.parent = g2
	
	for g in #(g0,g1,g2,g3,g4) do setGroupOpen g on
	
	
	
	clearlistener()
	select (findRealGroupMembers (getClRootGroupHead g2))
	print (findRealGroupMembers (getClRootGroupHead g2))
)