Custom obj error

hi guys .i have create custom object from the sample https://discourse.mcneel.com/uploads/short-url/2ACJgXlVO1cPAlcpMmbLGSCB2B1.zip ,
when i save and colse current file ,then open the file again.I find a problem that the custom object is
no longer a RhinoEntityCurve object.Is there an example of a relatively stable custom object Or how should I modify that code.

You need to do some more coding to achieve what you want. This is because the 3dm file format does not know about your plug-in, and the file could be opened by others who do not have your plug-in.
It can be achieved by writing extra plug-in information into the 3dm file using the plug-in’s methods:

  • ShouldWriteDocument - this should return true if the document contains any custom geometry
  • WriteDocument - this must write the custom object GUID and custom object features into the document
  • ReadDocument - this will be called if a document is opened that has plug-in data in it, this should then read the custom object GUID and the custom object features, and replace the normal object having the GUID with a custom object you create from the data read from the document.

I hope this is clear enough to get you started. If you need more information, let us know.

One tip: write some version information together with the custom object features, such that when you ever need to change something to the data that is written to file, you can be backwards compatible with files written before the change.

Do you have any intuitive and simple examples? :heart_eyes:

I have tested this briefly, YMMV

    protected override bool ShouldCallWriteDocument(FileWriteOptions options)
    {
      return options.RhinoDoc.Objects.Any(obj => obj is RhinoEntityCurve);
    }

    int _major = 0, _minor = 0;
    protected override void WriteDocument(RhinoDoc doc, BinaryArchiveWriter archive, FileWriteOptions options)
    {
      archive.Write3dmChunkVersion(_major, _minor);
      int nObjects = doc.Objects.Count(obj => obj is RhinoEntityCurve);
      archive.WriteInt(nObjects);
      foreach(var obj in doc.Objects.Where(obj => obj is RhinoEntityCurve))
      {
        RhinoEntityCurve curve = obj as RhinoEntityCurve;
        archive.WriteGuid(curve.Id);
        archive.WriteInt((int)curve.Entity.Color);
        archive.WriteDouble(curve.Entity.Inflation);
      }
    }

    protected override void ReadDocument(RhinoDoc doc, BinaryArchiveReader archive, FileReadOptions options)
    {      
      archive.Read3dmChunkVersion(out int major, out int minor);
      if (major == 0 && minor == 0)
      {
        ReadDocument00(doc, archive, options);
      }
    }

    protected void ReadDocument00(RhinoDoc doc, BinaryArchiveReader archive, FileReadOptions options)
    {
      int nObjects = archive.ReadInt();
      for(int i =0; i < nObjects; ++i)
      {
        Guid id = archive.ReadGuid();
        int color = archive.ReadInt();
        double inflation = archive.ReadDouble();

        RhinoObject obj = doc.Objects.Find(id);
        if (obj != null)
        {
          var entity = new EntityCurve();

          entity.Color = (Colors)color;
          entity.Inflation = inflation;
          entity.Value = obj.Geometry as Rhino.Geometry.Curve;

          var curve = entity.ToRhinoObject();
          ObjRef oRef = new ObjRef(doc, id);
          doc.Objects.Replace(oRef, curve);
        }
      }
    }

Could you let me know which sample you used to get started? Then I can add this bit to the example.

An example of a complete project that can be run and debugged :heart_eyes: So i can Clear understand

I’m not here to do your complete project. The code provided can be copy-pasted into your plug-in class and should give you what you want.

