示例#1
0
        public void Init(string name, GameFileCache gfc, bool hidef = true)
        {
            Name = name;
            var      modelnamel  = name.ToLowerInvariant();
            MetaHash modelhash   = JenkHash.GenHash(modelnamel);
            MetaHash modelhashhi = JenkHash.GenHash(modelnamel + "_hi");
            var      yfthash     = hidef ? modelhashhi : modelhash;

            VehicleInitData vid = null;

            if (gfc.VehiclesInitDict.TryGetValue(modelhash, out vid))
            {
                bool vehiclechange = NameHash != modelhash;
                ConvRoofDict = null;
                ConvRoofClip = null;
                ModelHash    = yfthash;
                NameHash     = modelhash;
                InitData     = vid;
                Yft          = gfc.GetYft(ModelHash);
                while ((Yft != null) && (!Yft.Loaded))
                {
                    Thread.Sleep(20);//kinda hacky
                    Yft = gfc.GetYft(ModelHash);
                }

                DisplayMake = GlobalText.TryGetString(JenkHash.GenHash(vid.vehicleMakeName.ToLowerInvariant()));
                DisplayName = GlobalText.TryGetString(JenkHash.GenHash(vid.gameName.ToLowerInvariant()));

                if (!string.IsNullOrEmpty(vid.animConvRoofDictName) && (vid.animConvRoofDictName.ToLowerInvariant() != "null"))
                {
                    var ycdhash  = JenkHash.GenHash(vid.animConvRoofDictName.ToLowerInvariant());
                    var cliphash = JenkHash.GenHash(vid.animConvRoofName?.ToLowerInvariant());
                    ConvRoofDict = gfc.GetYcd(ycdhash);
                    while ((ConvRoofDict != null) && (!ConvRoofDict.Loaded))
                    {
                        Thread.Sleep(20);//kinda hacky
                        ConvRoofDict = gfc.GetYcd(ycdhash);
                    }
                    ClipMapEntry cme = null;
                    ConvRoofDict?.ClipMap?.TryGetValue(cliphash, out cme);
                    ConvRoofClip = cme;
                }
            }
            else
            {
                ModelHash    = 0;
                NameHash     = 0;
                InitData     = null;
                Yft          = null;
                DisplayMake  = "-";
                DisplayName  = "-";
                ConvRoofDict = null;
                ConvRoofClip = null;
            }


            UpdateEntity();
        }
示例#2
0
        private void RenderVehicle()
        {
            ClipMapEntry clip = null;

            if (PlayConvRoofAnim)
            {
                clip = SelectedVehicle.ConvRoofClip;
            }

            Renderer.RenderVehicle(SelectedVehicle, clip);
        }
