public static VMTFile LoadMaterial(String MaterialPath)
        {
            //Normalize path before do magic here
            //(Cuz some paths uses different separators or levels... so we normalize paths always)
            String TempPath = NormalizePath(MaterialPath, MaterialsSubFolder, MaterialsExtension[0], false);

            //If material exist in cache, return it
            if (MaterialCache.ContainsKey(TempPath))
            {
                VMTFile VMTCache = MaterialCache[TempPath];

                if (VMTCache.Material == null)
                {
                    VMTCache.CreateMaterial();
                }

                return(VMTCache);
            }
            //Else begin try load & parse material

            String  FileName = TempPath + MaterialsExtension[0];
            VMTFile VMTFile;

            using (Stream vmtStream = OpenFile(FileName))
            {
                //If at least one material was not found, notify about that
                if (vmtStream == null)
                {
                    Debug.LogWarning(FileName + " NOT FOUND!");
                    return(new VMTFile(null, FileName));
                }
                //Else try load & parse material

                try
                {
                    VMTFile = new VMTFile(vmtStream, FileName);

                    if (VMTFile != null)
                    {
                        VMTFile.CreateMaterial();
                    }
                    else
                    {
                        VMTFile = new VMTFile(null, FileName);
                    }
                }
                catch (Exception ex)
                {
                    //notify about error
                    Debug.LogError(String.Format("{0}: {1}", TempPath, ex.Message));
                    return(new VMTFile(null, FileName));
                }
            }

            //Add material to cache (to load faster than reparse material again, again and again...)
            MaterialCache.Add(TempPath, VMTFile);
            return(VMTFile);
        }
