/// <summary>
        /// Creates a mesh set shape for serialising the mesh and its resource references.
        /// </summary>
        /// <param name="shapeComponent">The component to create a shape for.</param>
        /// <returns>A shape instance suitable for configuring to generate serialisation messages.</returns>
        protected override Shapes.Shape CreateSerialisationShape(ShapeComponent shapeComponent)
        {
            // Start by building the resource list.
            int partCount          = shapeComponent.transform.childCount;
            ObjectAttributes attrs = new ObjectAttributes();

            Shapes.MeshSet meshSet = new Shapes.MeshSet(shapeComponent.ObjectID, shapeComponent.Category);
            EncodeAttributes(ref attrs, shapeComponent.gameObject, shapeComponent);
            meshSet.SetAttributes(attrs);
            for (int i = 0; i < partCount; ++i)
            {
                // Write the mesh ID
                ShapeComponent partSrc = shapeComponent.transform.GetChild(i).GetComponent <ShapeComponent>();
                if (partSrc != null)
                {
                    MeshResourcePlaceholder part = new MeshResourcePlaceholder(partSrc.ObjectID);
                    // Encode attributes into target format.
                    EncodeAttributes(ref attrs, partSrc.gameObject, partSrc);
                    // And convert to matrix.
                    meshSet.AddPart(part, attrs.GetTransform());
                }
                else
                {
                    Log.Error("Failed to extract child {0} for mesh set {1}.", i, shapeComponent.name);
                    return(null);
                }
            }
            return(meshSet);
        }
        /// <summary>
        /// Read the contents of a create message for a <c>MeshSet</c>.
        /// </summary>
        /// <param name="packet">The buffer from which the reader reads.</param>
        /// <param name="reader">Stream to read from</param>
        /// <returns>True on success.</returns>
        /// <remarks>
        /// Reads additional data about the mesh parts contained in the mesh. All parts are represented
        /// by a <see cref="PlaceholderMesh"/> as real mesh data cannot be resolved here.
        /// </remarks>
        public override bool ReadCreate(PacketBuffer packet, BinaryReader reader)
        {
            if (!_data.Read(reader))
            {
                return(false);
            }

            // Read part details.
            // Note: we can only create placeholder meshes here for referencing resource IDs elsewhere.
            int partCount = reader.ReadUInt16();

            _parts.Clear();

            if (partCount > 0)
            {
                uint             meshId;
                ObjectAttributes partAttributes = new ObjectAttributes();

                for (int i = 0; i < partCount; ++i)
                {
                    meshId = reader.ReadUInt32();

                    if (!partAttributes.Read(reader))
                    {
                        return(false);
                    }

                    _parts.Add(new Part
                    {
                        Resource  = new PlaceholderMesh(meshId),
                        Transform = partAttributes.GetTransform(),
                        Colour    = new Colour(partAttributes.Colour)
                    });
                }
            }

            return(true);
        }