CGTalk > Software Specific Forums > Autodesk 3ds max > 3dsMax SDK and MaxScript
Login register
Thread Closed share thread « Previous Thread | Next Thread »  
 
Thread Tools Search this Thread Display Modes
Old 09-21-2007, 09:29 AM   #1
AJ
Totoro
 
AJ's Avatar
CGTalk Forum Leader
portfolio
Alex Jefferies
Director
MDI Digital Ltd
Norwich, United Kingdom
 
Join Date: Dec 2001
Posts: 4,961
Groups & opening...

Hello!

I've (very poorly) written a script that selects objects by the active material, sorts those that are in a group, opens those groups & then finally re-selects them.
Code:
Mat = meditmaterials[medit.GetActiveMtlSlot()] MatObj = #() -- Collect all objects with material applied for i in $* do ( if i.material == Mat then append MatObj i ) if MatObj.count == 0 then print "Nothing has this material you fool!" -- Seperate objects that are in a group ObjNum = MatObj.count GroupedObj = #() for s = 1 to ObjNum do ( if isGroupMember MatObj[s] then (append GroupedObj MatObj[s]) else false ) -- Opens all groups ObjCount = GroupedObj.count progressStart "Opening Groups" for y = 1 to ObjCount do ( select MatObj max group open progressupdate (100.0*y/ObjCount) ) progressEnd() select MatObj


It works, but I know that the last part (Opens all groups) isn't as efficient as it should be.

Firstly it loops through the MatObj array & tries to open the selection for every grouped object - not for every group.

Secondly, I couldn't find a cleaner way to open a group other than 'max group open'. Is there any way to select/find the group node & manipulate it?

Thirdly, I am terrible at maxscript, I was only able to cobble this together thanks to Bobo's fantastic 'Maxscript for the Masses' DVD... So any other improvements or advice would be greatly appreciated.

Thanks!
__________________
SKETCHBOOK
MDI
moonjam.com

Last edited by AJ : 09-21-2007 at 09:31 AM.
 
Old 09-21-2007, 02:36 PM   #2
Gravey
3D Dude
Joel Hewitt
Sydney, Australia
 
Join Date: Dec 2005
Posts: 879
there are a few things you can do to make your code more efficient. The following code will do what you require and in only 4 lines!
Code:
mat = meditmaterials[medit.GetActiveMtlSlot()] matObj = for o in objects where (superclassof o == GeometryClass OR superclassof o == Shape) AND o.material == mat collect o for m in matObj where isGroupMember m AND (NOT isOpenGroupMember m) do setGroupOpen m.parent true select matObj
The first line defines 'mat' the same way you have.

Next line loops through all objects that are either geometry or shape objects (incase you are using renderable splines) and has the material 'mat' and collects that object into an array and the result is stored in the variable 'matObj'. The collect function is faster than append and you can use 'where' as I have to subsitute for your if statement which i believe would also be faster.

Then loop through matObj looking for groupmembers that are part of a group that has not already been opened, and then of course, open the group. Skipping groupMembers that are in a group that is already open saves time as you can imagine.

Finally, select the objects with the given material

I hope this all makes sense. If not let me know specifics and I'll try to explain them better.
I recommend you watch bobo's dvd again and again and just practice scripting with small projects that make simple repetative tasks easier for yourself.

Last edited by Gravey : 09-21-2007 at 02:38 PM.
 
Old 09-21-2007, 03:36 PM   #3
AJ
Totoro
 
AJ's Avatar
CGTalk Forum Leader
portfolio
Alex Jefferies
Director
MDI Digital Ltd
Norwich, United Kingdom
 
Join Date: Dec 2001
Posts: 4,961
Oh that's wonderful - thank you!

I will keep trying... I tend to fall into the trap of plotting out each task I need a script to perform in the order & in the method I would manually in Max - so even though it's 'doing the work for me', it's going around the horn to get there.

Once again, thank you.
__________________
SKETCHBOOK
MDI
moonjam.com
 
Old 09-21-2007, 04:20 PM   #4
AJ
Totoro
 
AJ's Avatar
CGTalk Forum Leader
portfolio
Alex Jefferies
Director
MDI Digital Ltd
Norwich, United Kingdom
 
Join Date: Dec 2001
Posts: 4,961
One quick question, the script is very fast but I've tried it on a scene in production (lots of nested groups...etc.) recieved the following error:

--Runtime error: Not a valid group head: $Dummy:Dummy @ (and then some point3 coords)


What could cause this?
__________________
SKETCHBOOK
MDI
moonjam.com
 
Old 09-22-2007, 12:17 AM   #5
Gravey
3D Dude
Joel Hewitt
Sydney, Australia
 
Join Date: Dec 2005
Posts: 879
not sure, i did some quick tests and it seemed to work fine. Maybe try adding the following code in between ... (NOT isOpenGroupMember m) ... and ... do setGroupOpen ...
Code:
AND isGroupHead m.parent
I could look at your scene but since its a production scene i doubt that'd b possible. Let me know if this doesnt fix the problem
 
