Change ModelState in assembly/subassembly

Change ModelState in assembly/subassembly

mateusz_baczewski
Advocate Advocate
283 Views
7 Replies
Message 1 of 8

Change ModelState in assembly/subassembly

mateusz_baczewski
Advocate
Advocate

Hi,

 

I’m developing an add-in for Vault that uses InventorServer to edit the model by adding a new model state with simplifications for welded components and assigning an ERP ID to surface bodies for parts (including simplified parts) or in the name for assemblies. My goal is simply to switch the model state in welded assemblies to one that contains the simplified model.

 

The problem is that sometimes the model is created successfully and everything works fine, but for some cases I get the following error when calling:

 

oOcc.ActiveModelState = $"{itemErpId.ToString()}";

 

ex = {"The remote procedure call failed. (0x800706BE)"}

 

I should add that I also checked whether the model state I’m interested in exists in the given model, and it did.

 

public string CreateSimplifyModel(AssemblyDocument assemblyDocument, string folder)
{
    try
    {
        var modelName = System.IO.Path.GetFileNameWithoutExtension(assemblyDocument.FullFileName);
        var simplifyPartPath = System.IO.Path.Combine("C:\\Vault\\Projekty\\URZĄDZENIA STAL POWIETRZE\\OGRZEWACZE POM. STAL KOZY\\BJORN", "Uproszczenia", modelName + ".ipt");

        PartDocument oPartDoc = (PartDocument)_mInv.Documents.Add(DocumentTypeEnum.kPartDocumentObject, "", false);
        PartComponentDefinition oPartDef = oPartDoc.ComponentDefinition;

        DerivedAssemblyDefinition oDerivedAssemblyDef =
            oPartDef.ReferenceComponents.DerivedAssemblyComponents.CreateDefinition(assemblyDocument.FullDocumentName);

   
        oDerivedAssemblyDef.DeriveStyle = DerivedComponentStyleEnum.kDeriveAsSingleBodyNoSeams;

        oPartDef.ReferenceComponents.DerivedAssemblyComponents.Add(oDerivedAssemblyDef);

        object itemErpId = GetErpID(System.IO.Path.GetFileName(assemblyDocument.FullFileName));

        oPartDef.SurfaceBodies[1].Name = $"{itemErpId}";
        oPartDoc.SaveAs(simplifyPartPath, false);
        oPartDoc.Close(true);

        return simplifyPartPath;

    }
    catch (Exception ex)
    {
        throw new Exception("Błąd podczas generowania uproszczonego modelu.", ex);
    }
}

