Select all materials in model

Discussions concerning programming of SOFTIMAGE©
Falam

Select all materials in model

Post by Falam » 28 Jun 2013, 16:43

I want a script that selects all materials in a model, learning the SDK don't know how to set this up. :)

User avatar
xsisupport
Posts: 713
Joined: 09 Jun 2009, 11:02
Location: Montreal Canada
Contact:

Re: Select all materials in model

Post by xsisupport » 28 Jun 2013, 17:26

A model supports the Model interface, so you should go to the Model reference page and look through the properties and methods. You'll find your answer there.
// Steve Blair
// "You're not a runner, you're just a guy who runs" -- my wife
//
// My Blogs: Arnold | Softimage

Falam

Re: Select all materials in model

Post by Falam » 28 Jun 2013, 18:26

ActiveProject.SceneItem.Material
SceneItem.Material.

Atleast I hope I'm on the right path ? :)
The language syntax I'm grasping, putting it together, arghh.

User avatar
xsisupport
Posts: 713
Joined: 09 Jun 2009, 11:02
Location: Montreal Canada
Contact:

Re: Select all materials in model

Post by xsisupport » 28 Jun 2013, 19:41

You want to find all materials on a model. Those would return a single material.
On the Model reference page, there are two possibilities that jump out: Materials and FindObjects.
// Steve Blair
// "You're not a runner, you're just a guy who runs" -- my wife
//
// My Blogs: Arnold | Softimage

User avatar
Hirazi Blue
Administrator
Posts: 5107
Joined: 04 Jun 2009, 12:15

Re: Select all materials in model

Post by Hirazi Blue » 28 Jun 2013, 22:36

I fully understand this would be a weird way to approach the problem ("don't try this at home"), but couldn't you just iterate all materials and use the "UsedBy" property to figure out if a material is used by your specific model?
Stay safe, sane & healthy!

face
Posts: 57
Joined: 10 Jan 2010, 12:28

Re: Select all materials in model

Post by face » 28 Jun 2013, 22:38

To learn scripting, i wouldn´t try to make so "simple" things.
I haven´t much experience in scripting but i can say how i would make it in C++.

First of all, i would write a recursive function which can call itself like this:

Code: Select all

bool findChildren( Model inModel ) {

    return true;
}
Then i get the children under the model with GetChildren() as an CRef array:

Code: Select all

bool findChildren( Model inModel ) {

    CRefArray cRefs( inModel.GetChildren() );

    return true;
}
The next step is to go through the array and generate a X3DObject:

Code: Select all

bool findChildren( Model inModel ) {

    CRefArray cRefs( inModel.GetChildren() );
    for( LONG t = 0; t < cRefs.GetCount(); ++t ) {

        X3DObject obj( cRef.GetItem( t ) );
    }

    return true;
}
Then i would check, if the new obj is also a model and if yes, the function call itself:

Code: Select all

bool findChildren( Model inModel ) {

    CRefArray cRefs( inModel.GetChildren() );
    for( LONG t = 0; t < cRefs.GetCount(); ++t ) {

        X3DObject obj( cRef.GetItem( t ) );

        if( obj.GetType() == L"#model" )
            findChildren( Model( obj ) );

    }

    return true;
}
When the obj is a mesh or a surface, i would save the materials in another CRefArray.

Code: Select all

bool findChildren( Model inModel ) {

    CRefArray cRefs( inModel.GetChildren() );
    for( LONG t = 0; t < cRefs.GetCount(); ++t ) {

        X3DObject obj( cRef.GetItem( t ) );

        if( obj.GetType() == L"#model" )
            findChildren( Model( obj ) );

        else if( obj.GetType() == L"polymsh" || obj.GetType() == L"surfmsh" ) {

            CRefArray mats( obj.GetMaterials() )
        }

    }

    return true;
}
The next step is to store new materials to a CRefArray which should be a parameter in the function to transport it from call to call.

Code: Select all

bool findChildren( Model inModel, CRefArray& inArray ) {

    CRefArray cRefs( inModel.GetChildren() );
    for( LONG t = 0; t < cRefs.GetCount(); ++t ) {

        X3DObject obj( cRef.GetItem( t ) );

        if( obj.GetType() == L"#model" )
            findChildren( Model( obj ), inArray );

        else if( obj.GetType() == L"polymsh" || obj.GetType() == L"surfmsh" ) {

            CRefArray mats( obj.GetMaterials() )
            for( LONG u = 0; u < mats.GetCount(); ++u ) {
                
                Material mat( mats.GetItem( u ) );
                bool found = false;

                for( LONG o = 0; o < inArray.GetCount(); ++o )
                    if( inArray.GetItem( o ) ==  mat.GetRef() )
                        found = true;

                if( !found )
                    inArray.Add( mat.GetRef() );

            }
            mats.Clear();
        }

    }
    cRefs.Clear();

    return true;
}
Now i think the function is complete.
The last step is to call the function with:

