Getting the original shader assignment

65 views
Skip to first unread message

likage

unread,
Oct 6, 2016, 9:08:29 PM10/6/16
to Python Programming for Autodesk Maya

Was wondering if anyone has any good ways for approaching this problem of mine...


I have a few rigs in which it is a reference. I am trying to do some shader-assignment that targets for a certain name in these rigs.

In my UI, if the user selects a certain color in the combobox, it will create a new shader and assign to the geos within that rig(s). And if it selects the first index of the combobox which is a blank, it will reassign those geos back to shaders that it was initially assigned.


For example, I have a test_geo (this is a reference) and it comes with a "test_geoShader (lambert)". If I select any other color, the connect between the test_geo and test_geoShader will be disconnected and it will be assigned with a new shader, eg. newShader (lambert) If I select the 'blanked' option, it will disconnect test_geo with the new shader and assigned back to test_geoShader


However, my code (pls see below) only works on the first try to get the original assignment.. Meaning to say if I open my UI the first time, did some new shader assignments, close and reopen my UI, it will pick up the current assignment it has as the original assignment..


Any suggestions in approaching this? And is it possible to do so without creating any new files (json etc..) to store the data?


def get_orig_shader(self, nodes_list):
    orig_shader_dict
= {}
   
for node_name in nodes_list:            
        node_shapes
= get_shape(node_name)
       
for node in node_shapes:
           
if "defaultPtx" in node:
                shading_grps
= cmds.listConnections(node, type='shadingEngine')
                shaders
= cmds.ls(cmds.listConnections(shading_grps), materials=1)
                orig_shader_dict
[node] = shaders[0]


Justin Israel

unread,
Oct 6, 2016, 9:26:31 PM10/6/16
to python_in...@googlegroups.com
On Fri, Oct 7, 2016 at 2:08 PM likage <dissid...@gmail.com> wrote:

Was wondering if anyone has any good ways for approaching this problem of mine...


I have a few rigs in which it is a reference. I am trying to do some shader-assignment that targets for a certain name in these rigs.

In my UI, if the user selects a certain color in the combobox, it will create a new shader and assign to the geos within that rig(s). And if it selects the first index of the combobox which is a blank, it will reassign those geos back to shaders that it was initially assigned.


For example, I have a test_geo (this is a reference) and it comes with a "test_geoShader (lambert)". If I select any other color, the connect between the test_geo and test_geoShader will be disconnected and it will be assigned with a new shader, eg. newShader (lambert) If I select the 'blanked' option, it will disconnect test_geo with the new shader and assigned back to test_geoShader


However, my code (pls see below) only works on the first try to get the original assignment.. Meaning to say if I open my UI the first time, did some new shader assignments, close and reopen my UI, it will pick up the current assignment it has as the original assignment..


Any suggestions in approaching this? And is it possible to do so without creating any new files (json etc..) to store the data?

Well the fact of the matter is that you would have to persist this information somewhere, right? There are a ton of places to store this information, but it also depends on whether you need this persistent to outlive the current Maya session?

global dictionary in your module
optionVars
files (json, ...)
custom attribute on the node to store the original value

The last one could be useful, because it would obviously be stored directly on the node in which you are considering. And you could check to see if the custom attribute exists to know whether you have ever applied a change with your UI.


def get_orig_shader(self, nodes_list):
    orig_shader_dict
= {}
   
for node_name in nodes_list:            
        node_shapes
= get_shape(node_name)
       
for node in node_shapes:
           
if "defaultPtx" in node:
                shading_grps
= cmds.listConnections(node, type='shadingEngine')
                shaders
= cmds.ls(cmds.listConnections(shading_grps), materials=1)
                orig_shader_dict
[node] = shaders[0]


--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/785548cf-e276-433b-aaf8-6e8462a295a4%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

likage

unread,
Oct 7, 2016, 12:38:56 PM10/7/16
to Python Programming for Autodesk Maya
Hey Justin, correct me if I am wrong on this..

So while I did try using global dictionary, it only works on the first try too, but as soon as I close and reopen my UI, the original assignment is gone.. Giving me the same issue as stated in my thread.
I must be doing something very wrong in my logic and if possible, could you kindly enlighten me on this?

I suppose using of json files work but if can be, I would not want to introduce in a new file creation which is solely just for containing the assignments.

Will need to check up on optionsVars to see if it caters to my need

Justin Israel

unread,
Oct 7, 2016, 4:36:03 PM10/7/16
to python_in...@googlegroups.com
On Sat, Oct 8, 2016 at 5:38 AM likage <dissid...@gmail.com> wrote:
Hey Justin, correct me if I am wrong on this..

So while I did try using global dictionary, it only works on the first try too, but as soon as I close and reopen my UI, the original assignment is gone.. Giving me the same issue as stated in my thread.
I must be doing something very wrong in my logic and if possible, could you kindly enlighten me on this?

In your original example, the problem that you are seeing is you are not conditionally updating your default dict only when it doesn't have an entry (at least not how I read it). So each time you run the code, it will just update the dict with the current value before changing to another shader. The logic needs to include something like this:

some_persistent_dict = {}
...
entry = 'node_name'
if not entry in some_persistent_dict:
    # We have never recorded the original shader.
    some_persistent_dict[entry] = get_original_shader(entry)
