Missing Attributes in Shader created from Mdl

Hi,

I was trying to apply a material on a xform (target prim) using the following script

from pxr import UsdShade

f_path = "/NVIDIA/Materials/Base/Carpet/Carpet_Cream.mdl"
mtl_url = self.default_server+f_path
mtl_name = f_path.split("/")[-1].split(".")[0]
omni.kit.commands.execute("CreateMdlMaterialPrim",
                                  mtl_url=mtl_url,
                                  mtl_name=mtl_name,
                                  mtl_path="/Looks/"+mtl_name)
mtl_prim = self._my_world.stage.GetPrimAtPath("/Looks/"+mtl_name)

mat_shade = UsdShade.Material(mtl_prim)
UsdShade.MaterialBindingAPI(target_prim).Bind(mat_shade, 
                               UsdShade.Tokens.strongerThanDescendants)
shade_prim = mtl_prim.GetAllChildren()[0]

Then I want to set the attributes inputs:project_uvw and inputs:world_or_object to True

shade_prim.GetAttribute('inputs:project_uvw').Set(True)
shade_prim.GetAttribute('inputs:world_or_object').Set(True)

However, the following error was returned

'Empty typeName for </Looks/Carpet_Cream/Shader.inputs:project_uvw>'

Interestingly, after I click on the material in the GUI, the attributes can be found and set using the above script.

Did I do something wrong when creating the material? Is there anyway to ensure the attributes to be accessible in the python api after creating the material?

Thank you in advance for any input and help.

Hi @chris.tung - The error message you’re seeing suggests that the attribute you’re trying to access doesn’t exist at the time you’re trying to set it. This could be because the material hasn’t been fully created and loaded into the stage at the time you’re trying to access its attributes.

In the Omniverse Kit, the creation of materials and other operations are asynchronous. This means that they don’t complete immediately when the command is issued, but instead they are scheduled to be completed in the future. This allows the system to continue processing other tasks without waiting for the material creation to complete.

To ensure that the material is fully created and its attributes are accessible, you can use the omni.kit.commands.wait_for_commands() function after creating the material. This function will block the script until all previously issued commands have completed.

Here’s how you can modify your script:

from pxr import UsdShade

f_path = "/NVIDIA/Materials/Base/Carpet/Carpet_Cream.mdl"
mtl_url = self.default_server+f_path
mtl_name = f_path.split("/")[-1].split(".")[0]

omni.kit.commands.execute("CreateMdlMaterialPrim",
                          mtl_url=mtl_url,
                          mtl_name=mtl_name,
                          mtl_path="/Looks/"+mtl_name)

# Wait for the material creation command to complete
omni.kit.commands.wait_for_commands()

mtl_prim = self._my_world.stage.GetPrimAtPath("/Looks/"+mtl_name)
mat_shade = UsdShade.Material(mtl_prim)

UsdShade.MaterialBindingAPI(target_prim).Bind(mat_shade,
                                              UsdShade.Tokens.strongerThanDescendants)

shade_prim = mtl_prim.GetAllChildren()[0]

# Now the attributes should be accessible
shade_prim.GetAttribute('inputs:project_uvw').Set(True)
shade_prim.GetAttribute('inputs:world_or_object').Set(True)

This should ensure that the material is fully created and its attributes are accessible before you try to set them.

Thanks @rthaker, after I added the line

omni.kit.commands.wait_for_commands()

but it’s returned with the error

module 'omni.kit.commands' has no attribute 'wait_for_commands'

I am using IsaacSim 2022.2.1.

not sure if it’s related, but came across this post (if it’s not relevant, feel free to ignore):

p.s. looks like the newest omni.kit.usd doc (1.1.1) can be found here - USD in Kit — omni.kit.usd_docs 1.1.1 documentation

1 Like

Big thank you to @Simplychenable. I have managed to find the attributes after adding

lp = stage.GetPrimAtPath('/Looks')
mtl_prims = lp.GetAllChildren()
shd_prims = [p.GetPrimPath().pathString+'/Shader' for p in mtl_prims]
selection = omni.usd.get_context().get_selection()
selection.set_selected_prim_paths(shd_prims, False)
for _ in range(5):
    kit.update()

The key is to select the prims with the python api, then the attributes will be authored.
Once again, really appreciate your help.

2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.