Code: Select all

CRefArray matArray;
Selection selection( app.GetSelection() );
Model mod( selection.GetItem( 0 ) );

if( mod.GetType() == L"#model" )
    findChildren( mod, matArray );
After the call, the matArray will hold the CRefs of each material.
Haven´t test it and it´s possible that there are some errors. It´s only to show how it can work.
Hope this helps a little bit...

face

Falam

Re: Select all materials in model

Post by Falam » 29 Jun 2013, 12:12

Face - That was helpful except, as much as I understand how you did what you did in C++ it's converting it to Js for me to understand that is one of the issues, the other thing, the order of the code that needs to be done, to be able to select all the materials in a model.

Edit: I messed my own self over i-)
Last edited by Falam on 29 Jun 2013, 20:44, edited 1 time in total.

face
Posts: 57
Joined: 10 Jan 2010, 12:28

Re: Select all materials in model

Post by face » 29 Jun 2013, 14:51

Then i would prefer to take a look at the MaterialLibrary and check each material with UsedBy(), how Hirazi wrote...

face

User avatar
xsisupport
Posts: 713
Joined: 09 Jun 2009, 11:02
Location: Montreal Canada
Contact:

Re: Select all materials in model

Post by xsisupport » 29 Jun 2013, 15:40

// Steve Blair
// "You're not a runner, you're just a guy who runs" -- my wife
//
// My Blogs: Arnold | Softimage

SpookyMunky
Posts: 102
Joined: 14 Jun 2012, 02:30

Re: Select all materials in model

Post by SpookyMunky » 30 Jun 2013, 07:07

This is probably an embarrassingly silly way of doing what you want since I'm not very good at scripting, just searched around the xsi wiki and tried to understand some things for fun :), . Sorry for it being vbs(is all I know), shouldn't be too hard to convert to js if needed ?

Code: Select all

'Create a collection to add the materials to
Set ChildMaterials = CreateObject( "XSI.Collection" )

set oSelecto = Application.Selection(0)

'use findchildren to find the children ;)
Set oChildren = oSelecto.FindChildren2

'Itterate a simple material selection for each child and add to the collective
for i = 0 to (oChildren.Count - 1)
	
	DeselectAll
	
	'Select the child's material
	SelectMaterialsUsedBy oChildren(i)
	
	'add it to the ChildMaterials collection
	ChildMaterials.add application.Selection(0)
	
	'if it is a polygon / nurb surface then look for clusters and add their materials too
	if oChildren(i).type = "polymsh" or oChildren(i).type = "surfmsh" then
	
		for each oItem in oChildren
				
			on error resume next
		
			set oClusters = oItem.ActivePrimitive.Geometry.Clusters
			
			if ( err = 0 ) then
				
				for each oCls in oClusters
					
					DeselectAll
					
					'select the cluster's material
					SelectMaterialsUsedBy oCls
					
					'add it to the ChildMaterials collection
					ChildMaterials.add application.Selection(0)
					
				next
				
			end if	

		next
	
	end if

next

'Select the collection
selectobj ChildMaterials
just select a model and run..again it's probably a silly way to do it and might miss some materials.. kinda seems to work tho :)

http://softimage.wiki.softimage.com/sdk ... ldren2.htm
http://softimage.wiki.softimage.com/sdkdocs/Cluster.htm
http://softimage.wiki.softimage.com/sdk ... UsedBy.htm

Edit : Did a little bit work on it to get it working with multiple selections or start a picksession if no object selected. Also made it select the objects material / cluster material incase I select a polymesh or whatever instead of a model.. not really needed, am just a little ocd :).. http://pastebin.com/mu5WdR9X

NNois
Posts: 754
Joined: 09 Jun 2009, 20:33

Re: Select all materials in model

Post by NNois » 30 Jun 2013, 12:17

of topic... for thoses who just want to find without scripting... use the softimage search "Search selection" on materials...

Falam

Re: Select all materials in model

Post by Falam » 30 Jun 2013, 16:16

SpookyMunky wrote:This is probably an embarrassingly silly way of doing what you want since I'm not very good at scripting, just searched around the xsi wiki and tried to understand some things for fun :), . Sorry for it being vbs(is all I know), shouldn't be too hard to convert to js if needed ?

Code: Select all

'Create a collection to add the materials to
Set ChildMaterials = CreateObject( "XSI.Collection" )

set oSelecto = Application.Selection(0)

'use findchildren to find the children ;)
Set oChildren = oSelecto.FindChildren2