public void TraverseAssembly(ComponentOccurrences occurrences, int level)
{
    ComponentOccurrence occ = null;
    string oOccName = null;
    string splittedoOccName = null;
    try
    {
        foreach (ComponentOccurrence oOcc in occurrences)
        {
           
            oOccName = oOcc.Name;
            splittedoOccName = oOccName.Split(':')[0];
            if (nameCountDict.ContainsKey(splittedoOccName))
            {
                nameCountDict[splittedoOccName]++;
            }
            else
            {
                nameCountDict.Add(splittedoOccName, 1);
            }

            if (oOcc.DefinitionDocumentType == DocumentTypeEnum.kPartDocumentObject)
            {

                string partName = System.IO.Path.GetFileName(oOcc.ReferencedDocumentDescriptor.FullDocumentName);

                object itemErpId = GetErpID(partName);

                oOcc.SurfaceBodies[1].Name = (string)itemErpId;
            }

            else if (oOcc.DefinitionDocumentType == DocumentTypeEnum.kAssemblyDocumentObject && !string.IsNullOrEmpty(oOcc.Name) && !oOcc.Name.Contains("Weldbead"))
            {
                AssemblyDocument assemblyDocumentOcc = oOcc.ReferencedFileDescriptor.ReferencedDocument as AssemblyDocument;

                string assemblyName = System.IO.Path.GetFileName(assemblyDocumentOcc.FullDocumentName);
                string folder = System.IO.Path.GetDirectoryName(assemblyDocumentOcc.FullDocumentName);
                var modelName = System.IO.Path.GetFileNameWithoutExtension(assemblyDocumentOcc.FullFileName);
                var simplyfyModelPath = System.IO.Path.Combine("C:\\Vault\\Projekty\\URZĄDZENIA STAL POWIETRZE\\OGRZEWACZE POM. STAL KOZY\\BJORN", "Uproszczenia", modelName + ".ipt");

                if (assemblyDocumentOcc.SubType == DocumentSubTypeIds.Weldment)
                {

                    if (System.IO.File.Exists(simplyfyModelPath))
                    {
                        continue;
                    }

                    simplyfyModelPath = CreateSimplifyModel(assemblyDocumentOcc, folder);
                    object itemErpId = GetErpID(assemblyName);

                    ComponentDefinition oOccCompDef = oOcc.Definition;
                    LevelOfDetailRepresentation levelOfDetail = null;

                    if (oOccCompDef.Type == ObjectTypeEnum.kWeldmentComponentDefinitionObject)
                    {
                        WeldmentComponentDefinition oOccWeldCompDef = (WeldmentComponentDefinition)oOccCompDef;
                        levelOfDetail = oOccWeldCompDef.RepresentationsManager.LevelOfDetailRepresentations.AddSubstitute(simplyfyModelPath, $"{itemErpId.ToString()}", false);
                    }
                    else
                    {
                        AssemblyComponentDefinition oOccAssemblyCompDef = (AssemblyComponentDefinition)oOccCompDef;
                        levelOfDetail = oOccAssemblyCompDef.RepresentationsManager.LevelOfDetailRepresentations.AddSubstitute(simplyfyModelPath, $"{itemErpId.ToString()}", false);
                    }


                    oOcc.ActiveModelState = $"{itemErpId.ToString()}";

                    Debug.WriteLine(oOcc.ActiveModelState);
                }
                else
                {
                    object itemErpId = GetErpID(System.IO.Path.GetFileName(oOcc.ReferencedFileDescriptor.FullFileName));
                    oOcc.Name = $"{itemErpId}:{nameCountDict[splittedoOccName]}";

                    if (oOcc.BOMStructure != Inventor.BOMStructureEnum.kPurchasedBOMStructure)
                    {
                        TraverseAssembly(oOcc.Definition.Occurrences, level + 1);
                    }
                }
            }
        }
    }
    catch(Exception ex)
    {
        throw new Exception("Wystapił błąd podczas przeszukiwania modelu.");
    }
}
If you found it helpful, a "Like" would be much appreciated!
If this post solved your problem, please mark it as "Solution.".

0 Likes
284 Views
7 Replies
Replies (7)
Message 2 of 8

WCrihfield
Mentor
Mentor

Hi @mateusz_baczewski.  I am not super fluent in C#.net, but I think I understand your code relatively well, due to its similarities to vb.net.  After a quick review, I saw that your code is working with 'LevelOfDetailRepresentations' (LODs) instead of 'ModelStates', but then attempting to set the ComponentOccurrence.ActiveModelState property's value using the name of the LOD.  I think you may need to choose one or the other (LOD's or ModelStates), but not both.  Which version is the InventerServer you are using.  The 'ModelStates' replaced the LOD's in the Inventor 2022 model year.  It seems like they kept some of the 'LOD' handling tools in place, but 'hid' them, to encourage new development to use the ModelStates instead of the older LOD's system.  Back in Inventor 2021 and older, there was the ComponentOccurrence.ActiveLevelOfDetailRepresentation property, instead of 'ActiveModelState' property.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 3 of 8

mateusz_baczewski
Advocate
Advocate

Hi, @WCrihfield 

 

