How to run iLogic rules from assembly with Model States in parts ?

How to run iLogic rules from assembly with Model States in parts ?

TONELLAL
Collaborator Collaborator
1,779 Views
10 Replies
Message 1 of 11

How to run iLogic rules from assembly with Model States in parts ?

TONELLAL
Collaborator
Collaborator

Hello,

I have an iLogic rule in an ipt file, which works fine from the ipt. But, if I insert this ipt in an iam, then Run all rules from the assembly, it no longer works if the ipt contains Model States.

How can I fix this ?

 

 

Dim oMyParameters As UserParameters
Dim oParameter As UserParameter

oDoc = ThisDoc.FactoryDocument
oParameters =  oDoc.ComponentDefinition.Parameters
oMyParameters = oParameters.UserParameters

'Delete parameter MyParam if it exist
Try
	oMyParameters("MyParam").Delete
Catch
End Try

'Create parameter MyParam
MsgBox("Create MyParam")
oParameter = oMyParameters.AddByExpression("MyParam", "10", kDefaultDisplayLengthUnits)

'Format MyParam
oParameters("MyParam").ExposedAsProperty = True
With oParameters("MyParam").CustomPropertyFormat
                .ShowLeadingZeros = True
                .ShowTrailingZeros = False
                .ShowUnitsString = True
                .Units = "m"
                .Precision = Inventor.CustomPropertyPrecisionEnum.kThreeDecimalPlacesPrecision
End With
		
'Affect MyParam (formatted) to custom property MyProperty, then delete it
MsgBox("Affect MyParam to MyProperty")
iProperties.Value("Custom", "MyProperty") = iProperties.Value("Custom", "MyParam")	

MsgBox("Delete MyParam")
oMyParameters("MyParam").delete

 

 

Alain

0 Likes
1,780 Views
10 Replies
Replies (10)
Message 2 of 11

nedeljko.sovljanski
Advocate
Advocate

Hi,

I have no problem with your code. It creates custom prop. MyProperty with value 0,01 m. This works in both model states I have created. If you want to share your assembly and parts for testing, I am using I2022.2

0 Likes
Message 3 of 11

TONELLAL
Collaborator
Collaborator

I send you the files.

If I run the rule from the ipt it's ok. When I run the run from the assembly ("Regenerate all rules"), I have an error message : 

Error on line 30 in rule: Règle0, in the document: Pièce1.ipt

iProperties: property named "MyParam" not found.

 

I use Inv 2022.2 FR

0 Likes
Message 4 of 11

WCrihfield
Mentor
Mentor

If you want to run that rule within the part, while the assembly is active, you will need to change your line near the end that sets the one iProperty's value from the other iProperty using the iLogic snippet 'iProperties.Value(), because right now it is targeting the assembly, instead of the part.  You need to either include the document specific reference, or change them to use the API route Document.PropertySets.PropertySet.Property.Value.  Because that iLogic snippet will always target the 'active' document (unless specified otherwise), which in this case remains the main assembly.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 5 of 11

TONELLAL
Collaborator
Collaborator

This rule works fine in 2018, and always works in 2022 is there are no model states in the part. I'll try your code, but the problem seems to be  around model states.

0 Likes
Message 6 of 11

WCrihfield
Mentor
Mentor

There's one other potential issue that I believe I have observed concerning a situation like this, but I don't know if this would have any bearing on your specific problem here.  When I was helping someone else sometime last year with a problem he was having involving attempts to run local rules within components, from a main assembly, I found out about a situation that seemed like a bug in the system, related to the ModelStates.  When the ModelState of the component was set to one ModelState, but the model document that the component represents is set to a different model state, then the local rule within that model document could not be found, which was causing his assembly level rule to throw errors at the point of running that rule.  We did not know what was causing this at first, and the problem seemed to be somewhat random.  We checked the code within the local rule until we couldn't think of anything else within it that could possibly be causing any problems.  Then I did some experimentation of my own with some local files and local rules.  I believe that what I found was similar to what I eluded to above, if the model states were not 'aligned' (set the same), then the local rule could not be found, so the assembly level rule that was trying to run the local rule in the part was encountering an error.  But when the component and the model document it represented were both set to the same model state, there was no problem, and everything worked as expected.  I don't know if they have fixed that situation yet though, because that was several months ago.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 7 of 11

TONELLAL
Collaborator
Collaborator

Yes, I noticed several situations like yours with modelstates. It seems an ipt with MS is managed in fact like an iPart with several versions. I explain : when you insert an iPart, you insert the iFactory. You select the version, then Inventor use the corresponding ipt generated by the factory. It seems to be the same thing for MS : there is the "Factory document", which is the corresponding iFactory,  and the "document", which is the Model State.