'Itterate a simple material selection for each child and add to the collective
for i = 0 to (oChildren.Count - 1)
	
	DeselectAll
	
	'Select the child's material
	SelectMaterialsUsedBy oChildren(i)
	
	'add it to the ChildMaterials collection
	ChildMaterials.add application.Selection(0)
	
	'if it is a polygon / nurb surface then look for clusters and add their materials too
	if oChildren(i).type = "polymsh" or oChildren(i).type = "surfmsh" then
	
		for each oItem in oChildren
				
			on error resume next
		
			set oClusters = oItem.ActivePrimitive.Geometry.Clusters
			
			if ( err = 0 ) then
				
				for each oCls in oClusters
					
					DeselectAll
					
					'select the cluster's material
					SelectMaterialsUsedBy oCls
					
					'add it to the ChildMaterials collection
					ChildMaterials.add application.Selection(0)
					
				next
				
			end if	

		next
	
	end if

next

'Select the collection
selectobj ChildMaterials
just select a model and run..again it's probably a silly way to do it and might miss some materials.. kinda seems to work tho :)

http://softimage.wiki.softimage.com/sdk ... ldren2.htm
http://softimage.wiki.softimage.com/sdkdocs/Cluster.htm
http://softimage.wiki.softimage.com/sdk ... UsedBy.htm

Edit : Did a little bit work on it to get it working with multiple selections or start a picksession if no object selected. Also made it select the objects material / cluster material incase I select a polymesh or whatever instead of a model.. not really needed, am just a little ocd :).. http://pastebin.com/mu5WdR9X
Verifying, this script selects all materials in a model ? :)

User avatar
csaez
Posts: 253
Joined: 09 Jul 2012, 15:31
Skype: csaezmargotta
Location: Sydney, Australia
Contact:

Re: Select all materials in model

Post by csaez » 30 Jun 2013, 17:32

Falam wrote:I want a script that selects all materials in a model, learning the SDK don't know how to set this up. :)
It is not the most elegant piece of code but works...

Code: Select all

model = Application.Selection(0)
materials = [material for child in model.FindChildren("*") for material in child.Materials]
Application.SelectObj(materials)

Falam

Re: Select all materials in model

Post by Falam » 30 Jun 2013, 17:52

Oh you python guys, maybe I should learn it :)
One more request, what about selecting all materials in a model without a specific progID (shader) ?

EricTRocks
Moderator
Posts: 754
Joined: 25 Nov 2009, 01:41
Contact:

Re: Select all materials in model

Post by EricTRocks » 30 Jun 2013, 20:57

Going to chime in here on this thread. Firstly, it's broken one of the rules I have setup in the "Programming Read First" thread. This board shouldn't be for requesting someone to write a script for you.

@Falam, you posted a meager 2 simplistic lines of code and not even in your first post. In the future you HAVE TO post code that isn't working. This is a forum for programming and like I mention above you shouldn't be coming to this board hoping that others are going to just give you the code.

These threads end up with little value in terms of learning programming since they simply have code that works. They aren't necessarily going through the steps of how to achieve the end goal, explaining each step along the way. We are going to end up with a ton of posts with code with no explanations and others aren't going to be able learn from them.


Here is some code that may help others understand the method of going through the model and its objects to find materials, then select them:

Code: Select all

from win32com.client import constants as c
from win32com.client.dynamic import Dispatch as d

xsi = Application
log = xsi.LogMessage
sel = xsi.Selection

def selectMdlMats(model):
    
    # If input object is not a model, return false.
    if model.Type != "#model": 
        log("Input object is not a model!", 4)
        return False
    
    mats = d("XSI.Collection") # Create an empty collection
    mats.Unique = True # Make sure objects only appear once in collection
    
    # Loop through the children of the model and find materials
    for eachChild in model.Children:
        childMats = eachChild.Materials
        mats.AddItems(childMats) # Add all materials on a child object to our mats collection
    
    return mats

if sel.Count: # Check that something is selected
    modelMats = selectMdlMats(sel(0)) # Pass first select object as function input
    # modelMats is now a pointer to the 'mats' returned from the selectMdlMats function
    
    if modelMats: # If the function returned something valid continue to select it
        sel.SetAsText(modelMats.GetAsText()) # Set selection from our mats collection
Eric Thivierge
Lead Kraken Developer, Fabric Engine
http://fabric-engine.github.io/Kraken

Falam

Re: Select all materials in model

Post by Falam » 30 Jun 2013, 21:08

Even if the code is Gobbledygook, alright, you said it.

Edit: Both csaez and Eric code do the same task, csaez is a little smaller, this ain't a competition. Either script is helpful, and beneficial I suppose I'm obliged to say 'thank you' to both. :)

Posting my code, on how to only select materials that don't contain a specific node, won't be understandable. Why I haven't, simply because I'm still coming to grips with the SDK and it would be a mess. Everyone is posting in Python, which is fine, but it would be a little helpful if someone would post in Javascript, so I can read it.

Post Reply

Who is online

Users browsing this forum: No registered users and 26 guests