From 59a457cff832dc5afc58797d822d8ec33cb88cd2 Mon Sep 17 00:00:00 2001 From: dexy Date: Tue, 26 Nov 2019 20:47:47 +1100 Subject: [PATCH] Cutscene viewer vehicles --- CodeWalker.Core/CodeWalker.Core.csproj | 1 + CodeWalker.Core/GameFiles/GameFileCache.cs | 34 +++---- CodeWalker.Core/World/Vehicle.cs | 102 +++++++++++++++++++ PedsForm.cs | 1 + Rendering/Renderer.cs | 16 +++ VehicleForm.cs | 113 ++++----------------- World/CutsceneForm.cs | 47 +++++---- 7 files changed, 182 insertions(+), 132 deletions(-) create mode 100644 CodeWalker.Core/World/Vehicle.cs diff --git a/CodeWalker.Core/CodeWalker.Core.csproj b/CodeWalker.Core/CodeWalker.Core.csproj index 757b713..8e9c9ae 100644 --- a/CodeWalker.Core/CodeWalker.Core.csproj +++ b/CodeWalker.Core/CodeWalker.Core.csproj @@ -150,6 +150,7 @@ + diff --git a/CodeWalker.Core/GameFiles/GameFileCache.cs b/CodeWalker.Core/GameFiles/GameFileCache.cs index e22a0f4..955db7f 100644 --- a/CodeWalker.Core/GameFiles/GameFileCache.cs +++ b/CodeWalker.Core/GameFiles/GameFileCache.cs @@ -92,7 +92,7 @@ namespace CodeWalker.GameFiles public bool DoFullStringIndex = false; public bool BuildExtendedJenkIndex = true; public bool LoadArchetypes = true; - public bool LoadVehicles = false; + public bool LoadVehicles = true; public bool LoadPeds = true; private bool PreloadedMode = false; @@ -1404,6 +1404,7 @@ namespace CodeWalker.GameFiles string langstr3 = "american.rpf"; Gxt2Dict = new Dictionary(); + var gxt2files = new List(); foreach (var rpf in AllRpfs) { foreach (var entry in rpf.AllEntries) @@ -1414,13 +1415,25 @@ namespace CodeWalker.GameFiles if (entry.NameLower.EndsWith(".gxt2") && (p.Contains(langstr) || p.Contains(langstr2) || p.Contains(langstr3))) { Gxt2Dict[entry.ShortNameHash] = fentry; + + if (DoFullStringIndex) + { + var gxt2 = RpfMan.GetFile(entry); + if (gxt2 != null) + { + for (int i = 0; i < gxt2.TextEntries.Length; i++) + { + var e = gxt2.TextEntries[i]; + GlobalText.Ensure(e.Text, e.Hash); + } + gxt2files.Add(gxt2); + } + } } } } } - - if (!DoFullStringIndex) { string globalgxt2path = "x64b.rpf\\data\\lang\\" + langstr + ".rpf\\global.gxt2"; @@ -1437,21 +1450,6 @@ namespace CodeWalker.GameFiles } - List gxt2files = new List(); - foreach (var entry in Gxt2Dict.Values) - { - var gxt2 = RpfMan.GetFile(entry); - if (gxt2 != null) - { - for (int i = 0; i < gxt2.TextEntries.Length; i++) - { - var e = gxt2.TextEntries[i]; - GlobalText.Ensure(e.Text, e.Hash); - } - gxt2files.Add(gxt2); - } - } - GlobalText.FullIndexBuilt = true; diff --git a/CodeWalker.Core/World/Vehicle.cs b/CodeWalker.Core/World/Vehicle.cs new file mode 100644 index 0000000..4428f73 --- /dev/null +++ b/CodeWalker.Core/World/Vehicle.cs @@ -0,0 +1,102 @@ +using CodeWalker.GameFiles; +using SharpDX; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace CodeWalker.World +{ + [TypeConverter(typeof(ExpandableObjectConverter))] public class Vehicle + { + public string Name { get; set; } = string.Empty; + public MetaHash NameHash { get; set; } = 0;//base vehicle name hash + public MetaHash ModelHash { get; set; } = 0;//vehicle model name hash, can be _hi + + public VehicleInitData InitData { get; set; } = null; + public YftFile Yft { get; set; } = null; + + public YcdFile ConvRoofDict { get; set; } = null; + public ClipMapEntry ConvRoofClip { get; set; } = null; + + public string DisplayMake { get; set; } = string.Empty;//make display name + public string DisplayName { get; set; } = string.Empty;//model display name + + public YmapEntityDef RenderEntity = new YmapEntityDef(); //placeholder entity object for rendering + + public Vector3 Position { get; set; } = Vector3.Zero; + public Quaternion Rotation { get; set; } = Quaternion.Identity; + + + 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(); + } + + + + public void UpdateEntity() + { + RenderEntity.SetPosition(Position); + RenderEntity.SetOrientation(Rotation); + } + + + } +} diff --git a/PedsForm.cs b/PedsForm.cs index a5dd93d..e2d4709 100644 --- a/PedsForm.cs +++ b/PedsForm.cs @@ -335,6 +335,7 @@ namespace CodeWalker.Peds GameFileCache.EnableDlc = true; GameFileCache.EnableMods = true; GameFileCache.LoadPeds = true; + GameFileCache.LoadVehicles = false; GameFileCache.LoadArchetypes = false;//to speed things up a little GameFileCache.BuildExtendedJenkIndex = false;//to speed things up a little GameFileCache.DoFullStringIndex = true;//to get all global text from DLC... diff --git a/Rendering/Renderer.cs b/Rendering/Renderer.cs index b221527..523644d 100644 --- a/Rendering/Renderer.cs +++ b/Rendering/Renderer.cs @@ -2734,6 +2734,22 @@ namespace CodeWalker.Rendering } } + public void RenderVehicle(Vehicle vehicle, ClipMapEntry animClip = null) + { + + YftFile yft = vehicle.Yft; + if ((yft != null) && (yft.Loaded) && (yft.Fragment != null)) + { + var f = yft.Fragment; + var txdhash = vehicle.NameHash; + + RenderFragment(null, vehicle.RenderEntity, f, txdhash, animClip); + + } + + } + + public void RenderPed(Ped ped) diff --git a/VehicleForm.cs b/VehicleForm.cs index ff5bf16..4068a08 100644 --- a/VehicleForm.cs +++ b/VehicleForm.cs @@ -75,13 +75,8 @@ namespace CodeWalker.Vehicles - MetaHash SelectedVehicleHash = 0;//base vehicle name hash - MetaHash SelectedModelHash = 0;//yft name hash, can be _hi - VehicleInitData SelectedVehicleInit = null; - YftFile SelectedVehicleYft = null; + Vehicle SelectedVehicle = new Vehicle(); - YcdFile ConvRoofDict = null; - ClipMapEntry ConvRoofClip = null; bool PlayConvRoofAnim = false; @@ -289,6 +284,7 @@ namespace CodeWalker.Vehicles } GameFileCache.EnableDlc = true; + GameFileCache.LoadPeds = false; GameFileCache.LoadVehicles = true; GameFileCache.LoadArchetypes = false;//to speed things up a little GameFileCache.BuildExtendedJenkIndex = false;//to speed things up a little @@ -668,68 +664,22 @@ namespace CodeWalker.Vehicles public void LoadVehicle() { - var modelname = VehicleModelComboBox.Text; - var modelnamel = modelname.ToLowerInvariant(); - MetaHash modelhash = JenkHash.GenHash(modelnamel); - MetaHash modelhashhi = JenkHash.GenHash(modelnamel + "_hi"); + var name = VehicleModelComboBox.Text; bool hidet = VehicleHighDetailCheckBox.Checked; - var yfthash = hidet ? modelhashhi : modelhash; + bool vehiclechange = SelectedVehicle.Name != name; - VehicleInitData vid = null; - if (GameFileCache.VehiclesInitDict.TryGetValue(modelhash, out vid)) + SelectedVehicle.Init(name, GameFileCache, hidet); + + if (SelectedVehicle.InitData != null) { - bool vehiclechange = SelectedVehicleHash != modelhash; - ConvRoofDict = null; - ConvRoofClip = null; - SelectedModelHash = yfthash; - SelectedVehicleHash = modelhash; - SelectedVehicleInit = vid; - SelectedVehicleYft = GameFileCache.GetYft(SelectedModelHash); - while ((SelectedVehicleYft != null) && (!SelectedVehicleYft.Loaded)) - { - Thread.Sleep(20);//kinda hacky - SelectedVehicleYft = GameFileCache.GetYft(SelectedModelHash); - } - LoadModel(SelectedVehicleYft, vehiclechange); - VehicleMakeLabel.Text = GlobalText.TryGetString(JenkHash.GenHash(vid.vehicleMakeName.ToLower())); - VehicleNameLabel.Text = GlobalText.TryGetString(JenkHash.GenHash(vid.gameName.ToLower())); - - if (!string.IsNullOrEmpty(vid.animConvRoofDictName) && (vid.animConvRoofDictName.ToLowerInvariant() != "null")) - { - ConvRoofDictNameLabel.Text = vid.animConvRoofDictName; - ConvRoofNameLabel.Text = vid.animConvRoofName; - - var ycdhash = JenkHash.GenHash(vid.animConvRoofDictName.ToLowerInvariant()); - var cliphash = JenkHash.GenHash(vid.animConvRoofName?.ToLowerInvariant()); - ConvRoofDict = GameFileCache.GetYcd(ycdhash); - while ((ConvRoofDict != null) && (!ConvRoofDict.Loaded)) - { - Thread.Sleep(20);//kinda hacky - ConvRoofDict = GameFileCache.GetYcd(ycdhash); - } - ClipMapEntry cme = null; - ConvRoofDict?.ClipMap?.TryGetValue(cliphash, out cme); - ConvRoofClip = cme; - - ConvRoofPanel.Visible = true; - } - else - { - ConvRoofPanel.Visible = false; - } - } - else - { - SelectedModelHash = 0; - SelectedVehicleHash = 0; - SelectedVehicleInit = null; - SelectedVehicleYft = null; - VehicleMakeLabel.Text = "-"; - VehicleNameLabel.Text = "-"; - ConvRoofPanel.Visible = false; - ConvRoofDict = null; - ConvRoofClip = null; + LoadModel(SelectedVehicle.Yft, vehiclechange); + ConvRoofDictNameLabel.Text = SelectedVehicle.InitData.animConvRoofDictName; + ConvRoofNameLabel.Text = SelectedVehicle.InitData.animConvRoofName; } + VehicleMakeLabel.Text = SelectedVehicle.DisplayMake; + VehicleNameLabel.Text = SelectedVehicle.DisplayName; + ConvRoofPanel.Visible = SelectedVehicle.ConvRoofClip != null; + } public void LoadModel(YftFile yft, bool movecamera = true) @@ -926,39 +876,14 @@ namespace CodeWalker.Vehicles private void RenderVehicle() { - - YftFile yft = GameFileCache.GetYft(SelectedModelHash); - if (yft != null) + ClipMapEntry clip = null; + if (PlayConvRoofAnim) { - if (yft.Loaded) - { - if (yft.Fragment != null) - { - var f = yft.Fragment; - - var txdhash = SelectedVehicleHash;// yft.RpfFileEntry?.ShortNameHash ?? 0; - - var namelower = yft.RpfFileEntry?.GetShortNameLower(); - if (namelower?.EndsWith("_hi") ?? false) - { - txdhash = JenkHash.GenHash(namelower.Substring(0, namelower.Length - 3)); - } - - Archetype arch = null;// TryGetArchetype(hash); - - ClipMapEntry clip = null; - if (PlayConvRoofAnim) - { - clip = ConvRoofClip; - } - - Renderer.RenderFragment(arch, null, f, txdhash, clip); - - //seldrwbl = f.Drawable; - } - } + clip = SelectedVehicle.ConvRoofClip; } + Renderer.RenderVehicle(SelectedVehicle, clip); + } diff --git a/World/CutsceneForm.cs b/World/CutsceneForm.cs index 99c7ac1..e9540a4 100644 --- a/World/CutsceneForm.cs +++ b/World/CutsceneForm.cs @@ -467,44 +467,40 @@ namespace CodeWalker.World { foreach (var obj in SceneObjects.Values) { - if (obj.Ped != null) + var pos = Position; + var rot = Rotation; + var animate = (obj.Ped != null) || (obj.Prop != null) || (obj.Vehicle != null); + if (animate) { ycd.CutsceneMap.TryGetValue(obj.AnimHash, out cme); - var pos = Position; - var rot = Rotation; if (cme != null) { cme.OverridePlayTime = true; cme.PlayTime = cutOffset; - - updateObjectTransform(obj, cme, 0, 5, 6); - + updateObjectTransform(obj, cme, 0, 5, 6); //using root animation bone ids pos = pos + rot.Multiply(obj.Position); rot = rot * obj.Rotation; } + } + if (obj.Ped != null) + { obj.Ped.Position = pos; obj.Ped.Rotation = rot; obj.Ped.AnimClip = cme; } if (obj.Prop != null) { - ycd.CutsceneMap.TryGetValue(obj.AnimHash, out cme); - var pos = Position; - var rot = Rotation; - if (cme != null) - { - cme.OverridePlayTime = true; - cme.PlayTime = cutOffset; - - updateObjectTransform(obj, cme, 0, 5, 6); - - pos = pos + rot.Multiply(obj.Position); - rot = rot * obj.Rotation; - } obj.Prop.Position = pos; obj.Prop.Orientation = rot; obj.AnimClip = cme; } + if (obj.Vehicle != null) + { + obj.Vehicle.Position = pos; + obj.Vehicle.Rotation = rot; + obj.Vehicle.UpdateEntity(); + obj.AnimClip = cme; + } } } @@ -533,6 +529,10 @@ namespace CodeWalker.World { renderer.RenderArchetype(obj.Prop.Archetype, obj.Prop, null, true, obj.AnimClip); } + if (obj.Vehicle != null) + { + renderer.RenderVehicle(obj.Vehicle, obj.AnimClip); + } } } @@ -1026,12 +1026,14 @@ namespace CodeWalker.World public Quaternion Rotation { get; set; } public Ped Ped { get; set; } - public YmapEntityDef Prop { get; set; } + public Vehicle Vehicle { get; set; } public MetaHash AnimHash { get; set; } public ClipMapEntry AnimClip { get; set; } + + public void Init(CutObject obj, GameFileCache gfc) { @@ -1141,7 +1143,12 @@ namespace CodeWalker.World private void InitVehicle(CutVehicleModelObject veh, GameFileCache gfc) { + var name = veh.StreamingName.ToString(); + Vehicle = new Vehicle(); + Vehicle.Init(name, gfc); + + AnimHash = veh.StreamingName; } private void InitWeapon(CutWeaponModelObject weap, GameFileCache gfc)