## CycleChecking

### Introduced

v3.5

### Description

Checks the Graph For Operator Evaluation Cycles. An evaluation cycle is a looped graph dependency where an operation is dependent on itself.
This function determines if there is a cycle in a specified hierarchy and outputs to the script window the operators that are within the cycle, or are accessing the data within the cycle. Within each cycle traversed the script window outputs a name of a operator as 'Cycle Breaking Point' and outputs many operators names labeled as 'Cycle through' operators.
The 'Cycle Breaking Point' operator is the graph location where the evaluation check is terminated. This is dependent on where the evaluation was initiated from and may slightly vary. This is the critical location for scene evalution differences/odd results/odd behavior users see with problematic cycles in their graph. The reason, is that to avoid an infinite loop the data used to honour this evaluation request, is the evaluation upto that point in the connection stack. So in fact the result is not a re-evaluation of itself.
The 'Cycle through' operators are the contributers to the cycle and breaking one of these key dependencies will break the dependency cycle. Note: there are also other operators that will access the cycle and during a scene evaluation may end up with skewed cyclical results, but are not key contributers and as such removing one of these operators will not break the cycle.
To fix a cycle users should look for, narrow down and remove key contributers within the cycle. There are suggested approches for this. First to narrow down a cycle within a hierarchy isolating the breaking point and rerunning the cycle checking on it's data owner or other hierarchy's within it's cycled operators to get a handle on the depth and width of the cycle. Second, look for key contributers labeled within the cycle. To do this start with the 'Cycle Breaking Point' and trace down the output through the 'Cycle through' operators until the same 'Cycle Breaking Point' operator is found and labled as a 'Cycle through' operator. These are your contributers. Then look through the contributers for familiar cycle creators such as "Expression", "ScriptedOp" or "kine.Constraints". A key contributor for a problamatic cycle will not be of the form "kine.local.PoseCompensatorOp"or "kine.global.ParentPoseCns_E" or "kine.local.ParentPoseAndPoseCns_D" or "kine.global.SkeletonCtrlOpProp". Note: the operators labeled "*_D"'s and "*_E"'s are definers and enforcers of the "kine.Constraints".
You can customize cycle checking in several ways:
Tip 1: If you want to check only the current frame for cycles, set the Check Current Frame parameter to true. This is especially useful when one of the constraints participating in the cycle the activeness of a cycle is animated.
Tip 2: If you are running this command from scripting, running the Refresh command prior to running the CycleChecking command will ensure the values are current for the timeframe.
Tip 3: You can also maximize performance by enabling the 'Disable cycle checking when applying animation operators' User Preference and then specifying true for the FollowCycleCheckUserPref parameter. Note that if you leave the default value (false), this command will proceed with cycle checking regardless of what your user preference says.
Tip 4: By default the cycle checker checks the entire nested hierarchy, beginning with the scene element specified by the StartingGraphPt parameter. To check only the StartingGraphPt element, set the CheckFullNestedHier flag to false.
Note: This command uses output arguments. C# and some scripting languages (such as JScript, PerlScript and Python) don't support arguments passed by reference. Normally you can get the output arguments via either XSIApplication.ExecuteCommand method (C#) or the ISIVTCollection (scripting languages), but this command already returns a value.
The only available workaround in this case is to create a VBScript custom command which returns both the output arguments and the return value in one array. For details, see What Happens when the Function Already Returns a Value?.

### Scripting Syntax

    oBoolean = CycleChecking( [StartingGraphPt], [Check Current Frame], IsCycle, [DisableCycleCheck], [CheckFullNestedHier], [OutputObjs] );

### Return Value

Returns the result of the cycle check as a Boolean (true if there is a cycle).

### Parameters

Parameter | Type | Description
--- | --- | ---
StartingGraphPt | String | Object where the cycle checking will begin (the starting point). Default Value: Current selection
Check Current Frame | Boolean | True to check only the current frame for cycles. Default Value: false
IsCycle | Boolean | True if there is a cycle.
DisableCycleCheck | Boolean | Check the User Prefs to see if cycle checking is enabled. Default Value: false
CheckFullNestedHier | Boolean | Checks the entire nested hierarchy when enabled. Checks the specified object only when disabled. Default Value: true
OutputObjs | XSICollection of Operator objects | The Ops in the cycle(s).