Old 09-24-2007, 10:28 AM   #6
AJ
Totoro
 
AJ's Avatar
CGTalk Forum Leader
portfolio
Alex Jefferies
Director
MDI Digital Ltd
Norwich, United Kingdom
 
Join Date: Dec 2001
Posts: 4,961
I found the problem, the objects inside the group are all parented to a dummy, also inside the group. So the hierarchy went

Group01
->Dummy
-->Object01
-->Object02
-->Object03


So the script errors because it only 'steps up' the chain to Object01's parent, instead of the top of the chain.

Your code "AND isGroupHead m.parent" helps stop the error - which is great, but I'm now trying find a way to use it to tell Max to traverse further up the chain to find the GroupHead...

At the moment I just have:

Code:
for m in matObj where isGroupMember m AND (NOT isOpenGroupMember m) do ( if isGroupHead m.parent != false then setGroupOpen m.parent true else setGroupOpen m.parent.parent true )

Which obviously only solves the problem in my specific instance - where the grouphead is only one .parent away...

I really appreciate your help on this. I'm going to try to find a way to solve it myself but any suggestions you have would be fantastic.
__________________
SKETCHBOOK
MDI
moonjam.com

Last edited by AJ : 09-24-2007 at 10:30 AM.
 
Old 09-24-2007, 10:57 AM   #7
AJ
Totoro
 
AJ's Avatar
CGTalk Forum Leader
portfolio
Alex Jefferies
Director
MDI Digital Ltd
Norwich, United Kingdom
 
Join Date: Dec 2001
Posts: 4,961
I think I've cracked it.

I defined the following function:

Code:
fn GroupOpen OpenMe = ( if isGroupHead OpenMe.parent != false then setGroupOpen OpenMe.parent true else GroupOpen OpenMe.parent )


And then used it like this:
Code:
mat = meditmaterials[medit.GetActiveMtlSlot()] matObj = for o in objects where (superclassof o == GeometryClass OR superclassof o == Shape) AND o.material == mat collect o for m in matObj where isGroupMember m AND (NOT isOpenGroupMember m) do GroupOpen m select matObj

It works - seemingly... Again, I just don't know if it's the most efficient way to do so!
__________________
SKETCHBOOK
MDI
moonjam.com
 
Old 09-24-2007, 11:32 AM   #8
Gravey
3D Dude
Joel Hewitt
Sydney, Australia
 
Join Date: Dec 2005
Posts: 879
The way you have it seems to only work at one or 2 levels of the heirachy.
Code:
for m in matObj where isGroupMember m AND (NOT isOpenGroupMember m) do ( par = m.parent while par != undefined do ( if isGroupHead par then ( setGroupOpen par true par = undefined ) else par = par.parent ) )
This should work through as many parents as it takes before it reaches the grouphead. Let me know if you want clarification on how it all works
 
Old 09-24-2007, 12:18 PM   #9
AJ
Totoro
 
AJ's Avatar
CGTalk Forum Leader
portfolio
Alex Jefferies
Director
MDI Digital Ltd
Norwich, United Kingdom
 
Join Date: Dec 2001
Posts: 4,961
Nope that all makes perfect sense - thank you once more!

Although as far as I'm aware (and I'm not particularly aware!), both of our scripts are performing (practically) the same function...?

Quote:
The way you have it seems to only work at one or 2 levels of the heirachy.

It does?
I thought the fact that if m.parent returns false in the GroupOpen function it calls on itself with an additional .parent would cycle through the whole heirachy until it got to the GroupHead?

Like I said, I'm a novice and your solution certainly works so I'm not going to question it - I just want to make sure I understand the difference in the two methods.
__________________
SKETCHBOOK
MDI
moonjam.com
 
Old 09-24-2007, 01:45 PM   #10
Gravey
3D Dude
Joel Hewitt
Sydney, Australia
 
Join Date: Dec 2005
Posts: 879
sorry i missread your code for your function. I thought it said '... else SetGroupOpen OpenMe.parent'
If your way works then great! I wasn't aware that you could call a function from inside itself!
 
Old 09-24-2007, 01:45 PM   #11
CGTalk Moderation
Lord of the posts
CGTalk Forum Leader
 
Join Date: Sep 2003
Posts: 1,066,481
Thread automatically closed

This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.
__________________
CGTalk Policy/Legalities
Note that as CGTalk Members, you agree to the terms and conditions of using this website.
 
Thread Closed share thread


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
CGSociety
Society of Digital Artists
www.cgsociety.org

Powered by vBulletin
Copyright 2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump
Miscellaneous

All times are GMT. The time now is 02:20 AM.


Powered by vBulletin
Copyright ©2000 - 2016, Jelsoft Enterprises Ltd.