Browse Source

Add menu file utilities

habeebweeb 4 years ago
parent
commit
7312a6eaef
1 changed files with 694 additions and 0 deletions
  1. 694 0
      COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/MenuFileUtility.cs

+ 694 - 0
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/MenuFileUtility.cs

@@ -0,0 +1,694 @@
+using System;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Rendering;
+
+namespace COM3D2.MeidoPhotoStudio.Plugin
+{
+    internal static class MenuFileUtility
+    {
+        private static readonly HashSet<string> accMpn = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase)
+        {
+            "accashi", "acchana", "acchat", "acchead", "accheso", "acckami", "acckamisub", "acckubi", "acckubiwa",
+            "accmimi", "accnip", "accsenaka", "accshippo", "accude", "accxxx", "bra", "glove", "headset", "megane",
+            "mizugi", "onepiece", "panz", "shoes", "skirt", "stkg", "wear",
+        };
+        private enum IMode
+        {
+            None, ItemChange, TexChange
+        }
+        public static event EventHandler MenuFilesReadyChange;
+        public static bool MenuFilesReady { get; private set; } = false;
+
+        static MenuFileUtility()
+        {
+            GameMain.Instance.StartCoroutine(CheckMenuDataBaseJob());
+        }
+
+        private static IEnumerator CheckMenuDataBaseJob()
+        {
+            if (MenuFilesReady) yield break;
+            while (!GameMain.Instance.MenuDataBase.JobFinished()) yield return null;
+            MenuFilesReady = true;
+            MenuFilesReadyChange?.Invoke(null, EventArgs.Empty);
+            yield break;
+        }
+
+        private static bool ProcScriptBin(byte[] menuBuf, ModelInfo modelInfo)
+        {
+            using (BinaryReader binaryReader = new BinaryReader(new MemoryStream(menuBuf), Encoding.UTF8))
+            {
+                string menuHeader = binaryReader.ReadString();
+                NDebug.Assert(
+                    menuHeader == "CM3D2_MENU", "ProcScriptBin 例外 : ヘッダーファイルが不正です。" + menuHeader
+                );
+                binaryReader.ReadInt32(); // file version
+                binaryReader.ReadString(); // txt path
+                binaryReader.ReadString(); // name
+                binaryReader.ReadString(); // category
+                binaryReader.ReadString(); // description
+                binaryReader.ReadInt32(); // idk (as long)
+
+                string menuPropString = String.Empty;
+                string menuPropStringTemp = String.Empty;
+                // string tempString3 = String.Empty;
+                string slotName = String.Empty;
+
+                try
+                {
+                    while (true)
+                    {
+                        int numberOfProps = (int)binaryReader.ReadByte();
+                        menuPropStringTemp = menuPropString;
+                        menuPropString = String.Empty;
+
+                        if (numberOfProps != 0)
+                        {
+                            for (int i = 0; i < numberOfProps; i++)
+                            {
+                                menuPropString = $"{menuPropString}\"{binaryReader.ReadString()}\"";
+                            }
+
+                            if (menuPropString != string.Empty)
+                            {
+                                string header = UTY.GetStringCom(menuPropString);
+                                string[] menuProps = UTY.GetStringList(menuPropString);
+
+                                if (header == "end")
+                                {
+                                    break;
+                                }
+                                else if (header == "マテリアル変更")
+                                {
+                                    int matNo = int.Parse(menuProps[2]);
+                                    string materialFile = menuProps[3];
+                                    modelInfo.MaterialChanges.Add(new MaterialChange(matNo, materialFile));
+                                }
+                                else if (header == "additem")
+                                {
+                                    modelInfo.ModelFile = menuProps[1];
+                                }
+                            }
+                        }
+                        else
+                        {
+                            break;
+                        }
+                    }
+                }
+                catch
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        private static void ProcModScriptBin(byte[] cd, GameObject go)
+        {
+            BinaryReader binaryReader = new BinaryReader(new MemoryStream(cd), Encoding.UTF8);
+            string str1 = binaryReader.ReadString();
+            NDebug.Assert(str1 == "CM3D2_MOD", "ProcModScriptBin 例外 : ヘッダーファイルが不正です。" + str1);
+            binaryReader.ReadInt32();
+            binaryReader.ReadString();
+            binaryReader.ReadString();
+            binaryReader.ReadString();
+            binaryReader.ReadString();
+            binaryReader.ReadString();
+            string mpnValue = binaryReader.ReadString();
+            MPN mpn = MPN.null_mpn;
+            try
+            {
+                mpn = (MPN)Enum.Parse(typeof(MPN), mpnValue);
+            }
+            catch { }
+            if (mpn != MPN.null_mpn)
+            {
+                binaryReader.ReadString();
+            }
+            string s = binaryReader.ReadString();
+            int num2 = binaryReader.ReadInt32();
+            Dictionary<string, byte[]> dictionary = new Dictionary<string, byte[]>();
+            for (int i = 0; i < num2; i++)
+            {
+                string key = binaryReader.ReadString();
+                int count = binaryReader.ReadInt32();
+                byte[] value = binaryReader.ReadBytes(count);
+                dictionary.Add(key, value);
+            }
+            binaryReader.Close();
+
+            using (StringReader stringReader = new StringReader(s))
+            {
+                IMode mode = IMode.None;
+                string slotname = String.Empty;
+                Material material = null;
+                int num3 = 0;
+                string line;
+                bool change = false;
+                while ((line = stringReader.ReadLine()) != null)
+                {
+                    string[] array = line.Split(new[] { '\t', ' ' }, StringSplitOptions.RemoveEmptyEntries);
+
+                    if (array[0] == "アイテム変更" || array[0] == "マテリアル変更")
+                    {
+                        mode = IMode.ItemChange;
+                    }
+                    else if (array[0] == "テクスチャ変更")
+                    {
+                        mode = IMode.TexChange;
+                    }
+                    if (mode == IMode.ItemChange)
+                    {
+                        if (array[0] == "スロット名")
+                        {
+                            slotname = array[1];
+                            change = true;
+                        }
+                        if (change)
+                        {
+                            if (array[0] == "マテリアル番号")
+                            {
+                                num3 = int.Parse(array[1]);
+                                foreach (Transform transform in go.GetComponentsInChildren<Transform>(true))
+                                {
+                                    Renderer component = transform.GetComponent<Renderer>();
+                                    if (component != null && component.materials != null)
+                                    {
+                                        Material[] materials = component.materials;
+                                        for (int k = 0; k < materials.Length; k++)
+                                        {
+                                            if (k == num3)
+                                            {
+                                                material = materials[k];
+                                                break;
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                            if (material != null)
+                            {
+                                if (array[0] == "テクスチャ設定")
+                                {
+                                    ChangeTex(num3, array[1], array[2].ToLower(), dictionary, go);
+                                }
+                                else if (array[0] == "色設定")
+                                {
+                                    material.SetColor(array[1],
+                                        new Color(
+                                            float.Parse(array[2]) / 255f,
+                                            float.Parse(array[3]) / 255f,
+                                            float.Parse(array[4]) / 255f,
+                                            float.Parse(array[5]) / 255f
+                                        )
+                                    );
+                                }
+                                else if (array[0] == "数値設定")
+                                {
+                                    material.SetFloat(array[1], float.Parse(array[2]));
+                                }
+                            }
+                        }
+                    }
+                    else if (mode == IMode.TexChange)
+                    {
+                        int matno = int.Parse(array[2]);
+                        ChangeTex(matno, array[3], array[4].ToLower(), dictionary, go);
+                    }
+                }
+            }
+        }
+
+        private static void ChangeTex(
+            int matno, string prop, string filename, Dictionary<string, byte[]> matDict, GameObject go
+        )
+        {
+            TextureResource textureResource = null;
+            byte[] buf = matDict[filename.ToLowerInvariant()];
+            textureResource = new TextureResource(2, 2, TextureFormat.ARGB32, null, buf);
+            List<Renderer> list = new List<Renderer>(3);
+            go.transform.GetComponentsInChildren<Renderer>(true, list);
+            foreach (Renderer r in list)
+            {
+                if (r != null && r.material != null)
+                {
+                    if (matno < r.materials.Length)
+                    {
+                        r.materials[matno].SetTexture(prop, null);
+                        Texture2D texture2D = textureResource.CreateTexture2D();
+                        texture2D.name = filename;
+                        r.materials[matno].SetTexture(prop, texture2D);
+                    }
+                }
+            }
+        }
+
+        private static GameObject LoadSkinMesh_R(string modelFileName, int layer)
+        {
+            byte[] buffer = null;
+            using (AFileBase afileBase = GameUty.FileOpen(modelFileName, null))
+            {
+                if (afileBase.IsValid() && afileBase.GetSize() != 0)
+                {
+                    buffer = afileBase.ReadAll();
+                }
+                else
+                {
+                    Debug.LogError("invalid model");
+                    return null;
+                }
+            }
+            using (BinaryReader binaryReader = new BinaryReader(new MemoryStream(buffer), Encoding.UTF8))
+            {
+                GameObject gameObject = UnityEngine.Object.Instantiate(Resources.Load("seed")) as GameObject;
+                gameObject.layer = 1;
+                GameObject gameObject2 = null;
+                Hashtable hashtable = new Hashtable();
+                string text = binaryReader.ReadString();
+                if (text != "CM3D2_MESH")
+                {
+                    NDebug.Assert("LoadSkinMesh_R 例外 : ヘッダーファイルが不正です。" + text, false);
+                }
+                int num = binaryReader.ReadInt32();
+                string str = binaryReader.ReadString();
+                gameObject.name = "_SM_" + str;
+                string b = binaryReader.ReadString();
+                int num2 = binaryReader.ReadInt32();
+                List<GameObject> list = new List<GameObject>();
+                for (int i = 0; i < num2; i++)
+                {
+                    GameObject gameObject3 = UnityEngine.Object.Instantiate(Resources.Load("seed")) as GameObject;
+                    gameObject3.layer = layer;
+                    gameObject3.name = binaryReader.ReadString();
+                    list.Add(gameObject3);
+                    if (gameObject3.name == b)
+                    {
+                        gameObject2 = gameObject3;
+                    }
+                    hashtable[gameObject3.name] = gameObject3;
+                    bool flag = binaryReader.ReadByte() != 0;
+                    if (flag)
+                    {
+                        GameObject gameObject4 = UnityEngine.Object.Instantiate(Resources.Load("seed")) as GameObject;
+                        gameObject4.name = gameObject3.name + "_SCL_";
+                        gameObject4.transform.parent = gameObject3.transform;
+                        hashtable[gameObject3.name + "&_SCL_"] = gameObject4;
+                    }
+                }
+                for (int j = 0; j < num2; j++)
+                {
+                    int num3 = binaryReader.ReadInt32();
+                    if (num3 >= 0)
+                    {
+                        list[j].transform.parent = list[num3].transform;
+                    }
+                    else
+                    {
+                        list[j].transform.parent = gameObject.transform;
+                    }
+                }
+                for (int k = 0; k < num2; k++)
+                {
+                    Transform transform = list[k].transform;
+                    float x = binaryReader.ReadSingle();
+                    float y = binaryReader.ReadSingle();
+                    float z = binaryReader.ReadSingle();
+                    transform.localPosition = new Vector3(x, y, z);
+                    float x2 = binaryReader.ReadSingle();
+                    float y2 = binaryReader.ReadSingle();
+                    float z2 = binaryReader.ReadSingle();
+                    float w = binaryReader.ReadSingle();
+                    transform.localRotation = new Quaternion(x2, y2, z2, w);
+                    if (2001 <= num)
+                    {
+                        bool flag2 = binaryReader.ReadBoolean();
+                        if (flag2)
+                        {
+                            float x3 = binaryReader.ReadSingle();
+                            float y3 = binaryReader.ReadSingle();
+                            float z3 = binaryReader.ReadSingle();
+                            transform.localScale = new Vector3(x3, y3, z3);
+                        }
+                    }
+                }
+                int num4 = binaryReader.ReadInt32();
+                int num5 = binaryReader.ReadInt32();
+                int num6 = binaryReader.ReadInt32();
+                SkinnedMeshRenderer skinnedMeshRenderer = gameObject2.AddComponent<SkinnedMeshRenderer>();
+                skinnedMeshRenderer.updateWhenOffscreen = true;
+                skinnedMeshRenderer.skinnedMotionVectors = false;
+                skinnedMeshRenderer.lightProbeUsage = LightProbeUsage.Off;
+                skinnedMeshRenderer.reflectionProbeUsage = ReflectionProbeUsage.Off;
+                skinnedMeshRenderer.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion;
+                Transform[] array2 = new Transform[num6];
+                for (int l = 0; l < num6; l++)
+                {
+                    string text2 = binaryReader.ReadString();
+                    if (!hashtable.ContainsKey(text2))
+                    {
+                        Debug.LogError("nullbone= " + text2);
+                    }
+                    else
+                    {
+                        GameObject gameObject5;
+                        if (hashtable.ContainsKey(text2 + "&_SCL_"))
+                        {
+                            gameObject5 = (GameObject)hashtable[text2 + "&_SCL_"];
+                        }
+                        else
+                        {
+                            gameObject5 = (GameObject)hashtable[text2];
+                        }
+                        array2[l] = gameObject5.transform;
+                    }
+                }
+                skinnedMeshRenderer.bones = array2;
+                Mesh mesh = new Mesh();
+                skinnedMeshRenderer.sharedMesh = mesh;
+                Mesh mesh2 = mesh;
+                // bodyskin.listDEL.Add(mesh2);
+                Matrix4x4[] array4 = new Matrix4x4[num6];
+                for (int m = 0; m < num6; m++)
+                {
+                    for (int n = 0; n < 16; n++)
+                    {
+                        array4[m][n] = binaryReader.ReadSingle();
+                    }
+                }
+                mesh2.bindposes = array4;
+                Vector3[] array5 = new Vector3[num4];
+                Vector3[] array6 = new Vector3[num4];
+                Vector2[] array7 = new Vector2[num4];
+                BoneWeight[] array8 = new BoneWeight[num4];
+                for (int num8 = 0; num8 < num4; num8++)
+                {
+                    float num9 = binaryReader.ReadSingle();
+                    float num10 = binaryReader.ReadSingle();
+                    float new_z = binaryReader.ReadSingle();
+                    array5[num8].Set(num9, num10, new_z);
+                    num9 = binaryReader.ReadSingle();
+                    num10 = binaryReader.ReadSingle();
+                    new_z = binaryReader.ReadSingle();
+                    array6[num8].Set(num9, num10, new_z);
+                    num9 = binaryReader.ReadSingle();
+                    num10 = binaryReader.ReadSingle();
+                    array7[num8].Set(num9, num10);
+                }
+                mesh2.vertices = array5;
+                mesh2.normals = array6;
+                mesh2.uv = array7;
+                int num11 = binaryReader.ReadInt32();
+                if (num11 > 0)
+                {
+                    Vector4[] array9 = new Vector4[num11];
+                    for (int num12 = 0; num12 < num11; num12++)
+                    {
+                        float x4 = binaryReader.ReadSingle();
+                        float y4 = binaryReader.ReadSingle();
+                        float z4 = binaryReader.ReadSingle();
+                        float w2 = binaryReader.ReadSingle();
+                        array9[num12] = new Vector4(x4, y4, z4, w2);
+                    }
+                    mesh2.tangents = array9;
+                }
+                for (int num13 = 0; num13 < num4; num13++)
+                {
+                    array8[num13].boneIndex0 = binaryReader.ReadUInt16();
+                    array8[num13].boneIndex1 = binaryReader.ReadUInt16();
+                    array8[num13].boneIndex2 = binaryReader.ReadUInt16();
+                    array8[num13].boneIndex3 = binaryReader.ReadUInt16();
+                    array8[num13].weight0 = binaryReader.ReadSingle();
+                    array8[num13].weight1 = binaryReader.ReadSingle();
+                    array8[num13].weight2 = binaryReader.ReadSingle();
+                    array8[num13].weight3 = binaryReader.ReadSingle();
+                }
+
+                mesh2.boneWeights = array8;
+                mesh2.subMeshCount = num5;
+                for (int num19 = 0; num19 < num5; num19++)
+                {
+                    int num20 = binaryReader.ReadInt32();
+                    int[] array10 = new int[num20];
+                    for (int num21 = 0; num21 < num20; num21++)
+                    {
+                        array10[num21] = (int)binaryReader.ReadUInt16();
+                    }
+                    mesh2.SetTriangles(array10, num19);
+                }
+                int num22 = binaryReader.ReadInt32();
+                Material[] array11 = new Material[num22];
+                for (int num23 = 0; num23 < num22; num23++)
+                {
+                    Material material = ImportCM.ReadMaterial(binaryReader);
+                    array11[num23] = material;
+                }
+                skinnedMeshRenderer.materials = array11;
+                return gameObject;
+            }
+        }
+
+        public static GameObject LoadModel(string menuFile)
+        {
+            return LoadModel(new ItemData { MenuFile = menuFile });
+        }
+
+        public static GameObject LoadModel(ItemData menuItem)
+        {
+            byte[] menuBuffer = null;
+            byte[] modMenuBuffer = null;
+
+            if (menuItem.IsOfficialMod)
+            {
+                using (FileStream fileStream = new FileStream(menuItem.MenuFile, FileMode.Open))
+                {
+                    if (fileStream == null || fileStream.Length == 0)
+                    {
+                        Debug.LogError("Could not open mod menu");
+                        return null;
+                    }
+                    else
+                    {
+                        modMenuBuffer = new byte[fileStream.Length];
+                        fileStream.Read(modMenuBuffer, 0, (int)fileStream.Length);
+                    }
+                }
+            }
+
+            string menu = menuItem.IsOfficialMod ? menuItem.BaseMenuFile : menuItem.MenuFile;
+
+            using (AFileBase afileBase = GameUty.FileOpen(menu))
+            {
+                if (afileBase == null || !afileBase.IsValid())
+                {
+                    Debug.LogError("Could not open menu");
+                    return null;
+                }
+                else if (afileBase.GetSize() == 0)
+                {
+                    Debug.LogError("Mod menu is empty");
+                    return null;
+                }
+                else
+                {
+                    menuBuffer = afileBase.ReadAll();
+                }
+            }
+
+            ModelInfo modelInfo = new ModelInfo();
+
+            if (ProcScriptBin(menuBuffer, modelInfo))
+            {
+                GameObject gameObject = null;
+
+                try
+                {
+                    gameObject = LoadSkinMesh_R(modelInfo.ModelFile, 1);
+                }
+                catch
+                {
+                    Debug.LogError($"Could not load mesh for '{menuItem.MenuFile}'");
+                }
+
+                if (gameObject != null)
+                {
+                    foreach (MaterialChange matChange in modelInfo.MaterialChanges)
+                    {
+                        foreach (Transform transform in gameObject.transform.GetComponentInChildren<Transform>(true))
+                        {
+                            Renderer renderer = transform.GetComponent<Renderer>();
+                            if (renderer != null && renderer.material != null
+                                && matChange.MaterialIndex < renderer.materials.Length
+                            )
+                            {
+                                renderer.materials[matChange.MaterialIndex] =
+                                    ImportCM.LoadMaterial(matChange.MaterialFile, null);
+                            }
+                        }
+                    }
+
+                    if (menuItem.IsOfficialMod)
+                    {
+                        ProcModScriptBin(modMenuBuffer, gameObject);
+                    }
+                }
+
+                return gameObject;
+            }
+            else
+            {
+                Debug.LogWarning($"Could not parse menu file '{menuItem.MenuFile}'");
+                return null;
+            }
+        }
+
+        public static bool ParseNativeMenuFile(int menuIndex, ItemData menuItem)
+        {
+            MenuDataBase menuDataBase = GameMain.Instance.MenuDataBase;
+            menuDataBase.SetIndex(menuIndex);
+            if (menuDataBase.GetBoDelOnly()) return false;
+            menuItem.Category = menuDataBase.GetCategoryMpnText();
+            if (!accMpn.Contains(menuItem.Category)) return false;
+            menuItem.MenuFile = menuDataBase.GetMenuFileName().ToLower();
+            if (!validBG2MenuFile(menuItem.MenuFile)) return false;
+            menuItem.Name = menuDataBase.GetMenuName();
+            menuItem.IconFile = menuDataBase.GetIconS();
+            menuItem.Priority = (int)menuDataBase.GetPriority();
+            return true;
+        }
+
+        public static bool ParseModMenuFile(string modMenuFile, ItemData menuItem)
+        {
+            if (!validBG2MenuFile(modMenuFile)) return false;
+
+            byte[] buf = null;
+            try
+            {
+                using (FileStream fileStream = new FileStream(modMenuFile, FileMode.Open))
+                {
+                    if (fileStream == null) return false;
+                    if (fileStream.Length == 0L)
+                    {
+                        Debug.LogError($"Mod menu file '{modMenuFile}' is empty");
+                        return false;
+                    }
+                    buf = new byte[fileStream.Length];
+                    fileStream.Read(buf, 0, (int)fileStream.Length);
+                }
+            }
+            catch
+            {
+                Debug.LogError($"Could not read mod menu file '{modMenuFile}'");
+                return false;
+            }
+
+            if (buf == null) return false;
+
+            using (BinaryReader binaryReader = new BinaryReader(new MemoryStream(buf), Encoding.UTF8))
+            {
+                try
+                {
+                    if (binaryReader.ReadString() != "CM3D2_MOD") return false;
+                    else
+                    {
+                        binaryReader.ReadInt32();
+                        string iconName = binaryReader.ReadString();
+                        string baseItemPath = binaryReader.ReadString().Replace(":", " ");
+                        menuItem.BaseMenuFile = Path.GetFileName(baseItemPath);
+                        menuItem.Name = binaryReader.ReadString();
+                        menuItem.Category = binaryReader.ReadString();
+                        if (!accMpn.Contains(menuItem.Category)) return false;
+                        binaryReader.ReadString();
+                        string mpnValue = binaryReader.ReadString();
+                        MPN mpn = MPN.null_mpn;
+                        try
+                        {
+                            mpn = (MPN)Enum.Parse(typeof(MPN), mpnValue, true);
+                        }
+                        catch
+                        {
+                            return false;
+                        }
+                        if (mpn != MPN.null_mpn)
+                        {
+                            binaryReader.ReadString();
+                        }
+                        binaryReader.ReadString();
+                        int size = binaryReader.ReadInt32();
+                        for (int i = 0; i < size; i++)
+                        {
+                            string key = binaryReader.ReadString();
+                            int count = binaryReader.ReadInt32();
+                            byte[] data = binaryReader.ReadBytes(count);
+                            if (string.Equals(key, iconName, StringComparison.InvariantCultureIgnoreCase))
+                            {
+                                Texture2D tex = new Texture2D(1, 1, TextureFormat.RGBA32, false);
+                                tex.LoadImage(data);
+                                menuItem.Icon = tex;
+                                break;
+                            }
+                        }
+                    }
+                }
+                catch
+                {
+                    Debug.LogWarning($"Could not parse mod menu file '{modMenuFile}'");
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        private static bool validBG2MenuFile(string menu)
+        {
+            menu = Path.GetFileNameWithoutExtension(menu).ToLower();
+            return !(menu.EndsWith("_del") || menu.Contains("zurashi") || menu.Contains("mekure")
+                || menu.Contains("porori") || menu.Contains("moza"));
+        }
+
+        public abstract class MenuItem
+        {
+            public string IconFile { get; set; }
+            public Texture2D Icon { get; set; }
+        }
+
+        public class ItemData : MenuItem
+        {
+            public string MenuFile { get; set; }
+            public string BaseMenuFile { get; set; }
+            public string Name { get; set; }
+            public string Category { get; set; }
+            public int Priority { get; set; }
+            public bool IsMod { get; set; }
+            public bool IsOfficialMod { get; set; }
+            public string ModelFile { get; set; }
+        }
+
+        public class CreativeItem : MenuItem
+        {
+            public int ID { get; set; }
+            public string PrefabName { get; set; }
+        }
+
+        private class ModelInfo
+        {
+            public List<MaterialChange> MaterialChanges { get; set; } = new List<MaterialChange>();
+            public string ModelFile { get; set; }
+        }
+
+        private struct MaterialChange
+        {
+            public int MaterialIndex { get; }
+            public string MaterialFile { get; }
+
+            public MaterialChange(int matno, string matf)
+            {
+                this.MaterialIndex = matno;
+                this.MaterialFile = matf;
+            }
+        }
+    }
+}