### Examples

#### 1. VBScript Example

    ' Example: A cyclical expression
    NewScene
    CreatePrim "Sphere", "MeshSurface"
    Translate , -7.20756310877914, 2.07707676083662, -0.207707676083662, siRelative, siView, siObj, siXYZ
    GetPrim "Null"
    Translate , 3.82040230356053, 0.744612423696161, -7.44612423696161E-02, siRelative, siView, siObj, siXYZ
    SelectObj "sphere", , True
    InspectObj "sphere.kine.local"
    AddExpr "sphere.kine.local.posy"
    SelectObj "null", , True
    SetExpr "sphere.kine.local.posy", "null.kine.posy"
    Translate , 0.118156772275078, 0.235140765377718, -2.35140765377718E-02, siRelative, siView, siObj, siXYZ
    AddExpr "null.kine.local.posy"
    SetExpr "null.kine.local.posy", "sphere.kine.posy"
    Translate , 0.669555043461009, 1.01894331750266, -0.101894331750266, siRelative, siView, siObj, siXYZ
    Translate , -0.712516724951656, 1.96939066659309, -0.196939066659309, siRelative, siView, siObj, siXYZ
    Dim bCycle
    bCycle = CycleChecking( "Scene_Root" )
    Logmessage  bCycle
    ' The output is:
    'WARNING : "3000 - Cycle Breaking Point sphere.kine.local.pos.posy.Expression"
    'WARNING : "3000 - Cycle through sphere.kine.global.ParentPoseCns_E"
    'WARNING : "3000 - Cycle through sphere.kine.local.PoseCompensatorOp"
    'WARNING : "3000 - Cycle through null.kine.local.pos.posy.Expression"
    'WARNING : "3000 - Cycle through null.kine.global.ParentPoseCns_E"
    'WARNING : "3000 - Cycle through null.kine.local.PoseCompensatorOp"
    'WARNING : "3000 - Cycle through sphere.kine.local.pos.posy.Expression"
    'WARNING : "3000 - PROBLAMATIC EVALUATION CYCLES ARE IN THE SPECIFIED GRAPH"
    'CycleChecking "Scene_Root"
    'INFO : "True"

#### 2. VBScript Example

    ' Example: A cyclical constraint
    NewScene
    CreatePrim "Cube", "MeshSurface"
    Translate , -7.75896137939607, -0.235140765377774, 2.35140765377774E-02, siRelative, siView, siObj, siXYZ
    CreatePrim "Sphere", "MeshSurface"
    Translate , 8.12409703994715, -0.284640094775458, 2.84640094775458E-02, siRelative, siView, siObj, siXYZ
    ApplyCns "Pose", "sphere", "cube"
    SelectObj "cube", , True
    ApplyCns "Position", "cube", "sphere"
    SelectObj "Scene_Root"
    Dim bCycle
    bCycle = CycleChecking( "Scene_Root" )
    Logmessage  bCycle
    ' The output is:
    'WARNING : "3000 - Cycle Breaking Point cube.kine.global.IndpCns_E"
    'WARNING : "3000 - Cycle through sphere.kine.Constraints.posecns.blends.PosePoseCns_D"
    'WARNING : "3000 - Cycle through sphere.kine.global.PoseCns_E"
    'WARNING : "3000 - Cycle through cube.kine.Constraints.poscns.blends.PosePoseCns_D"
    'WARNING : "3000 - Cycle through cube.kine.global.IndpCns_E"
    'WARNING : "3000 - Cycle through cube.kine.local.PoseCompensatorOp"
    'WARNING : "3000 - Cycle through sphere.kine.local.PoseCompensatorOp"
    'WARNING : "3000 - PROBLAMATIC EVALUATION CYCLES ARE IN THE SPECIFIED GRAPH"
    'CycleChecking "Scene_Root"
    'INFO : "True"