示例#3
0
        public void Init(MetaHash pedhash, GameFileCache gfc)
        {
            Name     = string.Empty;
            NameHash = 0;
            InitData = null;
            Ydd      = null;
            Ytd      = null;
            Yld      = null;
            Ycd      = null;
            Yed      = null;
            Yft      = null;
            Ymt      = null;
            AnimClip = null;
            for (int i = 0; i < 12; i++)
            {
                Drawables[i]   = null;
                Textures[i]    = null;
                Expressions[i] = null;
            }


            CPedModelInfo__InitData initdata = null;

            if (!gfc.PedsInitDict.TryGetValue(pedhash, out initdata))
            {
                return;
            }

            var ycdhash = JenkHash.GenHash(initdata.ClipDictionaryName.ToLowerInvariant());
            var yedhash = JenkHash.GenHash(initdata.ExpressionDictionaryName.ToLowerInvariant());

            //bool pedchange = NameHash != pedhash;
            //Name = pedname;
            NameHash = pedhash;
            InitData = initdata;
            Ydd      = gfc.GetYdd(pedhash);
            Ytd      = gfc.GetYtd(pedhash);
            Ycd      = gfc.GetYcd(ycdhash);
            Yed      = gfc.GetYed(yedhash);
            Yft      = gfc.GetYft(pedhash);

            PedFile pedFile = null;

            gfc.PedVariationsDict?.TryGetValue(pedhash, out pedFile);
            Ymt = pedFile;

            Dictionary <MetaHash, RpfFileEntry> peddict = null;

            gfc.PedDrawableDicts.TryGetValue(NameHash, out peddict);
            DrawableFilesDict = peddict;
            DrawableFiles     = DrawableFilesDict?.Values.ToArray();
            gfc.PedTextureDicts.TryGetValue(NameHash, out peddict);
            TextureFilesDict = peddict;
            TextureFiles     = TextureFilesDict?.Values.ToArray();
            gfc.PedClothDicts.TryGetValue(NameHash, out peddict);
            ClothFilesDict = peddict;
            ClothFiles     = ClothFilesDict?.Values.ToArray();

            RpfFileEntry clothFile = null;

            if (ClothFilesDict?.TryGetValue(pedhash, out clothFile) ?? false)
            {
                Yld = gfc.GetFileUncached <YldFile>(clothFile);
                while ((Yld != null) && (!Yld.Loaded))
                {
                    Thread.Sleep(1);//kinda hacky
                    gfc.TryLoadEnqueue(Yld);
                }
            }



            while ((Ydd != null) && (!Ydd.Loaded))
            {
                Thread.Sleep(1);//kinda hacky
                Ydd = gfc.GetYdd(pedhash);
            }
            while ((Ytd != null) && (!Ytd.Loaded))
            {
                Thread.Sleep(1);//kinda hacky
                Ytd = gfc.GetYtd(pedhash);
            }
            while ((Ycd != null) && (!Ycd.Loaded))
            {
                Thread.Sleep(1);//kinda hacky
                Ycd = gfc.GetYcd(ycdhash);
            }
            while ((Yed != null) && (!Yed.Loaded))
            {
                Thread.Sleep(1);//kinda hacky
                Yed = gfc.GetYed(yedhash);
            }
            while ((Yft != null) && (!Yft.Loaded))
            {
                Thread.Sleep(1);//kinda hacky
                Yft = gfc.GetYft(pedhash);
            }


            Skeleton = Yft?.Fragment?.Drawable?.Skeleton?.Clone();

            MetaHash     cliphash = JenkHash.GenHash("idle");
            ClipMapEntry cme      = null;

            Ycd?.ClipMap?.TryGetValue(cliphash, out cme);
            AnimClip = cme;

            var        exprhash = JenkHash.GenHash(initdata.ExpressionName.ToLowerInvariant());
            Expression expr     = null;

            Yed?.ExprMap?.TryGetValue(exprhash, out expr);
            Expression = expr;


            UpdateEntity();
        }
