I have been migrating from Inventor 2021 to 2023. Therefore I have been playing around with model states for the last few weeks. I found 3 features (??) that can lead to unexpected results that I wanted to share.
In this post, I will write about model states but from the perspective of the API, these are documents within the file. There are 2 types of documents in the file. The Factory and the member document. For a full explanation, you should have a look at this post "Porting guide from Level of Details to Model states." For this post its good to know the following:
"Essentially, the Factory document is the document for the user to create model states or design modelling recipes. You can think of it as (in general) all edits users do need to be in the Factory document environment."
"Member document represents one result document from one of the model states. ... It is for consumption purpose. This document usually cannot be modified. Member document update is always driven by Factory Document. Please note, these documents are only elaborated on demand. If we do not consume, there might be no member document there."
(The problems that I'm about to describe are not limited to iLogic but are also a concern if you create addins/tools for Inventor. In the post "Wich model states do you update." I have a more generalized solution to these problems.)
ThisDoc.Document can break iLogic rules
The property “ThisDoc.Document” is one of the most used lines of code in any iLogic rule. But this property returns the “Model state member” document!
Often I see people using "ThisApplication.ActiveDocument" to get the active document. This also will get you the “Model state member” document. (There is also another drawback to using "ThisApplication.ActiveDocument". See this post "Run Before Save Rule Only Once in Assemblies") And is therefore also affected by the following problem. According to this blog post (by an Autodesk employee), it’s not recommended to edit the “Model state member” document directly. Even worse in some cases the “Model state member” document may not exist and return Nothing/null. Which will break your code!
So even if your code does not break directly (and to be honest, I haven't had this problem myself yet) it might in the future. Therefore I would say that you need to start using the new property "ThisDoc.FactoryDocument". This will give you the factory document.
ThisDoc.FactoryDocument ' instead of ThisDoc.Document 'or ThisApplication.Document
Level of Details behaviour change
If you are using “Level of details” (lod) then they will get converted to a model state. They work more or less the same but not exactly. Lod and model states allow you to suppress occurrences in an assembly. But the key difference shows when you change a parameter, iProperty, material or even an iPart row. With lod these would change across all lod. But now with model states, only the active model state will change. Therefore you will get different models! (hence the name) This is the default behaviour but you can change this if you set the member edit scope to all members.
As an example of a situation that can get you unexpected (wrong) results:
In our models, we have a couple of reasons for using lod. In some assemblies, we have a lod for the customer. In this lod, we suppressed all parts that you don't want to send to customers. (If you export an assembly as a step file the suppressed parts don't get exported.) In these assemblies, we change parameters and iPart rows with iLogic. The default behaviour is such that the exported customer model is different than our design, after running an iLogic rule! As you can imagen this could become a huge issue if you don’t supply the customer with the correct information. And because we automated the process of creating step files for the customers this is a big concern for me. The engineers might not notice that they are sending the wrong models/data.
The solution to this problem might be to set the member edit scope to all members at the beginning of your rule. This will ensure that you get the same behaviour as with the lod. The following lines of code should do the trick:
Dim doc As AssemblyDocument = ThisDoc.FactoryDocument doc.ComponentDefinition.ModelStates.MemberEditScope = MemberEditScopeEnum.kEditAllMembers
Because we have a lot of iLogic rules that might be affected I also discussed this on the "Inventor iLogic and VB.net Forum". We came to the conclusion that I need to check/update all rules manually. But WCrihfield pointed me to an undocumented helper class. The class also sets the member edit scope to all members but it changes it back when you are finished. You might want to have a look at it if you don't like it when your iLogic rule changes the edit scope in your model. But still, need all changes in your iLogic rule to affect all member states. It works like this:
Dim doc As Document = ThisDoc.FactoryDocument Using MSGS As New ModelStatesGlobalScope(doc) ' Your code goes here... End Using
(Pay attention, that this is an undocumented class, therefore, you have to do more of your own research.)
In some situations, not all Model states get updated
Consider the following situation: You have multiple different model states. You want to update a parameter in all model states so that the parameter becomes the same as in the active model state. You set the scope to “edit all members” and set the parameter. Your iLogic code looks something like this:
Dim correctValue = Parameter("MyParameter") ThisDoc.FactoryDocument.ComponentDefinition.ModelStates.MemberEditScope = MemberEditScopeEnum.kEditAllMembers Parameter("MyParameter") = correctValue
I would have expected that the parameter “MyParameter” in all model states now to have the same value. But that is not what will happen! Because the active model state does not change all other model states will also not change. In this example, I knew that I was not changing the parameter in the active model state. But this could happen as easily in a situation where you don’t know that you are not changing the active model state. I think this is a bug in the API and I have reported it to Autodesk.
I have no general solution for this and this might not be a big issue but you should be aware of this feature/bug.