I have some questions.there have the functions in class EntityRhinoData
protected override bool Write(Rhino.FileIO.BinaryArchiveWriter archive)
{
return base.Write(archive);
}
protected override bool Read(Rhino.FileIO.BinaryArchiveReader archive)
{
return base.Read(archive);
}
why i can’t [quote=“Menno Deij - van Rijswijk, post:4, topic:179830, full:true, username:menno”]
I have tested this briefly, YMMV

    protected override bool ShouldCallWriteDocument(FileWriteOptions options)
    {
      return options.RhinoDoc.Objects.Any(obj => obj is RhinoEntityCurve);
    }

    int _major = 0, _minor = 0;
    protected override void WriteDocument(RhinoDoc doc, BinaryArchiveWriter archive, FileWriteOptions options)
    {
      archive.Write3dmChunkVersion(_major, _minor);
      int nObjects = doc.Objects.Count(obj => obj is RhinoEntityCurve);
      archive.WriteInt(nObjects);
      foreach(var obj in doc.Objects.Where(obj => obj is RhinoEntityCurve))
      {
        RhinoEntityCurve curve = obj as RhinoEntityCurve;
        archive.WriteGuid(curve.Id);
        archive.WriteInt((int)curve.Entity.Color);
        archive.WriteDouble(curve.Entity.Inflation);
      }
    }

    protected override void ReadDocument(RhinoDoc doc, BinaryArchiveReader archive, FileReadOptions options)
    {      
      archive.Read3dmChunkVersion(out int major, out int minor);
      if (major == 0 && minor == 0)
      {
        ReadDocument00(doc, archive, options);
      }
    }

    protected void ReadDocument00(RhinoDoc doc, BinaryArchiveReader archive, FileReadOptions options)
    {
      int nObjects = archive.ReadInt();
      for(int i =0; i < nObjects; ++i)
      {
        Guid id = archive.ReadGuid();
        int color = archive.ReadInt();
        double inflation = archive.ReadDouble();

        RhinoObject obj = doc.Objects.Find(id);
        if (obj != null)
        {
          var entity = new EntityCurve();

          entity.Color = (Colors)color;
          entity.Inflation = inflation;
          entity.Value = obj.Geometry as Rhino.Geometry.Curve;

          var curve = entity.ToRhinoObject();
          ObjRef oRef = new ObjRef(doc, id);
          doc.Objects.Replace(oRef, curve);
        }
      }
    }

[/quote]

I have some questions.There have fucntions in class EntityRhinoData like this:
protected override bool Write(Rhino.FileIO.BinaryArchiveWriter archive)
{
return base.Write(archive);
}
protected override bool Read(Rhino.FileIO.BinaryArchiveReader archive)
{
return base.Read(archive);
}
why i should save and read the proterty in function ReadDocument and WriteDocument

It looks like you’ve been trying a few different things:

  • SetUserString on the custom object attributres
  • Use EntityRhinoData custom user data

And I have added

  • reading/writing the data to plug-in data

Neither of the methods you tried will replace the object when the file is re-opened with your custom object class because of reasons I mentioned earlier (users without your plug-in will also need to be able to open the document).

I agree that it may not be necessary to write the entity features if you write them also to the attributes or the custom user data. But you need to choose one of the three methods to save the entity features AND you need to replace the object upon reading the file like I have done in the code I provided.

I am even more confused. What you said about saving and reading are two different types of custom objects?[quote=“Menno Deij - van Rijswijk, post:10, topic:179830, full:true, username:menno”]
It looks like you’ve been trying a few different things:

  • SetUserString on the custom object attributres
  • Use EntityRhinoData custom user data

And I have added

  • reading/writing the data to plug-in data

Neither of the methods you tried will replace the object when the file is re-opened with your custom object class because of reasons I mentioned earlier (users without your plug-in will also need to be able to open the document).

I agree that it may not be necessary to write the entity features if you write them also to the attributes or the custom user data. But you need to choose one of the three methods to save the entity features AND you need to replace the object upon reading the file like I have done in the code I provided.
[/quote]

I am even more confused.
Uploading: 1712908277926.png…
What you said about reading/writing are two different types of custom objects?
could you please provide a detailed explanation about

  • SetUserString on the custom object attributres

  • Use EntityRhinoData custom user data
    when i reading/writing in EntityRhinoData class is that mean need to replace the object in RhinoDoc_EndOpenDocument Instead of ReadDocument.Because I found that the object is empty