示例#4
0
        public void Update(float newTime)
        {
            if (newTime > Duration)
            {
                newTime = 0.0f; //stop or loop?
            }

            if (newTime >= PlaybackTime)
            {
                RaiseEvents(newTime);
            }
            else
            {
                //reset playback to beginning, and seek to newTime
                RaiseEvents(Duration);//raise all events up to the end first
                PlaybackTime   = 0.0f;
                NextLoadEvent  = 0;
                NextPlayEvent  = 0;
                NextCameraCut  = 0;
                NextConcatData = 0;
                RaiseEvents(newTime);
            }

            PlaybackTime = newTime;

            int   cutIndex = 0;
            float cutStart = 0.0f;

            for (cutIndex = 0; cutIndex < CameraCutList?.Length; cutIndex++)
            {
                var cutTime = CameraCutList[cutIndex];
                if (cutTime > newTime)
                {
                    break;
                }
                cutStart = cutTime;
            }

            float cutOffset = newTime - cutStart;//offset into the current cut


            void updateObjectTransform(CutsceneObject obj, ClipMapEntry cme, ushort boneTag, byte posTrack, byte rotTrack)
            {
                if (cme != null)
                {
                    if (cme.Clip is ClipAnimation canim)
                    {
                        if (canim.Animation != null)
                        {
                            var t = canim.GetPlaybackTime(cutOffset);
                            var f = canim.Animation.GetFramePosition(t);
                            var p = canim.Animation.FindBoneIndex(boneTag, posTrack);
                            var r = canim.Animation.FindBoneIndex(boneTag, rotTrack);
                            if (p >= 0)
                            {
                                obj.Position = canim.Animation.EvaluateVector4(f, p, true).XYZ();
                            }
                            if (r >= 0)
                            {
                                obj.Rotation = canim.Animation.EvaluateQuaternion(f, r, true);
                            }
                        }
                    }
                    else if (cme.Clip is ClipAnimationList alist)
                    {
                        if (alist.Animations?.Data != null)
                        {
                            foreach (var anim in alist.Animations.Data)
                            {
                                var t = anim.GetPlaybackTime(cutOffset);
                                var f = anim.Animation.GetFramePosition(t);
                                var p = anim.Animation.FindBoneIndex(boneTag, posTrack);
                                var r = anim.Animation.FindBoneIndex(boneTag, rotTrack);
                                if (p >= 0)
                                {
                                    obj.Position = anim.Animation.EvaluateVector4(f, p, true).XYZ();
                                }
                                if (r >= 0)
                                {
                                    obj.Rotation = anim.Animation.EvaluateQuaternion(f, r, true);
                                }
                            }
                        }
                    }
                }
            }

            var ycd = (cutIndex < (Ycds?.Length ?? 0)) ? Ycds[cutIndex] : null;

            if (ycd?.CutsceneMap != null)
            {
                ClipMapEntry cme = null;

                if (CameraObject != null)
                {
                    ycd.CutsceneMap.TryGetValue(CameraObject.Name, out cme);

                    updateObjectTransform(CameraObject, cme, 0, 7, 8);


                    if (cme != null)
                    {
                        var pos = Position;
                        var rot = Rotation;
                        pos = pos + rot.Multiply(CameraObject.Position);
                        rot = rot * CameraObject.Rotation * CameraRotationOffset;
                        CameraObject.Position = pos;
                        CameraObject.Rotation = rot;
                    }
                }

                if (SceneObjects != null)
                {
                    foreach (var obj in SceneObjects.Values)
                    {
                        if (obj.Enabled == false)
                        {
                            continue;
                        }

                        var pos     = Position;
                        var rot     = Rotation;
                        var animate = (obj.Ped != null) || (obj.Prop != null) || (obj.Vehicle != null) || (obj.Weapon != null);
                        if (animate)
                        {
                            ycd.CutsceneMap.TryGetValue(obj.AnimHash, out cme);
                            if (cme != null)
                            {
                                cme.OverridePlayTime = true;
                                cme.PlayTime         = cutOffset;
                                updateObjectTransform(obj, cme, 0, 5, 6); //using root animation bone ids
                                pos = pos + rot.Multiply(obj.Position);
                                rot = rot * obj.Rotation;
                            }
                            obj.AnimClip = cme;
                        }
                        if (obj.Ped != null)
                        {
                            obj.Ped.Position = pos;
                            obj.Ped.Rotation = rot;
                            obj.Ped.UpdateEntity();
                            obj.Ped.AnimClip = cme;
                        }
                        if (obj.Prop != null)
                        {
                            obj.Prop.Position    = pos;
                            obj.Prop.Orientation = rot;
                        }
                        if (obj.Vehicle != null)
                        {
                            obj.Vehicle.Position = pos;
                            obj.Vehicle.Rotation = rot;
                            obj.Vehicle.UpdateEntity();
                        }
                        if (obj.Weapon != null)
                        {
                            obj.Weapon.Position = pos;
                            obj.Weapon.Rotation = rot;
                            obj.Weapon.UpdateEntity();
                        }
                    }
                }
            }
        }
