Internalise custom parameter

Description of the problem: There is a class Joint, it has JointGoo. There is a parameter JointParameter. When you click “Internalise” on Grasshopper and then copy a Parameter, all data from it is reset. Why might this happen?

This is what the properties of the Joint class look like:

    public class Joint
    {
        public int NodeID { get; }
        public Point3d Origin { get; set; }
        public List<Arm> Arms { get; set; } = new List<Arm>();
        public List<Chock> Chocks { get; set; } = new List<Chock>();
        public List<WasherL> LWashers { get; set; } = new List<WasherL>();
        public List<WasherS> SWashers { get; set; } = new List<WasherS>();
        public bool IsValid { get; set; }
}

JointGoo:

using Grasshopper.Kernel.Types;
using Grasshopper.Kernel;
using System.Linq;
using Rhino.Geometry;
using System;
using System.Collections.Generic;

namespace StructuralJointsDesigner
{
    public class JointGoo : GH_GeometricGoo<Joint>, IGH_PreviewData
    {
        #region constructors
        public JointGoo()
        {
            this.Value = new Joint();
        }

        public JointGoo(Joint joint)
        {
            if (joint == null)
            {
                joint = new Joint();
            }    
            this.Value = joint;
        }

        public override IGH_GeometricGoo DuplicateGeometry()
        {
            return DuplicateJointGoo();
        }

        public JointGoo DuplicateJointGoo()
        {
            return new JointGoo(Value == null ? new Joint() : Value.Duplicate());
        }
        #endregion

        #region properties
        public override bool IsValid
        {
            get
            {
                if (Value == null) { return false; }
                return Value.IsValid;
            }
        }

        public override string IsValidWhyNot
        {
            get
            {
                if (Value == null) { return "No internal Joint instance"; }
                if (Value.IsValid) { return string.Empty; }
                return "Invalid Joint instance";
            }
        }

        public override string ToString()
        {
            if (Value == null)
                return "Null Joint";
            else
                return "Joint " + Value.NodeID.ToString() + " (" + string.Join("-", Value.LWashers.Select(w => w.LineID.ToString())) + " arms)";
        }

        public override string TypeName
        {
            get { return (typeof(Joint).Name); }
        }
        public override string TypeDescription
        {
            get { return ("Joint"); }
        }
        public override BoundingBox Boundingbox
        {
            get
            {
                if (Value == null) { return BoundingBox.Empty; }
                return Value.GetBoundingBox();
            }
        }
        public override BoundingBox GetBoundingBox(Transform xform)
        {
            if (Value == null) { return BoundingBox.Empty; }
            return Value.GetBoundingBox(xform);
        }
        #endregion

        #region casting methods
        public override bool CastTo<Q>(out Q target)
        {
            //Cast to Joint.
            if (typeof(Q).IsAssignableFrom(typeof(Joint)))
            {
                if (Value == null)
                    target = default(Q);
                else
                    target = (Q)(object)Value;
                return true;
            }

            //Cast to Mesh.
            if (typeof(Q).IsAssignableFrom(typeof(GH_Mesh)))
            {
                if (Value == null)
                    target = default(Q);
                else if (Value.GetMeshes() == null)
                    target = default(Q);
                else
                    target = (Q)(object)new GH_Mesh(Value.GetMeshes());
                return true;
            }

            target = default(Q);
            return false;
        }
        public override bool CastFrom(object source)
        {
            if (source == null) { return false; }

            if (typeof(Joint).IsAssignableFrom(source.GetType()))
            {
                Value = (Joint)source;
                return true;
            }

            return false;
        }
        #endregion

        #region transformation methods
        public override IGH_GeometricGoo Transform(Transform xform)
        {
            if (Value == null || !Value.IsValid) return null;

            var transformedJoint = Value.Duplicate();
            transformedJoint.Transform(xform);
            return new JointGoo(transformedJoint);
        }
        public override IGH_GeometricGoo Morph(SpaceMorph xmorph)
        {
            return null;
        }
        #endregion

        #region drawing methods
        public BoundingBox ClippingBox
        {
            get { return Boundingbox; }
        }

        public void DrawViewportWires(GH_PreviewWireArgs args)
        {
            if (Value == null) { return; }
            
            if (Value.LWashers.Count > 0)
            {
                ProcessWasherEdges(Value.LWashers, args);
            }

            if (Value.SWashers.Count > 0)
            {
                ProcessWasherEdges(Value.SWashers, args);
            }

            foreach (Arm arm in Value.Arms)
            {
                args.Pipeline.DrawCurve(arm.Outline, System.Drawing.Color.Aquamarine, 2);
                foreach (Hole hole in arm.Holes)
                {
                    args.Pipeline.DrawCurve(hole.Curve, System.Drawing.Color.Aquamarine, 2);
                }
            }

            foreach (Chock chock in Value.Chocks)
            {
                args.Pipeline.DrawCurve(chock.Outline, System.Drawing.Color.Aquamarine, 2);
                foreach (Hole hole in chock.Holes)
                {
                    args.Pipeline.DrawCurve(hole.Curve, System.Drawing.Color.Aquamarine, 2);
                }
            }
        }

        public void DrawViewportMeshes(GH_PreviewMeshArgs args)
        {
        }

        private static void ProcessWasherEdges<T>(IEnumerable<T> washers, GH_PreviewWireArgs args) where T : Plywood
        {
            foreach (var washer in washers)
            {
                Curve crv = washer.Outline;
                Plane plane = washer.Plane;
                var offsetCurve = crv.DuplicateCurve();

                switch (washer.OffsetType)
                {
                    case OffsetType.Up:
                        // Никакого смещения не требуется
                        break;
                    case OffsetType.Middle:
                        offsetCurve.Transform(Rhino.Geometry.Transform.Translation(-plane.ZAxis * washer.Thickness / 2));
                        break;
                    case OffsetType.Dawn:
                        offsetCurve.Transform(Rhino.Geometry.Transform.Translation(-plane.ZAxis * washer.Thickness));
                        break;
                    default:
                        throw new Exception("У объекта не указано направление выдавливания.");
                }

                args.Pipeline.DrawCurve(offsetCurve, System.Drawing.Color.Aquamarine, 3);
            }
        }

        #endregion
    }
}

You need to override read and write methods. Below is an example based on the read and write methods of the Javid Bitmap parameter:

public override bool Read(GH_IReader reader)
{
    m_value = reader.GetDrawingBitmap("Bitmap");
    return true;
}
public override bool Write(GH_IWriter writer)
{
    if (m_value != null)
        writer.SetDrawingBitmap("Bitmap", m_value);
    return true;
}

These methods handle the serialization and deserialization of the ‘Bitmap’ data. For a complete reference, you can review the GH_Bitmap class in the Javid repository on GitHub at: Javid/Javid/Parameter/GH_Bitmap.cs at master · mahdiyargit/Javid · GitHub.

1 Like