Exemple #2
0
        public Transform BuildModel(Boolean GenerateUV2 = false)
        {
            GameObject ModelObject = new GameObject(MDL_Header.Name);

            #region Bones
            Transform[] Bones = new Transform[MDL_Header.bone_count];
            Dictionary <Int32, String> bonePathDict = new Dictionary <Int32, String>();
            for (Int32 boneID = 0; boneID < MDL_Header.bone_count; boneID++)
            {
                GameObject BoneObject = new GameObject(MDL_BoneNames[boneID]);

                Bones[boneID] = BoneObject.transform;//MDL_Bones.Add(BoneObject.transform);

                Vector3 pos = MDL_StudioBones[boneID].pos * uLoader.UnitScale;
                Vector3 rot = MDL_StudioBones[boneID].rot * Mathf.Rad2Deg;

                //Invert x for convert right-handed to left-handed
                pos.x = -pos.x;

                if (MDL_StudioBones[boneID].parent >= 0)
                {
                    Bones[boneID].parent = Bones[MDL_StudioBones[boneID].parent];
                }
                else
                {
                    //Swap Z & Y and invert Y (ex: X Z -Y)
                    //only for parents, cuz parents used different order vectors
                    float temp = pos.y;
                    pos.y = pos.z;
                    pos.z = -temp;

                    Bones[boneID].parent = ModelObject.transform;
                }

                bonePathDict.Add(boneID, Bones[boneID].GetTransformPath(ModelObject.transform));

                Bones[boneID].localPosition = pos;
                //Bones[i].localRotation = MDL_StudioBones[i].quat;

                if (MDL_StudioBones[boneID].parent == -1)
                {
                    //Fix up parents
                    Bones[boneID].localRotation = Quaternion.Euler(-90, 90, -90) * MathLibrary.AngleQuaternion(rot);
                }
                else
                {
                    Bones[boneID].localRotation = MathLibrary.AngleQuaternion(rot);
                }
            }

            if (uLoader.DrawArmature)
            {
                MDLArmatureInfo DebugArmature = ModelObject.AddComponent <MDLArmatureInfo>();
                DebugArmature.boneNodes = Bones;
            }
            #endregion

            #region Hitboxes
            if (MDL_Hitboxsets != null)
            {
                for (Int32 HitboxsetID = 0; HitboxsetID < MDL_Header.hitbox_count; HitboxsetID++)
                {
                    for (Int32 HitboxID = 0; HitboxID < MDL_Hitboxsets[HitboxsetID].numhitboxes; HitboxID++)
                    {
                        mstudiobbox_t Hitbox = Hitboxes[HitboxsetID][HitboxID].BBox;
                        BoxCollider   BBox   = new GameObject(String.Format("Hitbox_{0}", Bones[Hitbox.bone].name)).AddComponent <BoxCollider>();

                        BBox.size   = MathLibrary.NegateX(Hitbox.bbmax - Hitbox.bbmin) * uLoader.UnitScale;
                        BBox.center = (MathLibrary.NegateX(Hitbox.bbmax + Hitbox.bbmin) / 2) * uLoader.UnitScale;

                        BBox.transform.parent        = Bones[Hitbox.bone];
                        BBox.transform.localPosition = Vector3.zero;
                        BBox.transform.localRotation = Quaternion.identity;

                        //bbox.transform.tag = HitTagType(MDL_BBoxes[i].group);
                    }
                }
            }
            #endregion

            #region BodyParts
            if (BuildMesh)
            {
                for (Int32 BodypartID = 0; BodypartID < MDL_Header.bodypart_count; BodypartID++)
                {
                    StudioBodyPart BodyPart = MDL_Bodyparts[BodypartID];

                    for (Int32 ModelID = 0; ModelID < BodyPart.Models.Length; ModelID++)
                    {
                        StudioModel Model = BodyPart.Models[ModelID];

                        //Skip if model is blank
                        if (Model.isBlank)
                        {
                            continue;
                        }

                        #region TODO: Remove this code after find way to strip unused vertexes for lod's (VTXStripGroup / VTXStrip)
                        mstudiovertex_t[] Vertexes = Model.VerticesPerLod[0];

                        BoneWeight[] BoneWeight = new BoneWeight[Vertexes.Length];
                        Vector3[]    Vertices   = new Vector3[Vertexes.Length];
                        Vector3[]    Normals    = new Vector3[Vertexes.Length];
                        Vector2[]    UvBuffer   = new Vector2[Vertexes.Length];

                        for (Int32 i = 0; i < Vertexes.Length; i++)
                        {
                            Vertices[i] = MathLibrary.SwapZY(Vertexes[i].m_vecPosition * uLoader.UnitScale);
                            Normals[i]  = MathLibrary.SwapZY(Vertexes[i].m_vecNormal);

                            Vector2 UV = Vertexes[i].m_vecTexCoord;
                            if (uLoader.SaveAssetsToUnity && uLoader.ExportTextureAsPNG)
                            {
                                UV.y = -UV.y;
                            }

                            UvBuffer[i]   = UV;
                            BoneWeight[i] = GetBoneWeight(Vertexes[i].m_BoneWeights);
                        }
                        #endregion

                        #region LOD Support
                        Boolean DetailModeEnabled =
                            uLoader.DetailMode == DetailMode.Lowest ||
                            uLoader.DetailMode == DetailMode.Low ||
                            uLoader.DetailMode == DetailMode.Medium ||
                            uLoader.DetailMode == DetailMode.High;

                        Boolean   LODExist       = uLoader.EnableLODParsing && !DetailModeEnabled && Model.NumLODs > 1;
                        Transform FirstLODObject = null;
                        LODGroup  LODGroup       = null;
                        LOD[]     LODs           = null;
                        Single    MaxSwitchPoint = 100;
                        Int32     StartLODIndex  = 0;

                        if (LODExist)
                        {
                            LODs = new LOD[Model.NumLODs];

                            for (Int32 LODID = 1; LODID < 3; LODID++)
                            {
                                Int32            LastID = Model.NumLODs - LODID;
                                ModelLODHeader_t LOD    = Model.LODData[LastID];

                                //ignore $shadowlod
                                if (LOD.switchPoint != -1)
                                {
                                    if (LOD.switchPoint > 0)
                                    {
                                        MaxSwitchPoint = LOD.switchPoint;
                                    }

                                    //Set switchPoint from MaxSwitchPoint (if switchPoint is zero or negative)
                                    if (LODID == 2 || LOD.switchPoint == 0)
                                    {
                                        MaxSwitchPoint += MaxSwitchPoint * uLoader.NegativeAddLODPrecent;
                                        Model.LODData[LOD.switchPoint == 0 ? LastID : LastID + 1].switchPoint = MaxSwitchPoint;
                                    }

                                    // + Threshold used to avoid errors with LODGroup
                                    MaxSwitchPoint += uLoader.ThresholdMaxSwitch;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            if (!uLoader.EnableLODParsing)
                            {
                                Model.NumLODs = 1;
                            }
                        }

                        if (uLoader.EnableLODParsing && DetailModeEnabled)
                        {
                            StartLODIndex =
                                uLoader.DetailMode == DetailMode.Lowest ? (Model.NumLODs - 1) :
                                uLoader.DetailMode == DetailMode.Low ? (Int32)(Model.NumLODs / 1.5f) :
                                uLoader.DetailMode == DetailMode.Medium ? (Model.NumLODs / 2) : (Int32)(Model.NumLODs / 2.5f);
                        }
                        #endregion

                        #region Build Meshes
                        for (Int32 LODID = StartLODIndex; LODID < Model.NumLODs; LODID++)
                        {
                            #region TODO: Uncomment after find way to strip unused vertexes for lod's (VTXStripGroup / VTXStrip)

                            /*mstudiovertex_t[] Vertexes = Model.VerticesPerLod[LODID];
                             *
                             * BoneWeight[] BoneWeight = new BoneWeight[Vertexes.Length];
                             * Vector3[] Vertices = new Vector3[Vertexes.Length];
                             * Vector3[] Normals = new Vector3[Vertexes.Length];
                             * Vector2[] UvBuffer = new Vector2[Vertexes.Length];
                             *
                             * for (Int32 i = 0; i < Vertexes.Length; i++)
                             * {
                             *  Vertices[i] = MathLibrary.SwapZY(Vertexes[i].m_vecPosition * uLoader.UnitScale);
                             *  Normals[i] = MathLibrary.SwapZY(Vertexes[i].m_vecNormal);
                             *
                             *  Vector2 UV = Vertexes[i].m_vecTexCoord;
                             *  if (uLoader.SaveAssetsToUnity && uLoader.ExportTextureAsPNG)
                             *      UV.y = -UV.y;
                             *
                             *  UvBuffer[i] = UV;
                             *  BoneWeight[i] = GetBoneWeight(Vertexes[i].m_BoneWeights);
                             * }*/
                            #endregion

                            #region LOD
                            ModelLODHeader_t ModelLOD = Model.LODData[LODID];

                            if (LODExist)
                            {
                                if (ModelLOD.switchPoint == 0)
                                {
                                    ModelLOD.switchPoint = MaxSwitchPoint;
                                }
                                else
                                {
                                    ModelLOD.switchPoint = MaxSwitchPoint - ModelLOD.switchPoint;
                                }

                                ModelLOD.switchPoint -= ModelLOD.switchPoint * uLoader.SubstractLODPrecent;
                            }
                            #endregion

                            #region Mesh
                            //Create empty object for mesh
                            GameObject MeshObject = new GameObject(Model.Model.Name);
                            MeshObject.name            += "_vLOD" + LODID;
                            MeshObject.transform.parent = ModelObject.transform;

                            //Create empty mesh and fill parsed data
                            Mesh Mesh = new Mesh();
                            Mesh.name = MeshObject.name;

                            Mesh.subMeshCount = Model.Model.nummeshes;
                            Mesh.vertices     = Vertices;
                            //Make sure if mesh exist any vertexes
                            if (Mesh.vertexCount <= 0)
                            {
                                Debug.LogWarning(String.Format("Mesh: \"{0}\" has no vertexes, skip building... (MDL Version: {1})", Mesh.name, MDL_Header.version));
                                continue;
                            }

                            Mesh.normals = Normals;
                            Mesh.uv      = UvBuffer;
                            #endregion

                            #region Renderers
                            Renderer Renderer;
                            //SkinnedMeshRenderer (Models with "animated" bones & skin data)
                            if (!MDL_Header.flags.HasFlag(StudioHDRFlags.STUDIOHDR_FLAGS_STATIC_PROP))
                            {
                                //Bind poses & bone weights
                                SkinnedMeshRenderer SkinnedRenderer = MeshObject.AddComponent <SkinnedMeshRenderer>();
                                Renderer = SkinnedRenderer;
                                Matrix4x4[] BindPoses = new Matrix4x4[Bones.Length];

                                for (Int32 i = 0; i < BindPoses.Length; i++)
                                {
                                    BindPoses[i] = Bones[i].worldToLocalMatrix * MeshObject.transform.localToWorldMatrix;
                                }

                                Mesh.boneWeights = BoneWeight;
                                Mesh.bindposes   = BindPoses;

                                SkinnedRenderer.sharedMesh = Mesh;

                                SkinnedRenderer.bones = Bones;
                                SkinnedRenderer.updateWhenOffscreen = true;
                            }
                            //MeshRenderer (models with "STUDIOHDR_FLAGS_STATIC_PROP" flag or with generic "static_prop" bone)
                            else
                            {
                                MeshFilter MeshFilter = MeshObject.AddComponent <MeshFilter>();
                                Renderer = MeshObject.AddComponent <MeshRenderer>();
                                MeshFilter.sharedMesh = Mesh;
                            }

                            Renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.TwoSided;
                            #endregion

                            #region Debug Stuff
                            #if UNITY_EDITOR
                            DebugMaterial DebugMat = null;
                            if (uLoader.DebugMaterials)
                            {
                                DebugMat = MeshObject.AddComponent <DebugMaterial>();
                            }
                            #endif
                            #endregion

                            #region Triangles and Materials
                            Material[] Materials = new Material[Mesh.subMeshCount];

                            for (Int32 MeshID = 0; MeshID < Model.Model.nummeshes; MeshID++)
                            {
                                //Set triangles per lod & submeshes
                                Mesh.SetTriangles(Model.IndicesPerLod[LODID][MeshID], MeshID);

                                //Find & parse materials
                                String MaterialPath;
                                Int32  LastDirID = MDL_TDirectories.Length - 1;
                                for (Int32 DirID = 0; DirID < MDL_TDirectories.Length; DirID++)
                                {
                                    MaterialPath = MDL_TDirectories[DirID] + MDL_Textures[Model.Meshes[MeshID].material];

                                    //If material exist
                                    if (uResourceManager.ContainsFile(MaterialPath, uResourceManager.MaterialsSubFolder, uResourceManager.MaterialsExtension[0]))
                                    {
                                        VMTFile VMT = uResourceManager.LoadMaterial(MaterialPath);

                                        #region Debug Stuff
                                        #if UNITY_EDITOR
                                        if (uLoader.DebugMaterials)
                                        {
                                            DebugMat.Init(VMT);
                                        }
                                        #endif
                                        #endregion

                                        //Set material
                                        Materials[MeshID] = VMT.Material;
                                        break;
                                    }
                                    else if (DirID == LastDirID)
                                    {
                                        Materials[MeshID] = uResourceManager.LoadMaterial(String.Empty).Material;
                                    }
                                }
                            }

                            Renderer.sharedMaterials = Materials;
                            #endregion

                            #region UV2
                            #if UNITY_EDITOR
                            if (GenerateUV2)
                            {
                                UnityEditor.SerializedObject so = new UnityEditor.SerializedObject(Renderer);
                                so.FindProperty("m_ScaleInLightmap").floatValue = uLoader.ModelsLightmapSize;
                                so.ApplyModifiedProperties();

                                MeshObject.isStatic = GenerateUV2;
                                uResourceManager.UV2GenerateCache.Add(Mesh);
                            }
                            #endif
                            #endregion

                            #region Set LOD's
                            if (LODExist)
                            {
                                if (LODID == 0)
                                {
                                    LODGroup       = MeshObject.AddComponent <LODGroup>();
                                    FirstLODObject = MeshObject.transform;
                                }
                                else if (FirstLODObject != null)
                                {
                                    MeshObject.transform.parent = FirstLODObject;
                                }

                                LODs[LODID] = new LOD(ModelLOD.switchPoint / MaxSwitchPoint, new Renderer[] { Renderer });
                            }

                            if (uLoader.EnableLODParsing && DetailModeEnabled)
                            {
                                break;
                            }
                            #endregion
                        }//lod's per model

                        //Init all parsed lod's into LODGroup
                        if (LODGroup != null)
                        {
                            LODGroup.SetLODs(LODs);
                        }
                        #endregion
                    } //models in bodypart
                }     //Bodypart
            }
            #endregion

            #region Animations
            if (MDL_SeqDescriptions != null)
            {
                var AnimationComponent = ModelObject.AddComponent <Animation>();
                for (Int32 seqID = 0; seqID < MDL_SeqDescriptions.Length; seqID++)
                {
                    SeqInfo Sequence  = Sequences[seqID];
                    AniInfo Animation = Sequence.ani;

                    //Creating "AnimationCurve" for animation "paths" (aka frames where stored position (XYZ) & rotation (XYZW))
                    AnimationCurve[] posX = new AnimationCurve[MDL_Header.bone_count];    //X
                    AnimationCurve[] posY = new AnimationCurve[MDL_Header.bone_count];    //Y
                    AnimationCurve[] posZ = new AnimationCurve[MDL_Header.bone_count];    //Z

                    AnimationCurve[] rotX = new AnimationCurve[MDL_Header.bone_count];    //X
                    AnimationCurve[] rotY = new AnimationCurve[MDL_Header.bone_count];    //Y
                    AnimationCurve[] rotZ = new AnimationCurve[MDL_Header.bone_count];    //Z
                    AnimationCurve[] rotW = new AnimationCurve[MDL_Header.bone_count];    //W

                    //Fill "AnimationCurve" arrays
                    for (Int32 boneIndex = 0; boneIndex < MDL_Header.bone_count; boneIndex++)
                    {
                        posX[boneIndex] = new AnimationCurve();
                        posY[boneIndex] = new AnimationCurve();
                        posZ[boneIndex] = new AnimationCurve();

                        rotX[boneIndex] = new AnimationCurve();
                        rotY[boneIndex] = new AnimationCurve();
                        rotZ[boneIndex] = new AnimationCurve();
                        rotW[boneIndex] = new AnimationCurve();
                    }

                    Int32 numFrames = Animation.studioAnim.numframes;

                    //Used to avoid "Assertion failed" key count in Unity (if frames less than 2)
                    if (numFrames < 2)
                    {
                        numFrames += 1;
                    }

                    //Create animation clip
                    AnimationClip clip = new AnimationClip();
                    //Make it for legacy animation system (for now, but it possible to rework for Mecanim)
                    clip.legacy = true;
                    //Set animation clip name
                    clip.name = Animation.name;

                    //To avoid problems with "obfuscators" / "protectors" for models, make sure if model have name in sequence
                    if (String.IsNullOrEmpty(clip.name))
                    {
                        clip.name = "(empty)" + seqID;
                    }

                    for (Int32 frameIndex = 0; frameIndex < numFrames; frameIndex++)
                    {
                        //Get current frame from blend (meaning from "Animation") by index
                        //AnimationFrame frame = Animation.Frames[frameIndex];

                        //Set keys (position / rotation) from current frame
                        for (Int32 boneIndex = 0; boneIndex < Bones.Length; boneIndex++)
                        {
                            posX[boneIndex].AddKey(Animation.PosX[frameIndex][boneIndex]);
                            posY[boneIndex].AddKey(Animation.PosY[frameIndex][boneIndex]);
                            posZ[boneIndex].AddKey(Animation.PosZ[frameIndex][boneIndex]);

                            rotX[boneIndex].AddKey(Animation.RotX[frameIndex][boneIndex]);
                            rotY[boneIndex].AddKey(Animation.RotY[frameIndex][boneIndex]);
                            rotZ[boneIndex].AddKey(Animation.RotZ[frameIndex][boneIndex]);
                            rotW[boneIndex].AddKey(Animation.RotW[frameIndex][boneIndex]);

                            //Set default pose from the first animation
                            if (seqID == 0 && frameIndex == 0)
                            {
                                Bones[boneIndex].localPosition = new Vector3
                                                                 (
                                    Animation.PosX[0][boneIndex].value,
                                    Animation.PosY[0][boneIndex].value,
                                    Animation.PosZ[0][boneIndex].value
                                                                 );

                                Bones[boneIndex].localRotation = new Quaternion
                                                                 (
                                    Animation.RotX[0][boneIndex].value,
                                    Animation.RotY[0][boneIndex].value,
                                    Animation.RotZ[0][boneIndex].value,
                                    Animation.RotW[0][boneIndex].value
                                                                 );
                            }
                        }
                    }

                    //Apply animation paths (Position / Rotation) to clip
                    for (Int32 boneIndex = 0; boneIndex < MDL_Header.bone_count; boneIndex++)
                    {
                        clip.SetCurve(bonePathDict[boneIndex], typeof(Transform), "localPosition.x", posX[boneIndex]);
                        clip.SetCurve(bonePathDict[boneIndex], typeof(Transform), "localPosition.y", posY[boneIndex]);
                        clip.SetCurve(bonePathDict[boneIndex], typeof(Transform), "localPosition.z", posZ[boneIndex]);

                        clip.SetCurve(bonePathDict[boneIndex], typeof(Transform), "localRotation.x", rotX[boneIndex]);
                        clip.SetCurve(bonePathDict[boneIndex], typeof(Transform), "localRotation.y", rotY[boneIndex]);
                        clip.SetCurve(bonePathDict[boneIndex], typeof(Transform), "localRotation.z", rotZ[boneIndex]);
                        clip.SetCurve(bonePathDict[boneIndex], typeof(Transform), "localRotation.w", rotW[boneIndex]);
                    }

                    if (Animation.studioAnim.fps > 0.0f)
                    {
                        clip.frameRate = Animation.studioAnim.fps;
                    }

                    //This ensures a smooth interpolation (corrects the problem of "jitter" after 180~270 degrees rotation path)
                    //can be "comment" if have idea how to replace this
                    clip.EnsureQuaternionContinuity();
                    AnimationComponent.AddClip(clip, clip.name);
                }
            }
            #endregion

            //If model has compiled flag "$staticprop"
            //then rotate this model by 90 degrees (Y)
            //https://github.com/ValveSoftware/source-sdk-2013/blob/master/sp/src/public/studio.h#L1965
            //Big thanks for this tip:
            //ShadelessFox
            //REDxEYE
            if (MDL_Header.flags.HasFlag(StudioHDRFlags.STUDIOHDR_FLAGS_STATIC_PROP))
            {
                ModelObject.transform.eulerAngles = new Vector3(0, 90, 0);
            }

            return(ModelObject.transform);
        }
Exemple #3
0
        public static VMTFile ParseVMTFile(string name)
        {
            VMTFile material = new VMTFile();

            string path = "";

            if (name.StartsWith("/"))
            {
                name = name.Replace("/", "");
            }

            if (name.Contains("materials/"))
            {
                name = name.Replace("materials/", "");
            }

            if (name.Contains(".vmt"))
            {
                name = name.Replace(".vmt", "");
            }

            path = ResourceManager.GetPath("materials/" + name + ".vmt");

            if (path == null)
            {
                Debug.Log("materials/" + name + ".vmt: Not Found");
                return(null);
            }


            string[] file  = File.ReadAllLines(path);
            string[] temp  = null;
            string   line  = null;
            int      depth = 0;
            Dictionary <string, string> parameters = new Dictionary <string, string> ();
            string block = null;

            for (int i = 0; i < file.Length; i++)
            {
                line = file[i].Trim().Trim('\t');

                if (string.IsNullOrEmpty(line) || line.StartsWith("//"))
                {
                    continue;
                }

                if (line.StartsWith("{"))
                {
                    depth++;
                    continue;
                }

                if (depth == 0)
                {
                    material.shader = line.Trim('"').ToLower();
                }
                else if (depth == 1)
                {
                    if (line.StartsWith("}"))
                    {
                        depth--;
                        if (depth == 0)
                        {
                            break;
                        }
                    }
                    else
                    {
                        if (line.Split(new char[] { ' ', '\t' }).Length < 2)
                        {
                            block = line.Trim('"').ToLower();
                            //Debug.Log("Start block "+block);
                            //Debug.Log ("Line is short "+line);
                        }
                        else
                        {
                            temp = line.Trim().Split(new char[] { ' ', '\t' }, 2);
                            if (temp.Length < 2)
                            {
                                Debug.Log(path + " " + line);
                            }
                            if (!parameters.ContainsKey(temp[0].Trim('"').ToLower()))
                            {
                                parameters.Add(temp[0].Trim('"').ToLower(), temp[1].Trim().Trim('"'));
                            }
                        }
                    }
                }
                else if (depth == 2)
                {
                    if (line.StartsWith("}"))
                    {
                        depth--;
                        if (depth == 0)
                        {
                            break;
                        }
                    }
                    else
                    {
                        if (line.Split(new char[] { ' ', '\t' }).Length < 2)
                        {
                            //Debug.Log ("Line is short "+line);
                        }
                        else
                        {
                            if (block == "insert")
                            {
                                temp = line.Trim().Split(new char[] { ' ', '\t' }, 2);
                                if (temp.Length < 2)
                                {
                                    Debug.Log(path + " " + line);
                                }

                                if (!parameters.ContainsKey(temp[0].Trim('"').ToLower()))
                                {
                                    parameters.Add(temp[0].Trim('"').ToLower(), temp[1].Trim().Trim('"'));
                                }
                                else
                                {
                                    parameters[temp[0].Trim('"').ToLower()] = temp[1].Trim().Trim('"');
                                }
                            }
                        }
                    }
                }

                if (line.StartsWith("}"))
                {
                    depth--;
                    if (depth == 0)
                    {
                        break;
                    }
                }
            }

            if (material.shader == "patch")
            {
                if (parameters.ContainsKey("include"))
                {
                    //Debug.Log (name+ " include "+parameters["include"].ToLower()); debug
                    material = ParseVMTFile(parameters["include"].ToLower());
                    //return ParseVMTFile(parameters["include"].ToLower());

                    if (material == null)
                    {
                        Debug.LogError("Include \"" + parameters["include"].ToLower() + "\" from material \"" + name + "\" missing");
                        return(null);
                    }
                }
                else
                {
                    Debug.LogWarning("Shader is patch but has no parameter include " + path);
                    for (int i = 0; i < parameters.Keys.ToArray().Length; i++)
                    {
                        Debug.Log(parameters.Keys.ToArray()[i]);
                    }
                    return(null);
                }
            }

            /*if (parameters.ContainsKey("$basetexturetransform"))
             * {
             *      //file[file.FindIndex (n => n.ToLower ().Contains ("$basetexturetransform"))]="";
             * }*/

            if (parameters.ContainsKey("$basetexture"))
            {
                material.basetexture = parameters["$basetexture"];
            }
            else
            {
                //if(material.shader!="patch")
                //	Debug.Log ("File "+name+".vmt with shader"+material.shader+" dont contains texture name");
                if (parameters.ContainsKey("%tooltexture"))
                {
                    //Debug.Log ("Split strings count: "+temp.Length);
                    material.basetexture = parameters["%tooltexture"];
                }
                else if (parameters.ContainsKey("$iris"))
                {
                    material.basetexture = parameters["$iris"];
                }
                //else
                //	material.basetexture = null;
            }

            if (parameters.ContainsKey("$basetexture2"))
            {
                material.basetexture2 = parameters["$basetexture2"];
            }

            if (parameters.ContainsKey("$bumpmap"))
            {
                material.dudvmap = parameters["$bumpmap"];
            }

            if (parameters.ContainsKey("$surfaceprop"))
            {
                material.surfaceprop = parameters["$surfaceprop"];
            }

            if (parameters.ContainsKey("alphatest"))
            {
                if (parameters["alphatest"] == "1")
                {
                    material.alphatest = true;
                }
            }

            if (parameters.ContainsKey("$alphatest"))
            {
                if (parameters["$alphatest"] == "1")
                {
                    material.alphatest = true;
                }
            }

            if (parameters.ContainsKey("$selfillum"))
            {
                if (parameters["$selfillum"] == "1")
                {
                    material.selfillum = true;
                }
            }

            if (parameters.ContainsKey("$translucent"))
            {
                if (parameters["$translucent"] == "1")
                {
                    material.translucent = true;
                }
            }

            if (parameters.ContainsKey("$additive"))
            {
                if (parameters["$additive"] == "1")
                {
                    material.additive = true;
                }
            }

            if (parameters.ContainsKey("$dudvmap"))
            {
                material.dudvmap = parameters["$dudvmap"];
            }

            if (parameters.ContainsKey("$normalmap"))
            {
                material.dudvmap = parameters["$normalmap"];
            }

            return(material);
        }
Exemple #4
0
        public static void Configure(this Transform transform, List <String> Data)
        {
            //return;
            String Classname = Data[Data.FindIndex(n => n == "classname") + 1], Targetname = Data[Data.FindIndex(n => n == "targetname") + 1];

            transform.name = Classname;

            //ResourceManager.LoadModel("editor/axis_helper").SetParent(transform, false);

            Int32 OriginIndex = Data.FindIndex(n => n == "origin");

            if (OriginIndex != -1)
            {
                //Old but gold
                String[] origin = Data[OriginIndex + 1].Split(' ');

                while (origin.Length != 3)
                {
                    Int32 TempIndex = OriginIndex + 1;
                    origin = Data[Data.FindIndex(TempIndex, n => n == "origin") + 1].Split(' ');
                }
                //Old but gold

                transform.position = new Vector3(-origin[1].ToSingle(), origin[2].ToSingle(), origin[0].ToSingle()) * uLoader.UnitScale;
            }

            Int32 AnglesIndex = Data.FindIndex(n => n == "angles");

            if (AnglesIndex != -1)
            {
                Vector3 EulerAngles = Data[AnglesIndex + 1].ToVector3();

                EulerAngles = new Vector3(EulerAngles.x, -EulerAngles.y, -EulerAngles.z);

                if (Classname.StartsWith("light", StringComparison.Ordinal))
                {
                    EulerAngles.x = -EulerAngles.x;
                }

                Int32 PitchIndex = Data.FindIndex(n => n == "pitch");
                //Lights
                if (PitchIndex != -1)
                {
                    EulerAngles.x = -Data[PitchIndex + 1].ToSingle();
                }

                transform.eulerAngles = EulerAngles;
            }

            if (Classname.Contains("trigger"))
            {
                for (Int32 i = 0; i < transform.childCount; i++)
                {
                    GameObject Child = transform.GetChild(i).gameObject;
                    Child.SetActive(false);
                    Child.AddComponent <BoxCollider>().isTrigger = true;
                }
            }

#if UNITY_EDITOR
            if (Classname.Equals("env_sprite"))
            {
                //TODO: fix scale
                LensFlare lensFlare = transform.gameObject.AddComponent <LensFlare>();

                if (VBSPFile.GlowFlare == null)
                {
                    String path = UnityEditor.AssetDatabase.GUIDToAssetPath(UnityEditor.AssetDatabase.FindAssets("Glow t:Flare")[0]);
                    VBSPFile.GlowFlare = UnityEditor.AssetDatabase.LoadAssetAtPath <Flare>(path);
                }

                lensFlare.flare      = VBSPFile.GlowFlare;
                lensFlare.brightness = Data[Data.FindIndex(n => n == "scale") + 1].ToSingle();
                lensFlare.fadeSpeed  = Data[Data.FindIndex(n => n == "GlowProxySize") + 1].ToSingle();
                lensFlare.color      = Data[Data.FindIndex(n => n == "rendercolor") + 1].ToColor32();

                return;
            }
#endif

            /*if (Classname.Equals("point_viewcontrol"))
             * {
             *  transform.gameObject.AddComponent<point_viewcontrol>().Start();
             * }*/

            //3D Skybox
            if (uLoader.Use3DSkybox && Classname.Equals("sky_camera"))
            {
                //Setup 3DSkybox
                Camera playerCamera = new GameObject("CameraPlayer").AddComponent <Camera>();
                Camera skyCamera    = transform.gameObject.AddComponent <Camera>();

                CameraFly camFly = playerCamera.gameObject.AddComponent <CameraFly>();
                camFly.skyScale    = Data[Data.FindIndex(n => n == "scale") + 1].ToSingle();
                camFly.offset3DSky = transform.position;
                camFly.skyCamera   = skyCamera.transform;

                playerCamera.depth      = -1;
                playerCamera.clearFlags = CameraClearFlags.Depth;

                skyCamera.depth      = -2;
                skyCamera.clearFlags = CameraClearFlags.Skybox;
                //Setup 3DSkybox
                return;
            }
            //3D Skybox

            //Lights

            //shadow_control used to change parameters of dynamic shadows on the map: direction, color, length.
            if (Classname.Equals("shadow_control"))
            {
                //It can be integrated for Unity?
                //String[] color = Data[Data.FindIndex(n => n == "color") + 1].Split(' ');
                //RenderSettings.subtractiveShadowColor = new Color32(Byte.Parse(color[0]), Byte.Parse(color[1]), Byte.Parse(color[2]), 255);
                RenderSettings.ambientGroundColor = Data[Data.FindIndex(n => n == "color") + 1].ToColor();

                //Set light direction by shadow_control
                if (VBSPFile.LightEnvironment != null)
                {
                    if ((VBSPFile.LightEnvironment.rotation == Quaternion.identity) && !uLoader.IgnoreShadowControl)
                    {
                        VBSPFile.LightEnvironment.rotation = transform.rotation;
                    }

                    UpdateEquatorColor();
                }

                return;
            }

            //Lights parsing
            if (!uLoader.UseWorldLights && Classname.Contains("light") && !Classname.StartsWith("point"))
            {
                Color ambientLight;
                if (Classname.Equals("light_environment"))
                {
                    if (VBSPFile.LightEnvironment != null)
                    {
                        return;
                    }

                    VBSPFile.LightEnvironment = transform;

                    //TODO: Correct parse ambient color
                    String _ambient = Data[Data.FindIndex(n => n == "_ambient") + 1];
                    ambientLight = _ambient.ToColor();
                    RenderSettings.ambientLight = ambientLight;

                    //Set light direction by shadow_control
                    if (VBSPFile.ShadowControl != null)
                    {
                        if (!uLoader.IgnoreShadowControl && transform.rotation == Quaternion.identity)
                        {
                            transform.rotation = VBSPFile.ShadowControl.rotation;
                        }

                        UpdateEquatorColor();
                    }
                }

                if (uLoader.ParseLights)
                {
                    Light Light = transform.gameObject.AddComponent <Light>();

                    if (Classname.Equals("light_spot"))
                    {
                        Light.type = LightType.Spot;
                    }
                    else if (Classname.Equals("light_environment"))
                    {
                        Light.type = LightType.Directional;
                    }

                    Vector4 _lightColor    = Data[Data.FindIndex(n => n == "_light") + 1].ToColorVec();
                    Single  intensity      = _lightColor.w;
                    Single  m_Attenuation0 = 0;
                    Single  m_Attenuation1 = 0;
                    Single  m_Attenuation2 = 0;

                    Light.color = new Color(_lightColor.x / 255, _lightColor.y / 255, _lightColor.z / 255, 255);

                    Single LightRadius = 256;

                    if (Light.type == LightType.Spot || Light.type == LightType.Point)
                    {
                        if (Light.type == LightType.Spot)
                        {
                            //Single inner_cone = Converters.ToSingle(Data[Data.FindIndex(n => n == "_cone2") + 1]);
                            Single cone = Data[Data.FindIndex(n => n == "_cone") + 1].ToSingle() * 2;
                            //radius -= inner_cone / cone;
                            Light.spotAngle = Mathf.Clamp(cone, 0, 179);
                        }

                        Single _distance = Data[Data.FindIndex(n => n == "_distance") + 1].ToInt32();

                        if (_distance != 0)
                        {
                            LightRadius = _distance;
                            intensity  *= 1.5f;
                        }
                        else
                        {
                            Single  _fifty_percent_distance = Data[Data.FindIndex(n => n == "_fifty_percent_distance") + 1].ToSingle();
                            Boolean isFifty = _fifty_percent_distance != 0;

                            if (isFifty)
                            {
                                //New light style
                                Single _zero_percent_distance = Data[Data.FindIndex(n => n == "_zero_percent_distance") + 1].ToSingle();

                                if (_zero_percent_distance < _fifty_percent_distance)
                                {
                                    // !!warning in lib code???!!!
                                    Debug.LogWarningFormat("light has _fifty_percent_distance of {0} but no zero_percent_distance", _fifty_percent_distance);
                                    _zero_percent_distance = 2.0f * _fifty_percent_distance;
                                }

                                Single a = 0, b = 1, c = 0;
                                if (!MathLibrary.SolveInverseQuadraticMonotonic(0, 1.0f, _fifty_percent_distance, 2.0f, _zero_percent_distance, 256.0f, ref a, ref b, ref c))
                                {
                                    Debug.LogWarningFormat("can't solve quadratic for light {0} {1}", _fifty_percent_distance, _zero_percent_distance);
                                }

                                Single v50   = c + _fifty_percent_distance * (b + _fifty_percent_distance * a);
                                Single scale = 2.0f / v50;
                                a *= scale;
                                b *= scale;
                                c *= scale;
                                m_Attenuation2 = a;
                                m_Attenuation1 = b;
                                m_Attenuation0 = c;
                            }
                            else
                            {
                                //Old light style
                                Single constant_attn  = Data[Data.FindIndex(n => n == "_constant_attn") + 1].ToSingle();
                                Single linear_attn    = Data[Data.FindIndex(n => n == "_linear_attn") + 1].ToSingle();
                                Single quadratic_attn = Data[Data.FindIndex(n => n == "_quadratic_attn") + 1].ToSingle();

                                // old-style manually typed quadrtiac coefficients
                                if (quadratic_attn < 0.001)
                                {
                                    quadratic_attn = 0;
                                }

                                if (linear_attn < 0.001)
                                {
                                    linear_attn = 0;
                                }

                                if (constant_attn < 0.001)
                                {
                                    constant_attn = 0;
                                }

                                if ((constant_attn < 0.001) &&
                                    (linear_attn < 0.001) &&
                                    (quadratic_attn < 0.001))
                                {
                                    constant_attn = 1;
                                }

                                m_Attenuation2 = quadratic_attn;
                                m_Attenuation1 = linear_attn;
                                m_Attenuation0 = constant_attn;
                            }

                            // FALLBACK: older lights use this
                            if (m_Attenuation2 == 0.0f)
                            {
                                if (m_Attenuation1 == 0.0f)
                                {
                                    // Infinite, but we're not going to draw it as such
                                    LightRadius = 2000;
                                }
                                else
                                {
                                    LightRadius = (intensity / 0.03f - m_Attenuation0) / m_Attenuation1;
                                }
                            }
                            else
                            {
                                Single a       = m_Attenuation2;
                                Single b       = m_Attenuation1;
                                Single c       = m_Attenuation0 - intensity / 0.03f;
                                Single discrim = b * b - 4 * a * c;
                                if (discrim < 0.0f)
                                {
                                    // Infinite, but we're not going to draw it as such
                                    LightRadius = 2000;
                                }
                                else
                                {
                                    LightRadius = (-b + Mathf.Sqrt(discrim)) / (2.0f * a);
                                    if (LightRadius < 0)
                                    {
                                        LightRadius = 0;
                                    }

                                    //DeadZoneLuna
                                    //TODO: Find the best way to fix that
                                    //DeadZoneLuna
                                    if (isFifty)
                                    {
                                        //TODO: WHY?
                                        LightRadius /= 10;
                                    }
                                    else
                                    {
                                        //TODO: Not enough intensity?
                                        LightRadius *= 10;
                                    }
                                }
                            }
                        }

                        Light.range = (LightRadius * uLoader.UnitScale);
                    }

                    Light.intensity = (intensity / 255f) * 1.75f;

#if UNITY_EDITOR
                    Light.lightmapBakeType = LightmapBakeType.Baked;
#endif
                    if (uLoader.UseDynamicLight)
                    {
                        Light.shadows = LightShadows.Soft;
                        if (Light.type == LightType.Directional)
                        {
                            Light.shadowBias       = 0.1f;
                            Light.shadowNormalBias = 0;
                        }
                        else
                        {
                            Light.shadowBias = 0.01f;
                        }
                    }
                }

                return;
            }

            //Lights

            #region Counter-Strike entities test

            /*if (Classname.Equals("info_player_terrorist"))
             * {
             *  //Placeholder model (can be removed if needed)
             *  ResourceManager.LoadModel("player/t_phoenix").SetParent(transform, false);
             * }
             *
             * //Counter-Strike CT spawn point
             * if (Classname.Equals("info_player_counterterrorist"))
             * {
             *  //Placeholder model (can be removed if needed)
             *  ResourceManager.LoadModel("player/ct_urban").SetParent(transform, false);
             * }
             *
             * //Default spawn point
             * if (Classname.Equals("info_player_start"))
             * {
             *  //Placeholder model (can be removed if needed)
             *  ResourceManager.LoadModel("editor/playerstart").SetParent(transform, false);
             * }
             *
             * //weapon spawn point
             * if (Classname.Contains("weapon_"))
             * {
             *  //Placeholder model (can be removed if needed)
             *  ResourceManager.LoadModel("weapons/w_rif_ak47").SetParent(transform, false);
             * }
             *
             * //hostage spawn point
             * if (Classname.Equals("hostage_entity"))
             * {
             *  String[] hostages =
             *  {
             *      "characters/hostage_01",
             *      "characters/hostage_02",
             *      "characters/hostage_03",
             *      "characters/hostage_04"
             *  };
             *
             *  ResourceManager.LoadModel(hostages[UnityEngine.Random.Range(0, hostages.Length)]).SetParent(transform, false);
             * }*/
            #endregion

            Int32 RenderModeIndex = Data.FindIndex(n => n == "rendermode");
            if (RenderModeIndex != -1)
            {
                if (Data[RenderModeIndex + 1] == "10")
                {
                    for (Int32 i = 0; i < transform.childCount; i++)
                    {
                        GameObject Child = transform.GetChild(i).gameObject;
                        Child.GetComponent <Renderer>().enabled = false;
                    }
                }
            }

            if (Classname.Contains("prop_") || Classname.Contains("npc_"))// || Classname.Equals("asw_door"))
            {
                string ModelName = Data[Data.FindIndex(n => n == "model") + 1];

                if (!string.IsNullOrEmpty(ModelName))
                {
                    uResourceManager.LoadModel(ModelName, uLoader.LoadAnims, uLoader.UseHitboxesOnModel).SetParent(transform, false);
                    return;
                }

                return;
            }

            if (uLoader.ParseDecals && Classname.Equals("infodecal"))
            {
                String  DecalName     = Data[Data.FindIndex(n => n == "texture") + 1];
                VMTFile DecalMaterial = uResourceManager.LoadMaterial(DecalName);

                Single DecalScale = DecalMaterial.GetSingle("$decalscale");

                if (DecalScale <= 0)
                {
                    DecalScale = 1f;
                }

                Int32  DecalWidth   = DecalMaterial.Material.mainTexture.width;  //X
                Int32  DecalHeight  = DecalMaterial.Material.mainTexture.height; //Y
                Sprite DecalTexture = Sprite.Create((Texture2D)DecalMaterial.Material.mainTexture, new Rect(0, 0, DecalWidth, DecalHeight), Vector2.zero);

                Decal DecalBuilder = transform.gameObject.AddComponent <Decal>();

#if UNITY_EDITOR
                if (uLoader.DebugMaterials)
                {
                    transform.gameObject.AddComponent <DebugMaterial>().Init(DecalMaterial);
                }
#endif

                DecalBuilder.SetDirection();
                DecalBuilder.MaxAngle = 87.5f;
                DecalBuilder.Offset   = 0.001f;
                DecalBuilder.Sprite   = DecalTexture;
                DecalBuilder.Material = DecalMaterial.Material;
                DecalBuilder.Material.SetTextureScale("_MainTex", new Vector2(-1, 1));

                Single ScaleX = (DecalWidth * DecalScale) * uLoader.UnitScale;
                Single ScaleY = (DecalHeight * DecalScale) * uLoader.UnitScale;

                Single DepthSize = ScaleX;
                if (ScaleY < DepthSize)
                {
                    DepthSize = ScaleY;
                }

                transform.localScale = new Vector3(ScaleX, ScaleY, DepthSize);
                transform.position  += new Vector3(0, 0, 0.001f);

#if !UNITY_EDITOR
                DecalBuilder.BuildAndSetDirty();
#endif
            }
        }