When you work directly in an ipt, the FactoryDocument and the Document are the same, so there is no problem. But from an assembly, you need to make a difference between the Factory, which is the original file (and so contains irules, properties,... created in the ipt) and the Document, which is the generated version. If a rule create a property or parameter from the assembly, where is it created ? In the Factory, or in the Document ? Not clear...

More specifically, if we use the API syntax, we can choose to work on Thisdoc.FactoryDocument or on Thisdoc.Document. But with iLogic syntax like "iProperties.Value("Custom", "MyProp")", we don't know if Inventor work on Document or on FactoryDocument.

 

0 Likes
Message 8 of 11

JelteDeJong
Mentor
Mentor

I couldn't figure out which (Original, factory or member) document is used by "iProperties.Value("Custom", "MyProp")" . But when I created my own implementation of that function it worked fine. That looks like this:

Public Sub Main()
	oDoc = ThisDoc.FactoryDocument
	
	Dim oParameters =  oDoc.ComponentDefinition.Parameters
	Dim oMyParameters = oParameters.UserParameters

	'Delete parameter MyParam if it exist
	Try
		oMyParameters("MyParam").Delete
	Catch
	End Try

	'Create parameter MyParam
	MsgBox("Create MyParam")
	oParameter = oMyParameters.AddByExpression("MyParam", "10", kDefaultDisplayLengthUnits)

	'Format MyParam
	oParameters("MyParam").ExposedAsProperty = True
	With oParameters("MyParam").CustomPropertyFormat
	                .ShowLeadingZeros = True
	                .ShowTrailingZeros = False
	                .ShowUnitsString = True
	                .Units = "m"
	                .Precision = Inventor.CustomPropertyPrecisionEnum.kThreeDecimalPlacesPrecision
	End With
			
	'Affect MyParam (formatted) to custom property MyProperty, then delete it
	MsgBox("Affect MyParam to MyProperty")
	GetProperty(oDoc, "MyProperty").Expression = GetProperty(oDoc, "MyParam").Expression
	' iProperties.Value("Custom", "MyProperty") = iProperties.Value("Custom", "MyParam")	

	MsgBox("Delete MyParam")
	oMyParameters("MyParam").delete
End Sub

Public Function GetProperty(doc As PartDocument, name As String) As [Property]
	Dim propSet As PropertySet = doc.PropertySets.Item("Inventor User Defined Properties")
	Try
		Return propSet.Item(name)
	Catch
		Throw New Exception(String.Format("Custom property '{0}' could not be found in document: {1}",
			name, doc.FullFileName))
	End Try
	Return Nothing
End Function

Jelte de Jong
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

EESignature


Blog: hjalte.nl - github.com

0 Likes
Message 9 of 11

TONELLAL
Collaborator
Collaborator

@WCrihfield 

I've tested your code, it works fine, I think because you use API syntax instead of iLogic. I understand the difference about "thisdoc" when you run the rule locally from the ipt or from an assembly. But, in 2018, there was no problem : when regenerating all rules from the assembly, each rule was ran as if it was ran from the ipt itself...

 

@JelteDeJong 

Ok with your code, but same thing, you use "doc.PropertySets.Item("Inventor User Defined Properties").item("MyProp")" instead of iProperties("MyProp"), which was working in 2018

 

I found another problem with rules from assembly or ipt :

I have a rule which need to suppress all chamfers, perform a calculation using faces, then unsupress all chamfers.

Here is the simplified code.

 

'Swtich from FactoryDocument to Document to test from assembly
oDoc = ThisDoc.FactoryDocument
'oDoc = ThisDoc.document

'Check wich MS is detected
MsgBox(oDoc.ModelStateName)

oFaces
= oDoc.ComponentDefinition.SurfaceBodies.Item(1).Faces MsgBox("Faces number = " & oFaces.count) 'Suppress all chamfers oChanfrein= oDoc.ComponentDefinition.Features.ChamferFeatures For j = 1 To oChanfrein.Count oChanfrein.Item(j).Suppressed=True Next oFaces = oDoc.ComponentDefinition.SurfaceBodies.Item(1).Faces MsgBox("Faces number = " & oFaces.count) 'Missing calculation code '... '... 'Unsuppress all chamfers oChanfrein= oDoc.ComponentDefinition.Features.ChamferFeatures For j = 1 To oChanfrein.Count oChanfrein.Item(j).Suppressed=False Next

 This code work in an ipt with model states. But if you insert it in an assembly, it not work any more...

The ipt is joined, just insert it in a blank assembly then it like this :

-open the ipt and run the rule. You can switch, in the rule, between thisdoc.document and thisdoc.factorydocument. In both cases, it's ok

-insert it in an assembly, then run the rule using "thisdoc.document" : the correct MS is detected, but there is an error on line 16 "oChanfrein.Item(j).Suppressed=True

-if you modify the rule to use thisdoc.factorydocument, there is no longer an error, but the rule is ran on the Factory document, not on the inserted MS.

 

So... How can I change the rule to make it working when I regenerate rules from an assembly ?

