private JToken GetSkyMaterial(ValveBspFile bsp, string skyName)
        {
            var postfixes = new[]
            {
                "ft", "bk", "dn", "up", "rt", "lf"
            };

            var propArray = new JArray();
            var faceUrls  = new string[6];

            var i = 0;

            foreach (var postfix in postfixes)
            {
                var matName     = $"materials/skybox/{skyName}{postfix}.vmt";
                var matDir      = Path.GetDirectoryName(matName);
                var vmt         = VmtUtils.OpenVmt(bsp, matName);
                var shaderProps = vmt[vmt.Shaders.FirstOrDefault()];
                var baseTex     = shaderProps["$hdrcompressedtexture"] ?? shaderProps["$basetexture"];
                faceUrls[i++] = VmtUtils.GetTextureUrl(Request, bsp, baseTex, matDir);
            }

            VmtUtils.AddTextureCubeProperty(propArray, "baseTexture", faceUrls);

            return(new JObject
            {
                { "shader", "Sky" },
                { "properties", propArray }
            });
        }
        public JToken GetMaterials([Url] string mapName)
        {
            if (CheckNotExpired(mapName))
            {
                return(null);
            }

            var response = new JArray();

            var bsp = GetBspFile(Request, mapName);

            for (var i = 0; i < bsp.TextureStringTable.Length; ++i)
            {
                var path = $"materials/{bsp.GetTextureString( i ).ToLower()}.vmt";
                var vmt  = VmtUtils.OpenVmt(bsp, path);
                response.Add(vmt == null ? null : VmtUtils.SerializeVmt(Request, bsp, vmt, path));
            }

            return(new JObject
            {
                { "materials", response }
            });
        }
        private JToken GetIndex(IResourceProvider provider, string filePath, string mapName = null)
        {
            StudioModelFile mdl;

            using (var mdlStream = provider.OpenFile(filePath))
            {
                mdl = new StudioModelFile(mdlStream);
            }

            var parts = new JArray();

            for (var bodyPartIndex = 0; bodyPartIndex < mdl.BodyPartCount; ++bodyPartIndex)
            {
                var models = new JArray();

                var modelIndex = 0;
                foreach (var model in mdl.GetModels(bodyPartIndex))
                {
                    var meshes = new JArray();

                    foreach (var mesh in mdl.GetMeshes(model.MeshIndex, model.NumMeshes))
                    {
                        meshes.Add(new JObject
                        {
                            { "material", mesh.Material },
                            { "center", mesh.Center.ToJson() }
                        });
                    }

                    var meshDataAction = mapName == null?nameof(GetVpkMeshData) : nameof(GetPakMeshData);

                    models.Add(new JObject
                    {
                        { "name", model.Name },
                        { "radius", model.BoundingRadius },
                        {
                            "meshDataUrl", GetActionUrl(meshDataAction,
                                                        ResourcePath(filePath),
                                                        Replace("mapName", mapName),
                                                        Replace("bodyPart", bodyPartIndex),
                                                        Replace("model", modelIndex),
                                                        Replace("lod", 0))
                        },
                        { "meshes", meshes }
                    });

                    ++modelIndex;
                }

                parts.Add(new JObject
                {
                    { "name", mdl.GetBodyPartName(bodyPartIndex) },
                    { "models", models }
                });
            }

            var materials = new JArray();

            for (var i = 0; i < mdl.NumTextures; ++i)
            {
                var vmtPath = provider is ValveBspFile.PakFileLump
                    ? mdl.GetMaterialName(i, provider, Resources)
                    : mdl.GetMaterialName(i, provider);

                if (!vmtPath.Contains("/"))
                {
                    var mdlDir = Path.GetDirectoryName(filePath);
                    vmtPath = Path.Combine(mdlDir, vmtPath).Replace('\\', '/');
                }

                var vmt = mapName == null
                    ? VmtUtils.OpenVmt(vmtPath)
                    : VmtUtils.OpenVmt(BspController.GetBspFile(Request, mapName), vmtPath);

                materials.Add(vmt == null ? null : VmtUtils.SerializeVmt(Request, vmt, vmtPath));
            }

            return(new JObject
            {
                { "materials", materials },
                { "bodyParts", parts }
            });
        }