Thanks! In the meantime, I switched the LoD to model state, but unfortunately, it didn’t help. I’m currently working with InventorServer 2026. The weirdest part is that this error is barely documented, and I haven’t been able to find any solution.

 

  else if (oOcc.DefinitionDocumentType == DocumentTypeEnum.kAssemblyDocumentObject && !string.IsNullOrEmpty(oOcc.Name) && !oOcc.Name.Contains("Weldbead"))
  {
      AssemblyDocument assemblyDocumentOcc = oOcc.ReferencedFileDescriptor.ReferencedDocument as AssemblyDocument;

      string assemblyName = System.IO.Path.GetFileName(assemblyDocumentOcc.FullDocumentName);
      string folder = System.IO.Path.GetDirectoryName(assemblyDocumentOcc.FullDocumentName);
      var modelName = System.IO.Path.GetFileNameWithoutExtension(assemblyDocumentOcc.FullFileName);
      var simplyfyModelPath = System.IO.Path.Combine("C:\\Vault\\Projekty\\URZĄDZENIA STAL POWIETRZE\\OGRZEWACZE POM. STAL KOZY\\BJORN", "Uproszczenia", modelName + ".ipt");

      if (assemblyDocumentOcc.SubType == DocumentSubTypeIds.Weldment)
      {

          if (System.IO.File.Exists(simplyfyModelPath))
          {
              continue;
          }

          simplyfyModelPath = CreateSimplifyModel(assemblyDocumentOcc, folder);
          itemErpId = GetErpID(assemblyName);

          ComponentDefinition oOccCompDef = oOcc.Definition;
          ModelState modelState = null;

          if (oOccCompDef.Type == ObjectTypeEnum.kWeldmentComponentDefinitionObject)
          {
              WeldmentComponentDefinition oOccWeldCompDef = (WeldmentComponentDefinition)oOccCompDef;
              modelState = oOccWeldCompDef.ModelStates.AddSubstitute(simplyfyModelPath, $"{itemErpId.ToString()}", true);
          }
          else
          {
              AssemblyComponentDefinition oOccAssemblyCompDef = (AssemblyComponentDefinition)oOccCompDef;
              modelState = oOccAssemblyCompDef.ModelStates.AddSubstitute(simplyfyModelPath, $"{itemErpId.ToString()}", true);
          }

          oOcc.ActiveModelState = modelState.Name; // exception apear
          modelState.Activate(); 

          Debug.WriteLine(oOcc.ActiveModelState);
      }
      else
      {
          itemErpId = GetErpID(System.IO.Path.GetFileName(oOcc.ReferencedFileDescriptor.FullFileName));
          oOcc.Name = $"{itemErpId}:{nameCountDict[splittedoOccName]}";

          if (oOcc.BOMStructure != Inventor.BOMStructureEnum.kPurchasedBOMStructure)
          {
              TraverseAssembly(oOcc.Definition.Occurrences, level + 1);
          }
      }
  }
If you found it helpful, a "Like" would be much appreciated!
If this post solved your problem, please mark it as "Solution.".

0 Likes
Message 4 of 8

WCrihfield
Mentor
Mentor

Were there any other details related to the error, such as the 'More Info' tab of the usual Inventor error dialogs?  I am honestly not experienced with using InventorServer or Apprentice yet, because I have not had the permissions on my work PC to venture into Inventor add-ins or standalone EXE's yet.  I only recently got Vault also, so not too familiar yet with how its involvement will effect all of my other pre-existing Inventor automation tools yet, other than hardcoded file/folder paths needing to be changed.  And I don't really do much 'simplified' substitute ModelState creations by code either.  So, I may not be the best person to help you figure out the remaining issues.

But the most prevalent problem I (and others on this forum) encounter when custom or multiple ModelStates get involved, is that suddenly stuff stops working, due to encountering ModelState 'members' in the process, which tend to act like 'ReadOnly'.  This is especially the case when working with assemblies by code.  Any time either the main (active or highest level) assembly itself has multiple ModelStates, or any of the components within the assembly reference a model file in which multiple ModelStates exist, the problem shows up.  It is especially problematic when there are multiple 'instances or occurrences' of the same component in the assembly, where some of the occurrence represent different ModelState versions of the source file.  The first occurrence you encounter may act relatively normal, but then the next 'instance' of the same source model will act like it is ReadOnly.  Sometimes you have to update the component's source document before it will allow you to make new changes to it, because multiple versions (ModelStates) of it are currently being held in Inventor's session memory at the same time, which all point back to the same file on disk.  So, sometimes you need to make sure you are working with the 'factory' version of documents with multiple ModelStates, because the factory version is the only version we can make direct edits to.  The factory version is just the version associated with the file's 'active' ModelState, so it can be changed.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 5 of 8

mateusz_baczewski
Advocate
Advocate

Hi @WCrihfield 

 

Thank you for the comprehensive answer. I will check the states and whether the model state is perhaps read-only or if something is blocking the assembly, etc. I just noticed some strange behavior: I checked the InventorServer state after the error I mentioned earlier occurred, and it seems that after attempting to change the model state, InventorServer stops working, as if something triggers an error that causes InventorServer to crash. It’s somewhat similar to when, for unknown reasons, the Inventor application sometimes stops working. Any attempt to execute a method on InventorServer returns an error: The RPC server is unavailable. I will keep digging into this issue and hopefully find more information about the error.

