Site Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

developer:rhinocommonsamples:userdata [2015/09/14] (current)
Line 1: Line 1:
 +====== Info: RhinoCommon object plug-in user data ======
 +
 +=====Overview=====
 +There are two basic ways plug-ins can store information in Rhino .3dm files, **document user data** and **object user data**.
 +
 +For example, a rendering plug-in might save a scene descriptions as **document user data** and use **object user data** to attach rendering material information to individual surfaces.
 +
 +=====Document User Data=====
 +To save document user data your plug-in must override three PlugIn base class functions:
 +
 +<code c#>
 +PlugIn::​ShouldWriteDocument
 +PlugIn::​WriteDocument
 +PlugIn::​ReadDocument
 +</​code>​
 +
 +SDK references for these functions can be found [[http://​www.rhino3d.com/​5/​rhinocommon/​html/​Methods_T_Rhino_PlugIns_PlugIn.htm|here]]
 +
 +When Rhino writes a .3dm file, it goes through all the plug-ins that are currently loaded. ​ First Rhino calls ShouldWriteDocument() to see if the plug-in wants to save document user data.  If ShouldWriteDocument() returns true, Rhino saves information that identifies the plug-in and then calls WriteDocument() when it is time for the plug-in to save its "​document"​ user data.
 +
 +When Rhino reads a .3dm file and it encounters document user data, it uses the plug-in identification information to load the plug-in and then calls the plug-in'​s ReadDocument() to read the plug-in'​s "​document"​ user data.
 +
 +
 +=====Object User Data=====
 +
 +Object user data can be attached to things like layers, materials, geometry objects, and object attributes. ​ In fact object user data can be attached to any class derived from CommonObject. ​ This user data is stored in a linked list on CommonObject and can be copied, transformed and saved along with the parent object. ​ For example, you could attach object user data to a mesh.  When the mesh is copied the object user data would be copied and attached to the copy.  When the mesh is transformed,​ the transformation would be recored by the object user data.  When the mesh is saved in a .3dm file, the object user data will be saved too.
 +
 +There are three forms of object user data
 +  - User strings
 +  - UserDictionary
 +  - Custom UserData
 +
 +**It is recommended to typically use the User Strings or the UserDictionary on an object since the data is automatically serialized for you and it is easily shared between plug-ins and scripts.**
 +
 +In the case that you want to write your own private custom user data, you would derive a class from Rhino.DocObjects.Custom.UserData. ​ Here's a sample
 +
 +===== C# =====
 +<code c# userdata.cs>​
 +using System;
 +using Rhino;
 +using System.Runtime.InteropServices;​
 +
 +namespace examples_cs
 +{
 +  // You must define a Guid attribute for your user data derived class
 +  // in order to support serialization. Every custom user data class
 +  // needs a custom Guid
 +  [Guid("​DAAA9791-01DB-4F5F-B89B-4AE46767C783"​)]
 +  public class PhysicalData : Rhino.DocObjects.Custom.UserData
 +  {
 +    public int Weight{ get; set; }
 +    public double Density {get; set;}
 +
 +
 +    // Your UserData class must have a public parameterless constructor
 +    public PhysicalData(){}
 +
 +    public PhysicalData(int weight, double density)
 +    {
 +      Weight = weight;
 +      Density = density;
 +    }
 +
 +    public override string Description
 +    {
 +      get { return "​Physical Properties";​ }
 +    }
 +
 +    public override string ToString()
 +    {
 +      return String.Format("​weight={0},​ density={1}",​ Weight, Density);
 +    }
 +
 +    protected override void OnDuplicate(Rhino.DocObjects.Custom.UserData source)
 +    {
 +      PhysicalData src = source as PhysicalData;​
 +      if (src != null)
 +      {
 +        Weight = src.Weight;
 +        Density = src.Density;​
 +      }
 +    }
 +
 +    // return true if you have information to save
 +    public override bool ShouldWrite
 +    {
 +      get
 +      {
 +        if (Weight > 0 && Density > 0)
 +          return true;
 +        return false;
 +      }
 +    }
 +
 +    protected override bool Read(Rhino.FileIO.BinaryArchiveReader archive)
 +    {
 +      Rhino.Collections.ArchivableDictionary dict = archive.ReadDictionary();​
 +      if (dict.ContainsKey("​Weight"​) && dict.ContainsKey("​Density"​))
 +      {
 +        Weight = (int)dict["​Weight"​];​
 +        Density = (double)dict["​Density"​];​
 +      }
 +      return true;
 +    }
 +    protected override bool Write(Rhino.FileIO.BinaryArchiveWriter archive)
 +    {
 +      // you can implement File IO however you want... but the dictionary class makes
 +      // issues like versioning in the 3dm file a bit easier. ​ If you didn't want to use
 +      // the dictionary for writing, your code would look something like.
 +      //
 +      //  archive.Write3dmChunkVersion(1,​ 0);
 +      //  archive.WriteInt(Weight);​
 +      //  archive.WriteDouble(Density);​
 +      var dict = new Rhino.Collections.ArchivableDictionary(1,​ "​Physical"​);​
 +      dict.Set("​Weight",​ Weight);
 +      dict.Set("​Density",​ Density);
 +      archive.WriteDictionary(dict);​
 +      return true;
 +    }
 +  }
 +
 +
 +  [Guid("​ca9a110e-3969-49ec-9d59-a7c2ee0b85bd"​)]
 +  public class ex_userdataCommand : Rhino.Commands.Command
 +  {
 +    public override string EnglishName { get { return "​cs_userdataCommand";​ } }
 +
 +    protected override Rhino.Commands.Result RunCommand(RhinoDoc doc, Rhino.Commands.RunMode mode)
 +    {
 +      Rhino.DocObjects.ObjRef objref;
 +      var rc = Rhino.Input.RhinoGet.GetOneObject("​Select Object",​ false, Rhino.DocObjects.ObjectType.AnyObject,​ out objref);
 +      if (rc != Rhino.Commands.Result.Success)
 +        return rc;
 +
 +      // See if user data of my custom type is attached to the geomtry
 +      var ud = objref.Geometry().UserData.Find(typeof(PhysicalData)) as PhysicalData;​
 +      if (ud == null)
 +      {
 +        // No user data found; create one and add it
 +        int weight = 0;
 +        rc = Rhino.Input.RhinoGet.GetInteger("​Weight",​ false, ref weight);
 +        if (rc != Rhino.Commands.Result.Success)
 +          return rc;
 +
 +        ud = new PhysicalData(weight,​ 12.34);
 +        objref.Geometry().UserData.Add(ud);​
 +      }
 +      else
 +      {
 +        RhinoApp.WriteLine("​{0} = {1}", ud.Description,​ ud);
 +      }
 +      return Rhino.Commands.Result.Success;​
 +    }
 +  }
 +}
 +
 +</​code>​
 +
 +{{tag>​Developer rhinocommon}}
  
developer/rhinocommonsamples/userdata.txt ยท Last modified: 2015/09/14 (external edit)