/// <summary>
        /// Reads a Quill project folder and imports it in a Sequence object.
        /// A project consists in a json-based scene hierarchy, a json-based state file, and binary data.
        /// </summary>
        public static Sequence Read(string path)
        {
            if (string.IsNullOrEmpty(path) || !Directory.Exists(path))
            {
                return(null);
            }

            string sequenceFilename  = Path.Combine(path, "Quill.json");
            string paintDataFilename = Path.Combine(path, "Quill.qbin");

            if (!File.Exists(sequenceFilename) || !File.Exists(paintDataFilename))
            {
                return(null);
            }

            Sequence seq = null;

            try
            {
                string  json     = File.ReadAllText(sequenceFilename);
                dynamic document = JsonConvert.DeserializeObject(json);
                seq = Parse(document);
            }
            catch (JsonReaderException e)
            {
                // The JSON is invalid.
                // This happened sometimes in the early days of Quill when the transforms exploded and "inf" or "nan" was written in the matrix array.
                Console.WriteLine("JSON parsing error: {0}", e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine("Error during the parsing of the Quill.json document: {0}", e.Message);
            }

            if (seq == null)
            {
                return(null);
            }

            // Now that we have loaded the scene hierarchy, read the actual attached data from the qbin.
            using (Stream stream = File.OpenRead(paintDataFilename))
            {
                QBinReader qbinReader = new QBinReader(stream);
                seq.LastStrokeId = qbinReader.ReadUInt32();
                ReadLayerData(seq.RootLayer, qbinReader);
            }

            return(seq);
        }
 /// <summary>
 /// Recursive function reading binary data for the entire hierarchy.
 /// </summary>
 private static void ReadLayerData(Layer layer, QBinReader qbinReader)
 {
     if (layer.Type == LayerType.Group)
     {
         foreach (Layer l in ((LayerGroup)layer).Children)
         {
             ReadLayerData(l, qbinReader);
         }
     }
     else if (layer.Type == LayerType.Paint)
     {
         foreach (Drawing drawing in ((LayerPaint)layer).Drawings)
         {
             qbinReader.BaseStream.Seek(drawing.DataFileOffset, SeekOrigin.Begin);
             drawing.Data = qbinReader.ReadDrawingData();
         }
     }
 }