If you found it helpful, a "Like" would be much appreciated!
If this post solved your problem, please mark it as "Solution.".

0 Likes
Message 6 of 8

mateusz_baczewski
Advocate
Advocate

HI @WCrihfield,

 

Model states in Inventor are really a strange thing. I managed to solve my previous problem — it was enough to set:

 

 oOcc.IsAssociativeToDesignViewRepresentation = false;

 

But now a new issue has appeared: I cannot change the model state in a model whose parent is another assembly that also has model states. Every time I try, I get an undefined error. I tried doing it using the factory document, but unfortunately then the changes are not saved in the GLB model I later generate. The weldment assembly does not appear as a simplified part. I noticed that this only happens in models where the parent has more than one model state. :<

If you found it helpful, a "Like" would be much appreciated!
If this post solved your problem, please mark it as "Solution.".

0 Likes
Message 7 of 8

WCrihfield
Mentor
Mentor

That's interesting.  I know that the ModelStates do not record or control 'visibility or appearance' related settings, because those are managed by the DesignViewRepresentations (DVRs).  I am not 100% sure if that specific property of the assembly components is managed by the active DVR of their parent assembly, or the active ModelState of their parent assembly though.  It would make more sense if that property's value was controlled by whichever DesignViewRepresentation (DVR) happened to be 'active' in the component's owning assembly.

 

The issue you mentioned about not being able to make a change to a component where that component's parent assembly had multiple ModelStates, makes me think that you may need to either:  1) get the factory version of that parent assembly first ; or 2) find out which ModelState that parent assembly is associated with (Document.ModelStateName), then activate that ModelState in it first ; then make the change(s) to its child component's property.  This is because, whichever ModelState happens to be 'active' in that parent assembly, will be recording / managing which ModelState each of its immediate child components are set to (the value of their (ComponentOccurrence.ActiveModelState property).  And we can only make changes to the factory version of that parent assembly.

 

Sometimes, when we want to make changes to a component's referenced document, and we want those changes to only effect the specific ModelState which that component is set to, getting the factory version of that referenced document's source file may be getting a different document (different version of the file), so that may not work the way we need it to work.  In cases like that, what may be needed is to force that component's referenced document (which will be associated with the ModelState it is set to) to 'become' the factory version.  We can do this by checking which ModelState that component is set to, then activating the ModelState by that name within its source file, then getting the Document associated with that active ModelState, which will no longer be a 'member', but the factory'.  Then make the changes to that document while that ModelState it is active.  Early on, while using Inventor 2022 (first version with ModelStates), it seemed like activating the ModelState of a non-visible referenced document would cause an error, but I think they may have fixed that issue since then.  Another way certain types of changes could be made to ModelState member documents was to get the factory version of the file, whichever one that may be, then make the change within its ModelStateTable or through its Excel Worksheet (ModelStates.ExcelWorkSheet), if just changing the value of a pre-existing Parameter, iProperty, or pre-recorded suppression status.  In that table, each 'Row' represents a different ModelState, and each 'Column' represents a different detail of the model file, such as a Parameter, Property, suppression status, or similar types of things that ModelStates can manage.  Most of the table's structural layout (rows, columns, column headings, and such) is ReadOnly, but the 'Value' of an individual 'Cell' (within the customizable area) is Read/Write.  I think that if going the Excel route, we can actually add more rows &/or columns, for creating new ModelStates or adding additional details for them to manage, but that can also be the most complex way to do things.  But as usual, with more options or abilities available to us, there is usually also more complexity and responsibility involved.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 8 of 8

mateusz_baczewski
Advocate
Advocate

Hi @WCrihfield 

 

I’ve read a bit about model states, and in all operations on models where more than one model state exists, the operations are performed on the FactoryDocument. However, in the end, it still doesn’t get reflected in my target model, even though I checked right before generating the GLB model. At that point, the FactoryDocument is modified according to my scheme, but these changes are not visible in the model that I process.

 

I’m presenting the results from the debugger:
Occurrence name – Name of the active model state – Number of model states

 

mateusz_baczewski_0-1756212831226.png

 

If you found it helpful, a "Like" would be much appreciated!
If this post solved your problem, please mark it as "Solution.".

0 Likes