0 Likes
Message 10 of 11

WCrihfield
Mentor
Mentor

That is definitely an interesting situation. Since I almost never use the 'Regenerate All Rules' tool, I had not observed that unique behavior before, where it causes all rules within all component documents of an assembly to also run.  I can see now that it will not run the rule when using that tool from the assembly and while the rule is using the factory document setting.  I knew however that using the 'ThisDoc' iLogic term would always be working with the part instead of the assembly though, because it defaults to the 'local' document first, then in situations where there is no local document (like when used in an external rule), it then refers to whichever document was 'active' when the rule first started (not necessarily the 'active' document at that point in the code).  But I had not experimented enough yet with using that ThisDoc.FactoryDocument iLogic snippet, so I had not encountered an issue like this before.

 

When the part is the active document, and the first non-master model state is active, and the rule is using the ThisDoc.Document term, then I run the rule, the rule recognizes there are fewer faces, which makes sense because there are fewer features active in that model state, resulting in fewer faces, as expected.  However, there is another little detail that has me a little confused...

 

When running the rule from the active part, no matter how I get the document object (ThisDoc.Document, ThisDoc.FactoryDocument, or ThisApplication.ActiveDocument), and no matter if I identified it as PartDocument or Document, and no matter if the part currently has the Master model state active, or one of the other model states active, the PartComponentDefinition.IsModelStateMember property always returns False, and the IsModelStateFactory property always returns True.  After reading the documentation/description of those two properties, and seeing that all 3 of the above mentioned ways of getting the document result in the same property values, I am confused about either their meaning, or the usefulness of those two iLogic snippets.  If those properties are correct, then both of those two iLogic snippets return the factory document, no matter which model state the document is currently set to.  I was thinking that any time the model document (identified at the start/top of a rule through normal means) currently had a non-master model state active, it would not be the factory document.  Maybe that property is only useful/effective on a document object that is obtained by accessing the document being referenced by an assembly component.  Since I know custom model states do not have real standalone slave model files that exist in the file system, like the iPart/iAssembly system had, it is so odd and confusing that there can be both factory and non factory documents when dealing with model states.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 11 of 11

TONELLAL
Collaborator
Collaborator

Yes, ThisDoc is the "local" document, so when you use it from an assembly, it could be the assembly instead of the ipt. Same thing in VB, where there is ActiveDocument and ActiveEditDocument, to differentiate the assembly or the part being edited from the assembly. What is interesting with "Regenerate all rules" is that I don't have to open each part to run the internal rule, I can, from the assembly, run all the rules inside each part. I use it a lot with templates : I have several types of templates, depending of the part I need to create ( plate, pipe, skeleton,...). Each one has its own rule, and they are ran in one go from the assembly.

 

When you work in a part file, FactoryDocument and Document are the same. But, when you run the same rule from the assembly, FactoryDocument refers to the ipt itself, while Document refers to the generated model state. You can see it with the rule :

oDoc = thisdoc.document (or FactoryDocument)

msgbox(odoc.modelstatename)

 

In the part, activate MS1. In the assembly : activate MS2

1st case  : using Document. From the part : rule = MS1, from the assembly: rule = MS2. The MS are differentiated.

2nd case : using FactoryDocument. From the part : rule = MS1, from the assembly: rule = MS1. The MS are no longer differentiated, because FactoryDocument refers to the factory and not the member.

 

And now, the problem is : do we need to work on the Factory, or on the Member ? If Document and FactoryDocument are the same when in an ipt, we should always use Document, in order to access to the Member from an assembly. Unfortunately, it seems some actions are possible only on the factory (for example, suppress functions). Or perhaps, there is a way to select the Edit Scope, to choose to modify the Factory or the Member ? As you said, it seems Factory and Member are managed by Inventor as if they were different files, like for iParts...

 

Edit : I found a workflow, but not sure it always functions nor create other problems :

-detect the ActiveModelState in the Member

-activate this MS in the Factory (from an ipt, this has no effect)

-in the factory, define the scope on ActiveMemberOnly

-do modifications on the Factory, which is now identic to the Member

-restore initial factory

 

Main modifications in the rule are :

oPart = ThisDoc.Document
oFact = ThisDoc.FactoryDocument

oMSs = oFact.ComponentDefinition.ModelStates
oMSs.MemberEditScope = kEditActiveMember
oFact.ComponentDefinition.ModelStates(oPart.ModelStateName).Activate

oChanfrein= oFact.ComponentDefinition.Features.ChamferFeatures
For j = 1 To oChanfrein.Count
oChanfrein.Item(j).Suppressed=True
Next

Now the questions are :

-is it dangerous to edit the Factory : I don't think, if I can restore it. But the file will be dirtied.

-how to restore the original Factory : perhaps by creating a temporary MS at the beginning, to store the original  ? 😁

 

0 Likes