# Standard behavior
assign_new_shader(entry)

Any of your options (global dict, optionVar, file, node attributes, ...) will require a step like this to see if the original shader needs to be recorded. If you don't do this, you will always trample your previous value with the current one.

Hope this helps



I suppose using of json files work but if can be, I would not want to introduce in a new file creation which is solely just for containing the assignments.

Will need to check up on optionsVars to see if it caters to my need

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

zeth willie

unread,
Oct 7, 2016, 5:12:34 PM10/7/16
to Python Programming for Autodesk Maya
I would look at message attributes. i.e. create a message attribute somewhere on the rig (top level?) and plug the "message" attr of the shader or shading group into that. Then it's persistent across maya sessions,etc. Should be pretty easy to add to your script, too.

#create and connect message attr
cmds.addAttr(YOUR_RIG_OBJ, at="message", ln="origShader")
cmds.connectAttr("{0}.message".format(YOUR_SHDR), "{0}.origShader".format(YOUR_RIG_OBJ))

# getting object back from the message attr is bit weird, maybe there's an easier way? I'm getting the attr then getting the object from that
orig = cmds.connectionInfo("{0}.origShader".format(YOUR_RIG_OBJ), sfd=True).partition(".")[0]

Z

likage

unread,
Oct 7, 2016, 9:09:14 PM10/7/16
to Python Programming for Autodesk Maya
@Justin
Okay, I will try that out again. Did not saw your message as I was trying something from this link in which I create a locator and store the 'original' assignment under this new locators' extra attributes
But still, it starts to fail very badly when I tried to introduce logics in checking whether the locator exists and what to do after, especially so when I start adding in or removing an item, the assignments went very hay wire...

@Zeth
Did not saw your reply too. But I will try that out and see how it goes. I do not think that I can add a custom attribute to the rigs, as they are all references, I may be wrong on this, gotta try and give it another whirl


Message has been deleted

likage

unread,
Oct 13, 2016, 9:10:13 PM10/13/16
to Python Programming for Autodesk Maya
Hi all, so I have managed to store the initial shaders connection and it is currently working by using the above example that I have linked where they are stored as an extra attribute in a locator.

Currently I am stumped in an issue, where should the name of the said geo be changed, it should also changed the naming in the dict within that extra attribute.
Example.
One of the elements' naming in the dict:
'|Stack|model_from_groupA|group_01|roof_grp|roof_geoShape':'brick_shader'

If the hierarchy is renamed to:
'|Stack|model_A|group_01|roof_grp|roof_geoShape', the model_from_groupA (second level in the full path) should be named to model_A. 
Only that 'particular level' in hierarchy will be touched upon

While it works correctly for 1 object in scene, but if I have 2 or more objects, the renaming process will works but it is renaming incorrectly to the wrong objects.
Suppose the current dict values (before any nodes are renamed in scene) is:
cur_keytext_in_dict = {'|Stack|model_from_groupA|group_01|model_A_roof_grp|model_A_roof_geoShape':'brick_shader','|Stack|model_from_groupB|group_01|model_B_roof_grp|model_B_roof_geoShape':'brick_shader'}

And if I renamed, model_from_groupA to model_A and model_from_groupB to model_B, I can get the following results:
'|Stack|model_B|group_01|model_A_roof_grp|model_A_roof_geoShape', '|Stack|model_A|group_01|model_B_roof_grp|model_B_roof_geoShape'
See that model_B is renamed to the model_A geos and vice verse for model_A

I tried the following code:
cur_keytext_in_dict = {'|Stack|model_from_groupA|group_01|model_A_roof_grp|model_A_roof_geoShape':'brick_shader','|Stack|model_from_groupB|group_01|model_B_roof_grp|model_B_roof_geoShape':'brick_shader'}
cur_name_in_scene 
= ['|Stack|model_A|group_01|model_A_roof_grp|model_A_roof_geoShape', '|Stack|model_B|group_01|model_B_roof_grp|model_B_roof_geoShape']


for split_name in cur_name_in_scene:
    split_check 
= split_name.split("|", 4)[4]
    # result : model_A_roof_grp|model_A_roof_geoShape, model_B_roof_grp|model_B_roof_geoShape

But how can I replace the 'front' portion of the correct code after using the above check?
Hopefully I am making sense?

Justin Israel

unread,
Oct 13, 2016, 9:28:06 PM10/13/16
to python_in...@googlegroups.com
Maybe this suggestion doesn't work for your application, but is there any reason you can't store it as an attribute on each individual geo node, instead of building up some huge fullpath set on a locator? If it were stored on the geo, then you don't have to worry about tracking the renaming, right? It just travels around with the geo and you can query the original shader on that given node.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

likage

unread,
Oct 15, 2016, 6:16:26 PM10/15/16
to Python Programming for Autodesk Maya
After some trial and error around, I managed to come up with a 'hacky' way of renaming it by splitting the keys in the dict then creating a new dict which store the current connections (with the new naming) while comparing the last 2 elements in the scene to replace them.

While I understand this may not be the ideal solution and that placing the connection in the geo is a better idea, I was faced with some issues that does not allow me to do so for some reasons..
Thanks again for the inputs! I will try to submit my code as a first pass and see if it works for the artist

To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages