Beispiel #1
0
    // Helper method to lookup nonlocal textures from another bnd
    static Texture2D FindTexture(string path, DarkSoulsTools.GameType gameType)
    {
        string gamePath = DarkSoulsTools.GameFolder(gameType);

        // Map texture reference
        if (path.Contains(@"\map\"))
        {
            var splits = path.Split('\\');
            var mapid  = splits[splits.Length - 3];
            var asset  = AssetDatabase.LoadAssetAtPath <Texture2D>($@"Assets/{gamePath}/{mapid}/{Path.GetFileNameWithoutExtension(path)}.dds");
            if (asset == null)
            {
                // Attempt to load UDSFM texture
                asset = AssetDatabase.LoadAssetAtPath <Texture2D>($@"Assets/{gamePath}/UDSFMMapTextures/{Path.GetFileNameWithoutExtension(path)}.dds");
            }
            return(asset);
        }
        // Chr texture reference
        else if (path.Contains(@"\chr\"))
        {
            var splits = path.Split('\\');
            var chrid  = splits[splits.Length - 3];
            var asset  = AssetDatabase.LoadAssetAtPath <Texture2D>($@"Assets/{gamePath}/Chr/{chrid}/{Path.GetFileNameWithoutExtension(path)}.dds");
            if (asset == null)
            {
                // Attempt to load shared chr textures
                asset = AssetDatabase.LoadAssetAtPath <Texture2D>($@"Assets/{gamePath}/Chr/sharedTextures/{Path.GetFileNameWithoutExtension(path)}.dds");
            }
            return(asset);
        }
        // Obj texture reference
        else if (path.Contains(@"\obj\"))
        {
            var splits = path.Split('\\');
            var objid  = splits[splits.Length - 3];
            var asset  = AssetDatabase.LoadAssetAtPath <Texture2D>($@"Assets/{gamePath}/Obj/{objid}/{Path.GetFileNameWithoutExtension(path)}.dds");
            if (asset == null)
            {
                // Attempt to load shared chr textures
                asset = AssetDatabase.LoadAssetAtPath <Texture2D>($@"Assets/{gamePath}/Obj/sharedTextures/{Path.GetFileNameWithoutExtension(path)}.dds");
            }
            return(asset);
        }
        // Parts texture reference
        else if (path.Contains(@"\parts\"))
        {
            var asset = AssetDatabase.LoadAssetAtPath <Texture2D>($@"Assets/{gamePath}/Parts/textures/{Path.GetFileNameWithoutExtension(path)}.dds");
            return(asset);
        }
        return(null);
    }
Beispiel #2
0
    static public void ImportFlver(FLVER flver, FLVERAssetLink assetLink, DarkSoulsTools.GameType gameType, string assetName, string texturePath = null, bool mapflver = false)
    {
        Material[] materials = new Material[flver.Materials.Count];
        string     gamePath  = DarkSoulsTools.GameFolder(gameType);

        if (!AssetDatabase.IsValidFolder(assetName))
        {
            AssetDatabase.CreateFolder(Path.GetDirectoryName(assetName + ".blah"), Path.GetFileNameWithoutExtension(assetName + ".blah"));
        }

        Shader shader     = AssetDatabase.LoadAssetAtPath <Shader>("Assets/dstools/Shaders/FLVERShader.shadergraph");
        Shader shaderObj  = AssetDatabase.LoadAssetAtPath <Shader>("Assets/dstools/Shaders/ObjFLVERShader.shadergraph");
        Shader shaderDiff = AssetDatabase.LoadAssetAtPath <Shader>("Assets/dstools/Shaders/FLVERShaderDiffuse.shadergraph");
        var    t          = 0;

        foreach (var m in flver.Materials)
        {
            //string name = m.Name;
            //if (name == null || name == "")
            //{
            string name = Path.GetFileNameWithoutExtension(assetName) + $@"_{t}";
            //}
            //bool normalquery = (m.Textures.Where(x => ((x.Type.ToUpper() == "G_BUMPMAPTEXTURE") || (x.Type.ToUpper() == "G_BUMPMAP"))).Count() >= 1);
            bool normalquery = false;

            Texture2D albedo       = null;
            Texture2D specular     = null;
            Texture2D normal       = null;
            bool      IsMapTexture = mapflver;
            var       MTD          = AssetDatabase.LoadAssetAtPath <MTDAssetLink>($@"Assets/{gamePath}/MTD/{Path.GetFileNameWithoutExtension(m.MTD)}.asset");
            if (texturePath != null)
            {
                foreach (var matParam in m.Textures)
                {
                    var paramNameCheck = matParam.Type.ToUpper();
                    if (paramNameCheck == "G_DIFFUSETEXTURE" || paramNameCheck == "G_DIFFUSE" || paramNameCheck.Contains("ALBEDO"))
                    {
                        var texPath = matParam.Path;
                        if (texPath == "")
                        {
                            texPath = MTD.Textures.Find(x => (x.Name == matParam.Type)).TexturePath;
                            if (texPath == "")
                            {
                                continue;
                            }
                        }
                        if (albedo == null)
                        {
                            albedo = AssetDatabase.LoadAssetAtPath <Texture2D>($@"{texturePath}/{Path.GetFileNameWithoutExtension(texPath)}.dds");
                            if (albedo == null)
                            {
                                albedo = FindTexture(texPath, gameType);
                            }
                        }
                    }
                    if (paramNameCheck == "G_SPECULARTEXTURE" || paramNameCheck == "G_SPECULAR")
                    {
                        specular = AssetDatabase.LoadAssetAtPath <Texture2D>($@"{texturePath}/{Path.GetFileNameWithoutExtension(matParam.Path)}.dds");
                        if (specular == null)
                        {
                            specular = FindTexture(matParam.Path, gameType);
                        }
                    }
                    if (paramNameCheck == "G_BUMPMAPTEXTURE" || paramNameCheck == "G_BUMPMAP" || paramNameCheck.Contains("NORMAL"))
                    {
                        var texPath = matParam.Path;
                        if (texPath == "")
                        {
                            texPath = MTD.Textures.Find(x => (x.Name == matParam.Type)).TexturePath;
                            if (texPath == "")
                            {
                                continue;
                            }
                        }
                        if (normal == null)
                        {
                            normal = AssetDatabase.LoadAssetAtPath <Texture2D>($@"{texturePath}/{Path.GetFileNameWithoutExtension(texPath)}.dds");
                            if (normal == null)
                            {
                                normal = FindTexture(texPath, gameType);
                            }
                        }
                        normalquery = true;
                    }
                }
            }
            Material mat;

            /*if (IsMapTexture && specular != null)
             * {
             *  mat = new Material(shader);
             *  mat.SetTexture("_Albedo", albedo);
             *  mat.SetTexture("_Specular", specular);
             *  mat.SetTexture("_Normal", normal);
             * }
             * else */
            if (!normalquery)
            {
                mat = new Material(shaderDiff);
                mat.SetTexture("_MainTex", albedo);
            }
            else
            {
                mat = new Material(shaderObj);
                mat.SetTexture("_MainTex", albedo);
                mat.SetTexture("_Specular", specular);
                mat.SetTexture("_BumpMap", normal);
            }
            mat.name     = name;
            materials[t] = mat;
            t++;
            AssetDatabase.CreateAsset(mat, assetName + "/" + name + ".mat");
        }

        GameObject root      = new GameObject(Path.GetFileNameWithoutExtension(assetName));
        GameObject meshesObj = new GameObject("Meshes");
        GameObject bonesObj  = new GameObject("Bones");

        meshesObj.transform.parent = root.transform;
        bonesObj.transform.parent  = root.transform;

        // import the skeleton
        Transform[] bones     = new Transform[flver.Bones.Count];
        Matrix4x4[] bindPoses = new Matrix4x4[flver.Bones.Count];
        for (int i = 0; i < flver.Bones.Count; i++)
        {
            var fbone = flver.Bones[i];
            bones[i] = new GameObject(fbone.Name).transform;
            EulerToTransform(new Vector3(fbone.Rotation.X, fbone.Rotation.Y, fbone.Rotation.Z), bones[i]);
            bones[i].localPosition = new Vector3(fbone.Translation.X, fbone.Translation.Y, fbone.Translation.Z);
            bones[i].localScale    = new Vector3(fbone.Scale.X, fbone.Scale.Y, fbone.Scale.Z);
            //SetBoneWorldTransform(bones[i], flver.Bones.ToArray(), i);
            //bindPoses[i] = bones[i].worldToLocalMatrix * root.transform.localToWorldMatrix;
        }

        // Skeleton parenting
        for (int i = 0; i < flver.Bones.Count; i++)
        {
            var fbone = flver.Bones[i];
            if (fbone.ParentIndex == -1)
            {
                //bones[i].parent = root.transform;
                bones[i].SetParent(bonesObj.transform, false);
                bindPoses[i] = bones[i].worldToLocalMatrix * root.transform.localToWorldMatrix;
            }
            else
            {
                //bones[i].parent = bones[fbone.ParentIndex];
                bones[i].SetParent(bones[fbone.ParentIndex], false);
                bindPoses[i] = bones[i].worldToLocalMatrix * root.transform.localToWorldMatrix;
            }
        }

        // Import the meshes
        int index = 0;

        foreach (var m in flver.Meshes)
        {
            var mesh = new Mesh();

            var              verts        = new List <Vector3>();
            var              normals      = new List <Vector3>();
            var              tangents     = new List <Vector4>();
            var              boneweights  = new List <BoneWeight>();
            var              smcount      = 0;
            bool             usestangents = false;
            int              uvcount      = m.Vertices[0].UVs.Count;
            List <Vector2>[] uvs          = new List <Vector2> [uvcount];
            List <Material>  matList      = new List <Material>();

            // Add the mesh to the asset link
            FLVERAssetLink.SubmeshInfo info = new FLVERAssetLink.SubmeshInfo();
            info.Name = flver.Materials[m.MaterialIndex].Name;
            var MTD = AssetDatabase.LoadAssetAtPath <MTDAssetLink>($@"Assets/{gamePath}/MTD/{Path.GetFileNameWithoutExtension(flver.Materials[m.MaterialIndex].MTD)}.asset");
            info.Mtd = MTD;
            assetLink.Submeshes.Add(info);

            int lightmapUVIndex = 1;
            // Use MTD to get lightmap uv index
            if (gameType != DarkSoulsTools.GameType.Sekiro)
            {
                if (MTD != null)
                {
                    lightmapUVIndex = (MTD.LightmapUVIndex != -1) ? MTD.LightmapUVIndex : 1;
                    if (lightmapUVIndex >= uvs.Length)
                    {
                        lightmapUVIndex = 1;
                    }
                }
                else
                {
                    // Do a hardcoded lookup of a material's lightmap UV index from a shitty table :fatcat:
                    if (MaterialLightmapUVIndex.ContainsKey(Path.GetFileNameWithoutExtension(flver.Materials[m.MaterialIndex].MTD)))
                    {
                        lightmapUVIndex = MaterialLightmapUVIndex[Path.GetFileNameWithoutExtension(flver.Materials[m.MaterialIndex].MTD)];
                    }
                }
            }
            for (int i = 0; i < uvs.Length; i++)
            {
                uvs[i] = new List <Vector2>();
            }
            bool isSkinned = false;
            foreach (var v in m.Vertices)
            {
                verts.Add(new Vector3(v.Positions[0].X, v.Positions[0].Y, v.Positions[0].Z));
                normals.Add(new Vector3(v.Normals[0].X, v.Normals[0].Y, v.Normals[0].Z));
                if (v.Tangents.Count > 0)
                {
                    tangents.Add(new Vector4(v.Tangents[0].X, v.Tangents[0].Y, v.Tangents[0].Z, v.Tangents[0].W));
                    usestangents = true;
                }
                else
                {
                    tangents.Add(new Vector4(0, 0, 0, 1));
                }
                for (int i = 0; i < uvs.Length; i++)
                {
                    // Swap lightmap uvs with uv index 1 because lmao unity
                    if (i == 1)
                    {
                        uvs[i].Add(new Vector2(v.UVs[lightmapUVIndex].X, 1.0f - v.UVs[lightmapUVIndex].Y));
                    }
                    else if (i == lightmapUVIndex)
                    {
                        uvs[i].Add(new Vector2(v.UVs[1].X, 1.0f - v.UVs[1].Y));
                    }
                    else
                    {
                        uvs[i].Add(new Vector2(v.UVs[i].X, 1.0f - v.UVs[i].Y));
                    }
                }
                if (v.BoneWeights != null && v.BoneWeights.Count() > 0)
                {
                    isSkinned = true;
                    var weight = new BoneWeight();

                    if (m.Unk1 == 0)
                    {
                        weight.boneIndex0 = v.BoneIndices[0];
                        weight.boneIndex1 = v.BoneIndices[1];
                        weight.boneIndex2 = v.BoneIndices[2];
                        weight.boneIndex3 = v.BoneIndices[3];
                    }
                    else
                    {
                        weight.boneIndex0 = m.BoneIndices[v.BoneIndices[0]];
                        weight.boneIndex1 = m.BoneIndices[v.BoneIndices[1]];
                        weight.boneIndex2 = m.BoneIndices[v.BoneIndices[2]];
                        weight.boneIndex3 = m.BoneIndices[v.BoneIndices[3]];
                    }
                    if (v.BoneWeights[0] < 0.0)
                    {
                        weight.weight0 = 1.0f;
                    }
                    else
                    {
                        weight.weight0 = v.BoneWeights[0];
                    }
                    weight.weight1 = v.BoneWeights[1];
                    weight.weight2 = v.BoneWeights[2];
                    weight.weight3 = v.BoneWeights[3];
                    boneweights.Add(weight);
                }
                else
                {
                    boneweights.Add(new BoneWeight());
                }
            }
            foreach (var fs in m.FaceSets)
            {
                if (fs.Vertices.Count() > 0 && fs.Flags == FLVER.FaceSet.FSFlags.None)
                {
                    matList.Add(materials[m.MaterialIndex]);
                    smcount++;
                }
            }

            mesh.indexFormat  = UnityEngine.Rendering.IndexFormat.UInt32;
            mesh.subMeshCount = smcount;
            mesh.SetVertices(verts);
            mesh.SetNormals(normals);
            if (usestangents)
            {
                mesh.SetTangents(tangents);
            }
            if (isSkinned)
            {
                mesh.boneWeights = boneweights.ToArray();
                mesh.bindposes   = bindPoses;
            }

            for (int i = 0; i < uvs.Length; i++)
            {
                mesh.SetUVs(i, uvs[i]);
            }

            var submesh = 0;
            foreach (var fs in m.FaceSets)
            {
                if (fs.Vertices.Count() == 0)
                {
                    continue;
                }
                if (fs.Flags != FLVER.FaceSet.FSFlags.None)
                {
                    continue;
                }

                mesh.SetTriangles(fs.GetFacesArray(), submesh, true, 0);
                submesh++;
            }
            mesh.RecalculateBounds();

            // Setup a game object asset
            GameObject obj = new GameObject(Path.GetFileNameWithoutExtension(assetName) + $@"_{index}");
            if (isSkinned)
            {
                obj.AddComponent <SkinnedMeshRenderer>();
                obj.GetComponent <SkinnedMeshRenderer>().materials  = matList.ToArray();
                obj.GetComponent <SkinnedMeshRenderer>().bones      = bones;
                obj.GetComponent <SkinnedMeshRenderer>().sharedMesh = mesh;
            }
            else
            {
                obj.AddComponent <MeshRenderer>();
                obj.GetComponent <MeshRenderer>().materials = matList.ToArray();
                obj.AddComponent <MeshFilter>();
                obj.GetComponent <MeshFilter>().mesh = mesh;
            }
            obj.AddComponent <FlverSubmesh>();
            obj.GetComponent <FlverSubmesh>().Link       = assetLink;
            obj.GetComponent <FlverSubmesh>().SubmeshIdx = index;
            obj.transform.parent = meshesObj.transform;

            AssetDatabase.CreateAsset(mesh, assetName + $@"/{Path.GetFileNameWithoutExtension(assetName)}_{index}.mesh");
            index++;
        }

        // If there's no meshes, create an empty one to bind the skeleton to so that Maya works
        // when you export the skeleton (like with c0000).
        if (flver.Meshes.Count == 0)
        {
            var mesh = new Mesh();

            var verts       = new List <Vector3>();
            var normals     = new List <Vector3>();
            var tangents    = new List <Vector4>();
            var boneweights = new List <BoneWeight>();
            for (var i = 0; i < 3; i++)
            {
                verts.Add(new Vector3(0.0f, 0.0f, 0.0f));
                normals.Add(new Vector3(0.0f, 1.0f, 0.0f));
                tangents.Add(new Vector4(1.0f, 0.0f, 0.0f, 1.0f));
                var weight = new BoneWeight();
                weight.boneIndex0 = 0;
                weight.weight0    = 1.0f;
                boneweights.Add(weight);
            }

            mesh.indexFormat  = UnityEngine.Rendering.IndexFormat.UInt32;
            mesh.subMeshCount = 1;
            mesh.SetVertices(verts);
            mesh.SetNormals(normals);
            mesh.SetTangents(tangents);
            mesh.boneWeights = boneweights.ToArray();
            mesh.bindposes   = bindPoses;
            mesh.SetTriangles(new int [] { 0, 1, 2 }, 0);

            GameObject obj = new GameObject(Path.GetFileNameWithoutExtension(assetName) + $@"_{index}");
            obj.AddComponent <SkinnedMeshRenderer>();
            obj.GetComponent <SkinnedMeshRenderer>().bones      = bones;
            obj.GetComponent <SkinnedMeshRenderer>().sharedMesh = mesh;
            obj.transform.parent = meshesObj.transform;

            AssetDatabase.CreateAsset(mesh, assetName + $@"/{Path.GetFileNameWithoutExtension(assetName)}_{index}.mesh");
        }

        root.AddComponent <FlverMesh>();
        root.GetComponent <FlverMesh>().Link = assetLink;

        AssetDatabase.CreateAsset(assetLink, assetName + ".asset");
        AssetDatabase.SaveAssets();
        PrefabUtility.SaveAsPrefabAsset(root, assetName + ".prefab");
        Object.DestroyImmediate(root);
    }