Updating *shape.outMesh -> *shape.inMesh connection


#1

Hey there,

Let me setup a hypothetical scenario involving two Mesh/Polygon shapes. Shape A needs to look like Shape B which will be executed in a simple MEL procedure.

I’m utilizing the nifty trick of forcing Shape A to update its “look” from Shape B based on the outMesh-to-inMesh attributes. However, I noticed that Shape A will not update if Shape B is deleted after the connection is made within the procedure.

Is there anyway to force an update during a MEL procedure? I looked into and used the dgdirty command but it didn’t seem to work. I could be using it incorrectly of course.

The only solution I got working was to use the “evalDeferred” command in front of the “delete Shape B” command. However, this does not work in my actual code block that I’m writing. There are many other things going on (which I’d prefer to keep private for the time being) that could be keeping the shape from updating.

Just wondering if anyone might have a solution to force an update during a MEL procedure.

Thanks in advance!

Create a box named “obj1”.
Create a sphere named “obj2”.

This code will NOT work:

{
    string $shape1 = "objShape1";
    string $shape2 = "objShape2";
    
    connectAttr -f ($shape1 + ".outMesh") ($shape2 + ".inMesh");
    
    delete "obj1";
}

This code will work:

{
    string $shape1 = "objShape1";
    string $shape2 = "objShape2";
    
    connectAttr -f ($shape1 + ".outMesh") ($shape2 + ".inMesh");
    
    evalDeferred "delete obj1";
}

#2

That’s strange, didn’t notice that happening before.
You can force the viewport to redraw in your code via the “refresh” command.
It works fine then.

string $shape1 = "pCubeShape1";
string $shape2 = "pSphereShape1";

connectAttr -f ($shape1 + ".outMesh") ($shape2 + ".inMesh");
refresh;
delete "pCube1";

#3

It is not too strange. Almost everything in maya is triggered from a visible shape. If something is displayed in the viewport or some data are requested from some output attribute, the dg nodes are calculated. During script execution no UI updates happen (unless you force it with refresh), so no nodes are really calculated. But the input node is deleted in the script what leaves an empty output node. If I’m right, then requesting an output attribute should trigger the evaluation (but to be honest, I didn’t try it) and create the mesh.


#4

Ah! I had initially thought dgdirty also did a redraw.

Thanks for the explanation!


#5

Thanks a lot for the quick reply guys.

I did use refresh in one of my versions of the code, but I could have sworn it didn’t update the mesh with it. So after further investigation, I found out it’ll work in one scene but not another. Still investigating as to what causes the disconnect. I have lots of printing to do to find out what may or may not be working.

Thanks again!


#6

As much as I know it only makes the node/plug dirty what only means that it has to evaluate next time it is necessary. The actual evaluation should not start until any output is required. But I may be wrong.


#7

I think you are correct. I used the dgdirty to make nodes dirty/clean. This did not force an update though. There was an example I read recently involving other nodes, like the plusMinusAverage node. The code example included setAttr/getAttr commands to force an evaluation which was necessary to keep those nodes outputting properly. I can’t remember where I was reading this, I’ve been researching quite a few areas and finding different answers.


#8

Ah. That makes sense.

Though, I’m curious, when your blendshape nodes or any deformers aren’t evaluating, you can dgdirty the plugs to force an eval/redraw straight away.

If it was just marking the plug dirty, it wouldn’t actually cause a an eval until you at least moved the viewport or something, would it?


#9

I have no clue… Great question though. Oh Autodesk team, reveal your answers! hahaha…


#10

I know this is an old topic, but just wanted to add some more details for anyone finding this topic. :slight_smile:

Maya temporary .outMesh -> .inMesh without forced refresh

If you’d want to make a temporary connection and force evaluation then refresh does the trick, but it likely evaluates far more than what you need. So if you know exactly what you need to be evaluated you can force it manually. You can either trick it by querying something from the mesh, e.g. polyEvaluate -vertex shape2.

However, more explicity you could do so with dgeval, forcing an evaluation of a node or attribute. Here is a Python example of making a temporary mesh.outMesh to mesh.inMesh and have it correctly update the geometry without using refresh. It should be faster for most, if not all, cases. Plus it will avoid the viewport redraw.

Example

import maya.cmds as cmds

def transfer_mesh(src_mesh, tgt_mesh):
    
    # First collapse tweak points on the tgt_shape
    if cmds.polyCollapseTweaks(tgt_mesh, query=True, hasVertexTweaks=True):
        cmds.polyCollapseTweaks(tgt_mesh)

    cmds.connectAttr(src_mesh + ".outMesh", tgt_mesh + ".inMesh", force=True)
    cmds.dgeval(tgt_mesh) # Force outMesh update
    cmds.disconnectAttr(src_mesh + ".outMesh", tgt_mesh + ".inMesh")

# Example usage: select two meshes (by their transform, e.g. in viewport) and run
src, tgt = cmds.ls(sl=1)
src_shape = cmds.listRelatives(src, shapes=True, noIntermediate=True, fullPath=True, type="mesh")[0]
tgt_shape = cmds.listRelatives(tgt, shapes=True, noIntermediate=True, fullPath=True, type="mesh")[0]
transfer_mesh(src_shape, tgt_shape)

Note: This code example include some extra code to “freeze the vertices” due to mesh nodes in Maya having the capability of storing tweak points on it. When the Target mesh has tweaks in it, then they would be reapplied on the incoming new geometry. Meaning that still the meshes wouldn’t match, by collapsing these vertex tweaks that will be no longer be the case. More info on these tweak points on the mesh node, see .pnts - these are freezed using polyCollapseTweaks.