private static void AddModelNode(VirtualFolderVM parent, string localPath, LocalGameClientPackageIndexer indexer, bool addVisualNode = true)
        {
            var modelNode = new RemotePackageFileVM(parent,
                                                    indexer.GetPackagePath(localPath),
                                                    localPath,
                                                    Localization.Instance.L("game_client_explorer", "model"));

            parent.AddChild(modelNode);

            if (addVisualNode)
            {
                var    model      = TankNodeVM.LoadXmlFile(indexer.GetUnifiedPath(localPath));
                string visualFile = (model.Query("nodefullVisual") ?? model.Query("nodelessVisual")).Value + ".visual";
                if (!string.IsNullOrEmpty(visualFile))
                {
                    TankNodeVM.AddVisualNode(parent, visualFile, indexer);
                }
            }
        }
        private static void AddVisualNode(VirtualFolderVM parent, string localPath, LocalGameClientPackageIndexer indexer)
        {
            var visualNode = new RemotePackageFileVM(parent,
                                                     indexer.GetPackagePath(localPath),
                                                     localPath,
                                                     Localization.Instance.L("game_client_explorer", "visual"));

            parent.AddChild(visualNode);


            var visual = TankNodeVM.LoadXmlFile(indexer.GetUnifiedPath(localPath));

            foreach (var primitiveGroup in visual.QueryMany("renderSet/geometry/primitiveGroup"))
            {
                var material = primitiveGroup.Query("material");

                var identifier = material["identifier"];
                var groupNode  = new VirtualFolderVM(parent, identifier);
                parent.AddChild(groupNode);

                foreach (var property in material.QueryMany("property"))
                {
                    var    propertyName = (property.ToElement().FirstNode as XText).Value;
                    string displayName;
                    switch (propertyName.Trim())
                    {
                    case "specularMap":
                        displayName = Localization.Instance.L("game_client_explorer", "specular_map");
                        break;

                    case "normalMap":
                        displayName = Localization.Instance.L("game_client_explorer", "normal_map");
                        break;

                    case "diffuseMap":
                        displayName = Localization.Instance.L("game_client_explorer", "diffuse_map");
                        break;

                    case "metallicDetailMap":
                        displayName = Localization.Instance.L("game_client_explorer", "metallic_detail_map");
                        break;

                    case "metallicGlossMap":
                        displayName = Localization.Instance.L("game_client_explorer", "metallic_gloss_map");
                        break;

                    case "excludeMaskMap":
                        displayName = Localization.Instance.L("game_client_explorer", "exclude_mask_map");
                        break;

                    default:
                        if (property.Query("Texture") != null)
                        {
                        }
                        continue;
                    }

                    var textureFile = property["Texture"];
                    if (string.IsNullOrEmpty(textureFile))
                    {
                        continue;
                    }

                    var fileNode = new RemotePackageFileVM(groupNode, indexer.GetPackagePath(textureFile), textureFile, displayName);
                    groupNode.AddChild(fileNode);
                }
            }
        }