示例#5
0
        public byte[] BuildYcd()
        {
            YcdFile ycd = new YcdFile();

            ycd.ClipDictionary = new ClipDictionary();


            var clipmap = new List <ClipMapEntry>();
            var animmap = new List <AnimationMapEntry>();

            foreach (var onim in OnimFiles)
            {
                var anim = new Animation();
                anim.Hash               = JenkHash.GenHash(onim.Name.ToLowerInvariant());
                anim.Frames             = (ushort)onim.Frames;
                anim.SequenceFrameLimit = (ushort)onim.SequenceFrameLimit;
                anim.Duration           = onim.Duration;

                JenkIndex.Ensure(onim.Name.ToLowerInvariant());//just to make it nicer to debug really

                bool isUV          = false;
                bool hasRootMotion = false;
                var  boneIds       = new List <AnimationBoneId>();
                var  seqs          = new List <Sequence>();
                var  aseqs         = new List <List <AnimSequence> >();
                foreach (var oseq in onim.SequenceList)
                {
                    var boneid = new AnimationBoneId();
                    boneid.BoneId = (ushort)oseq.BoneID; //TODO: bone ID mapping
                    boneid.Unk0   = 0;                   //what to use here?
                    switch (oseq.Track)
                    {
                    case "BonePosition": boneid.Track = 0;
                        break;

                    case "BoneRotation": boneid.Track = 1;
                        break;

                    case "ModelPosition": boneid.Track = 5; hasRootMotion = true;
                        break;

                    case "ModelRotation": boneid.Track = 6; hasRootMotion = true;
                        break;

                    case "UV0": boneid.Track = 17; isUV = true;
                        break;

                    case "UV1": boneid.Track = 18; isUV = true;
                        break;

                    case "LightColor": boneid.Track = 0;    //what should this be?
                        break;

                    case "LightRange": boneid.Track = 0;    //what should this be?
                        break;

                    case "LightIntensity1": boneid.Track = 0;    //what should this be?
                        break;

                    case "LightIntensity2": boneid.Track = 0;    //what should this be?
                        break;

                    case "LightDirection": boneid.Track = 0;    //what should this be?
                        break;

                    case "Type21": boneid.Track = 0;    //what should this be?
                        break;

                    case "CameraPosition": boneid.Track = 7;
                        break;

                    case "CameraRotation": boneid.Track = 8;
                        break;

                    case "CameraFOV": boneid.Track = 0;    //what should this be?
                        break;

                    case "CameraDof": boneid.Track = 0;    //what should this be?
                        break;

                    case "CameraMatrixRotateFactor": boneid.Track = 0;    //what should this be?
                        break;

                    case "CameraControl": boneid.Track = 0;    //what should this be?
                        break;

                    case "ActionFlags":    //not sure what this is for? just ignore it for now
                        continue;

                    default:
                        break;
                    }
                    boneIds.Add(boneid);

                    for (int i = 0; i < oseq.FramesData.Count; i++)
                    {
                        var framesData = oseq.FramesData[i];
                        if (i > 0)
                        {
                        }
                        Sequence            seq      = null;
                        List <AnimSequence> aseqlist = null;
                        while (i >= seqs.Count)
                        {
                            seq = new Sequence();
                            seqs.Add(seq);
                            aseqlist = new List <AnimSequence>();
                            aseqs.Add(aseqlist);
                        }
                        seq      = seqs[i];
                        aseqlist = aseqs[i];


                        var chanlist = new List <AnimChannel>();
                        if (framesData.IsStatic)
                        {
                            var vals = (framesData.Channels.Count > 0) ? framesData.Channels[0].Values : null;
                            if (vals != null)
                            {
                                if (vals.Length == 1)
                                {
                                    var acsf = new AnimChannelStaticFloat();
                                    acsf.Value = vals[0];
                                    chanlist.Add(acsf);
                                }
                                else if (vals.Length == 3)
                                {
                                    var acsv = new AnimChannelStaticVector3();
                                    acsv.Value = new Vector3(vals[0], vals[1], vals[2]);
                                    chanlist.Add(acsv);
                                }
                                else if (vals.Length == 4)
                                {
                                    var acsq = new AnimChannelStaticQuaternion();
                                    acsq.Value = new Quaternion(vals[0], vals[1], vals[2], vals[3]);
                                    chanlist.Add(acsq);
                                }
                                else
                                {
                                }
                            }
                            else
                            {
                            }
                        }
                        else
                        {
                            int chanCount = framesData.Channels.Count;

                            for (int c = 0; c < chanCount; c++)
                            {
                                var ochan = framesData.Channels[c];
                                var vals  = ochan.Values;
                                if (vals.Length == 1)//static channel...
                                {
                                    var acsf = new AnimChannelStaticFloat();
                                    acsf.Value = vals[0];
                                    chanlist.Add(acsf);
                                }
                                else //if (vals.Length == onim.Frames)
                                {
                                    float minval   = float.MaxValue;
                                    float maxval   = float.MinValue;
                                    float lastval  = 0;
                                    float mindelta = float.MaxValue;
                                    foreach (var val in vals)
                                    {
                                        minval = Math.Min(minval, val);
                                        maxval = Math.Max(maxval, val);
                                        if (val != lastval)
                                        {
                                            float adelta = Math.Abs(val - lastval);
                                            mindelta = Math.Min(mindelta, adelta);
                                        }
                                        lastval = val;
                                    }
                                    if (mindelta == float.MaxValue)
                                    {
                                        mindelta = 0;
                                    }
                                    float range    = maxval - minval;
                                    float minquant = range / 1048576.0f;
                                    float quantum  = Math.Max(mindelta, minquant);

                                    var acqf = new AnimChannelQuantizeFloat();
                                    acqf.Values  = vals;
                                    acqf.Offset  = minval;
                                    acqf.Quantum = quantum;
                                    chanlist.Add(acqf);
                                }
                            }

                            if (chanCount == 4)
                            {
                                //assume it's a quaternion... add the extra quaternion channel
                                var acq1 = new AnimChannelCachedQuaternion(AnimChannelType.CachedQuaternion2);
                                acq1.QuatIndex = 3;//what else should it be?
                                chanlist.Add(acq1);
                            }
                        }

                        if (chanlist.Count == 4)
                        {
                        }  //shouldn't happen

                        AnimSequence aseq = new AnimSequence();
                        aseq.Channels = chanlist.ToArray();

                        aseqlist.Add(aseq);
                    }
                }

                int remframes = anim.Frames;
                for (int i = 0; i < seqs.Count; i++)
                {
                    var seq      = seqs[i];
                    var aseqlist = aseqs[i];

                    seq.Unknown_00h = 0;//what to set this???
                    seq.NumFrames   = (ushort)Math.Max(Math.Min(anim.SequenceFrameLimit, remframes), 0);
                    seq.Sequences   = aseqlist.ToArray();

                    seq.AssociateSequenceChannels();

                    remframes -= anim.SequenceFrameLimit;
                }


                anim.BoneIds            = new ResourceSimpleList64_s <AnimationBoneId>();
                anim.BoneIds.data_items = boneIds.ToArray();

                anim.Sequences            = new ResourcePointerList64 <Sequence>();
                anim.Sequences.data_items = seqs.ToArray();

                anim.Unknown_10h = hasRootMotion ? (byte)16 : (byte)0;
                anim.Unknown_1Ch = 0; //???

                anim.AssignSequenceBoneIds();



                var cliphash = anim.Hash;
                if (isUV)
                {
                    var name  = onim.Name.ToLowerInvariant();
                    var uvind = name.IndexOf("_uv_");
                    if (uvind < 0)
                    {
                    }
                    var modelname = name.Substring(0, uvind);
                    var geoindstr = name.Substring(uvind + 4);
                    var geoind    = 0u;
                    uint.TryParse(geoindstr, out geoind);
                    cliphash = JenkHash.GenHash(modelname) + geoind + 1;
                }
                else
                {
                }


                var clip = new ClipAnimation();
                clip.Animation   = anim;
                clip.StartTime   = 0.0f;
                clip.EndTime     = anim.Duration;
                clip.Rate        = 1.0f;
                clip.Name        = "pack:/" + onim.Name + ".clip"; //pack:/name.clip
                clip.Unknown_30h = 0;                              //what's this then?
                clip.Properties  = new ClipPropertyMap();
                clip.Properties.CreatePropertyMap(null);           //TODO?
                clip.Tags = new ClipTagList();                     //TODO?

                var cme = new ClipMapEntry();
                cme.Clip = clip;
                cme.Hash = cliphash;
                clipmap.Add(cme);

                var ame = new AnimationMapEntry();
                ame.Hash      = anim.Hash;//is this right? what else to use?
                ame.Animation = anim;
                animmap.Add(ame);
            }


            ycd.ClipDictionary.CreateClipsMap(clipmap.ToArray());
            ycd.ClipDictionary.CreateAnimationsMap(animmap.ToArray());

            ycd.ClipDictionary.BuildMaps();
            ycd.ClipDictionary.UpdateUsageCounts();
            ycd.InitDictionaries();

            byte[] data = ycd.Save();
            return(data);
        }