public static void Import(string xmlPath, GameObject root, string materialFolder)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(xmlPath);

            XmlNode xmlRoot = doc.DocumentElement;

            XmlNodeList nodes = xmlRoot.SelectNodes("/assignments/node");

            Dictionary<GameObject, List<AlembicMaterial.Assignment> > allAssignments = new Dictionary<GameObject, List<AlembicMaterial.Assignment> >();

            foreach (XmlNode node in nodes)
            {
                string path = node.Attributes["path"].Value;

                XmlNodeList shaders = node.SelectNodes("shader");

                foreach (XmlNode shader in shaders)
                {
                    XmlAttribute name = shader.Attributes["name"];
                    XmlAttribute inst = shader.Attributes["instance"];

                    if (name == null)
                    {
                        continue;
                    }

                    int instNum = (inst == null ? 0 : Convert.ToInt32(inst.Value));

                    GameObject target = FindNode(root, path, instNum);

                    if (target == null)
                    {
                        // Debug.Log("Could not find node: " + path);
                        continue;
                    }

                    List<AlembicMaterial.Assignment> assignments;

                    if (!allAssignments.ContainsKey(target))
                    {
                        assignments = new List<AlembicMaterial.Assignment>();
                        allAssignments.Add(target, assignments);
                    }
                    else
                    {
                        assignments = allAssignments[target];
                    }

                    Material material = GetMaterial(name.Value, materialFolder);

                    if (material == null)
                    {
                        material = new Material(Shader.Find("Standard"));

                        material.color = new Color(UnityEngine.Random.value,
                                                   UnityEngine.Random.value,
                                                   UnityEngine.Random.value);

                        AssetDatabase.CreateAsset(material, materialFolder + "/" + name.Value + ".mat");
                    }

                    // Get or create material assignment
                    bool newlyAssigned = false;
                    AlembicMaterial.Assignment a = null;

                    if (a == null)
                    {
                        a = new AlembicMaterial.Assignment();
                        a.material = material;
                        a.faces = new List<int>();

                        assignments.Add(a);

                        newlyAssigned = true;
                    }

                    string faceset = shader.InnerText;
                    faceset.Trim();

                    if (faceset.Length > 0 && (newlyAssigned || a.faces.Count > 0))
                    {
                        string[] items = faceset.Split(FaceSep, StringSplitOptions.RemoveEmptyEntries);

                        for (int i=0; i<items.Length; ++i)
                        {
                            string[] rng = items[i].Split(RangeSep, StringSplitOptions.RemoveEmptyEntries);

                            if (rng.Length == 1)
                            {
                                a.faces.Add(Convert.ToInt32(rng[0]));
                            }
                            else if (rng.Length == 2)
                            {
                                int j0 = Convert.ToInt32(rng[0]);
                                int j1 = Convert.ToInt32(rng[1]);

                                for (int j=j0; j<=j1; ++j)
                                {
                                    a.faces.Add(j);
                                }
                            }
                        }

                        if (!newlyAssigned)
                        {
                            a.faces = new List<int>(new HashSet<int>(a.faces));
                        }
                    }
                    else if (faceset.Length == 0 && a.faces.Count > 0)
                    {
                        // Shader assgined to whole object, remove any face level assignments
                        a.faces.Clear();
                    }
                }
            }

            // Update AlembicMaterial components
            foreach (KeyValuePair<GameObject, List<AlembicMaterial.Assignment> > pair in allAssignments)
            {
                AlembicMaterial abcmaterial = pair.Key.GetComponent<AlembicMaterial>();

                if (abcmaterial == null)
                {
                    abcmaterial = pair.Key.AddComponent<AlembicMaterial>();
                }

                abcmaterial.UpdateAssignments(pair.Value);
            }

            // Force refresh
            AlembicStream abcstream = root.GetComponent<AlembicStream>();

            if (abcstream != null)
            {
                abcstream.m_forceRefresh = true;
                abcstream.SendMessage("AbcUpdate", abcstream.m_time, SendMessageOptions.DontRequireReceiver);
            }
        }
        public static void Import(string xmlPath, GameObject root, string materialFolder)
        {
            XmlDocument doc = new XmlDocument();

            doc.Load(xmlPath);

            XmlNode xmlRoot = doc.DocumentElement;

            XmlNodeList nodes = xmlRoot.SelectNodes("/assignments/node");

            Dictionary <GameObject, List <AlembicMaterial.Assignment> > allAssignments = new Dictionary <GameObject, List <AlembicMaterial.Assignment> >();

            foreach (XmlNode node in nodes)
            {
                string path = node.Attributes["path"].Value;

                XmlNodeList shaders = node.SelectNodes("shader");

                foreach (XmlNode shader in shaders)
                {
                    XmlAttribute name = shader.Attributes["name"];
                    XmlAttribute inst = shader.Attributes["instance"];

                    if (name == null)
                    {
                        continue;
                    }

                    int instNum = (inst == null ? 0 : Convert.ToInt32(inst.Value));

                    GameObject target = FindNode(root, path, instNum);

                    if (target == null)
                    {
                        // Debug.Log("Could not find node: " + path);
                        continue;
                    }

                    List <AlembicMaterial.Assignment> assignments;

                    if (!allAssignments.ContainsKey(target))
                    {
                        assignments = new List <AlembicMaterial.Assignment>();
                        allAssignments.Add(target, assignments);
                    }
                    else
                    {
                        assignments = allAssignments[target];
                    }

                    Material material = GetMaterial(name.Value, materialFolder);

                    if (material == null)
                    {
                        material = new Material(Shader.Find("Standard"));

                        material.color = new Color(UnityEngine.Random.value,
                                                   UnityEngine.Random.value,
                                                   UnityEngine.Random.value);

                        AssetDatabase.CreateAsset(material, materialFolder + "/" + name.Value + ".mat");
                    }

                    // Get or create material assignment
                    bool newlyAssigned           = false;
                    AlembicMaterial.Assignment a = null;

                    if (a == null)
                    {
                        a          = new AlembicMaterial.Assignment();
                        a.material = material;
                        a.faces    = new List <int>();

                        assignments.Add(a);

                        newlyAssigned = true;
                    }

                    string faceset = shader.InnerText;
                    faceset.Trim();

                    if (faceset.Length > 0 && (newlyAssigned || a.faces.Count > 0))
                    {
                        string[] items = faceset.Split(FaceSep, StringSplitOptions.RemoveEmptyEntries);

                        for (int i = 0; i < items.Length; ++i)
                        {
                            string[] rng = items[i].Split(RangeSep, StringSplitOptions.RemoveEmptyEntries);

                            if (rng.Length == 1)
                            {
                                a.faces.Add(Convert.ToInt32(rng[0]));
                            }
                            else if (rng.Length == 2)
                            {
                                int j0 = Convert.ToInt32(rng[0]);
                                int j1 = Convert.ToInt32(rng[1]);

                                for (int j = j0; j <= j1; ++j)
                                {
                                    a.faces.Add(j);
                                }
                            }
                        }

                        if (!newlyAssigned)
                        {
                            a.faces = new List <int>(new HashSet <int>(a.faces));
                        }
                    }
                    else if (faceset.Length == 0 && a.faces.Count > 0)
                    {
                        // Shader assgined to whole object, remove any face level assignments
                        a.faces.Clear();
                    }
                }
            }

            // Update AlembicMaterial components
            foreach (KeyValuePair <GameObject, List <AlembicMaterial.Assignment> > pair in allAssignments)
            {
                AlembicMaterial abcmaterial = pair.Key.GetComponent <AlembicMaterial>();

                if (abcmaterial == null)
                {
                    abcmaterial = pair.Key.AddComponent <AlembicMaterial>();
                }

                abcmaterial.UpdateAssignments(pair.Value);
            }

            // Force refresh
            AlembicStream abcstream = root.GetComponent <AlembicStream>();

            if (abcstream != null)
            {
                abcstream.m_forceRefresh = true;
                abcstream.SendMessage("AbcUpdate", abcstream.m_time, SendMessageOptions.DontRequireReceiver);
            }
        }