Cutscene viewer vehicles

This commit is contained in:
dexy 2019-11-26 20:47:47 +11:00
parent 91873ea87a
commit 59a457cff8
7 changed files with 182 additions and 132 deletions

View File

@ -150,6 +150,7 @@
<Compile Include="World\Timecycle.cs" /> <Compile Include="World\Timecycle.cs" />
<Compile Include="World\TimecycleMods.cs" /> <Compile Include="World\TimecycleMods.cs" />
<Compile Include="World\Trains.cs" /> <Compile Include="World\Trains.cs" />
<Compile Include="World\Vehicle.cs" />
<Compile Include="World\Water.cs" /> <Compile Include="World\Water.cs" />
<Compile Include="World\Weather.cs" /> <Compile Include="World\Weather.cs" />
</ItemGroup> </ItemGroup>

View File

@ -92,7 +92,7 @@ namespace CodeWalker.GameFiles
public bool DoFullStringIndex = false; public bool DoFullStringIndex = false;
public bool BuildExtendedJenkIndex = true; public bool BuildExtendedJenkIndex = true;
public bool LoadArchetypes = true; public bool LoadArchetypes = true;
public bool LoadVehicles = false; public bool LoadVehicles = true;
public bool LoadPeds = true; public bool LoadPeds = true;
private bool PreloadedMode = false; private bool PreloadedMode = false;
@ -1404,6 +1404,7 @@ namespace CodeWalker.GameFiles
string langstr3 = "american.rpf"; string langstr3 = "american.rpf";
Gxt2Dict = new Dictionary<uint, RpfFileEntry>(); Gxt2Dict = new Dictionary<uint, RpfFileEntry>();
var gxt2files = new List<Gxt2File>();
foreach (var rpf in AllRpfs) foreach (var rpf in AllRpfs)
{ {
foreach (var entry in rpf.AllEntries) 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))) if (entry.NameLower.EndsWith(".gxt2") && (p.Contains(langstr) || p.Contains(langstr2) || p.Contains(langstr3)))
{ {
Gxt2Dict[entry.ShortNameHash] = fentry; Gxt2Dict[entry.ShortNameHash] = fentry;
if (DoFullStringIndex)
{
var gxt2 = RpfMan.GetFile<Gxt2File>(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) if (!DoFullStringIndex)
{ {
string globalgxt2path = "x64b.rpf\\data\\lang\\" + langstr + ".rpf\\global.gxt2"; string globalgxt2path = "x64b.rpf\\data\\lang\\" + langstr + ".rpf\\global.gxt2";
@ -1437,21 +1450,6 @@ namespace CodeWalker.GameFiles
} }
List<Gxt2File> gxt2files = new List<Gxt2File>();
foreach (var entry in Gxt2Dict.Values)
{
var gxt2 = RpfMan.GetFile<Gxt2File>(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; GlobalText.FullIndexBuilt = true;

View File

@ -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);
}
}
}

View File

@ -335,6 +335,7 @@ namespace CodeWalker.Peds
GameFileCache.EnableDlc = true; GameFileCache.EnableDlc = true;
GameFileCache.EnableMods = true; GameFileCache.EnableMods = true;
GameFileCache.LoadPeds = true; GameFileCache.LoadPeds = true;
GameFileCache.LoadVehicles = false;
GameFileCache.LoadArchetypes = false;//to speed things up a little GameFileCache.LoadArchetypes = false;//to speed things up a little
GameFileCache.BuildExtendedJenkIndex = 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... GameFileCache.DoFullStringIndex = true;//to get all global text from DLC...

View File

@ -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) public void RenderPed(Ped ped)

View File

@ -75,13 +75,8 @@ namespace CodeWalker.Vehicles
MetaHash SelectedVehicleHash = 0;//base vehicle name hash Vehicle SelectedVehicle = new Vehicle();
MetaHash SelectedModelHash = 0;//yft name hash, can be _hi
VehicleInitData SelectedVehicleInit = null;
YftFile SelectedVehicleYft = null;
YcdFile ConvRoofDict = null;
ClipMapEntry ConvRoofClip = null;
bool PlayConvRoofAnim = false; bool PlayConvRoofAnim = false;
@ -289,6 +284,7 @@ namespace CodeWalker.Vehicles
} }
GameFileCache.EnableDlc = true; GameFileCache.EnableDlc = true;
GameFileCache.LoadPeds = false;
GameFileCache.LoadVehicles = true; GameFileCache.LoadVehicles = true;
GameFileCache.LoadArchetypes = false;//to speed things up a little GameFileCache.LoadArchetypes = false;//to speed things up a little
GameFileCache.BuildExtendedJenkIndex = 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() public void LoadVehicle()
{ {
var modelname = VehicleModelComboBox.Text; var name = VehicleModelComboBox.Text;
var modelnamel = modelname.ToLowerInvariant();
MetaHash modelhash = JenkHash.GenHash(modelnamel);
MetaHash modelhashhi = JenkHash.GenHash(modelnamel + "_hi");
bool hidet = VehicleHighDetailCheckBox.Checked; bool hidet = VehicleHighDetailCheckBox.Checked;
var yfthash = hidet ? modelhashhi : modelhash; bool vehiclechange = SelectedVehicle.Name != name;
VehicleInitData vid = null; SelectedVehicle.Init(name, GameFileCache, hidet);
if (GameFileCache.VehiclesInitDict.TryGetValue(modelhash, out vid))
if (SelectedVehicle.InitData != null)
{ {
bool vehiclechange = SelectedVehicleHash != modelhash; LoadModel(SelectedVehicle.Yft, vehiclechange);
ConvRoofDict = null; ConvRoofDictNameLabel.Text = SelectedVehicle.InitData.animConvRoofDictName;
ConvRoofClip = null; ConvRoofNameLabel.Text = SelectedVehicle.InitData.animConvRoofName;
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;
} }
VehicleMakeLabel.Text = SelectedVehicle.DisplayMake;
VehicleNameLabel.Text = SelectedVehicle.DisplayName;
ConvRoofPanel.Visible = SelectedVehicle.ConvRoofClip != null;
} }
public void LoadModel(YftFile yft, bool movecamera = true) public void LoadModel(YftFile yft, bool movecamera = true)
@ -926,39 +876,14 @@ namespace CodeWalker.Vehicles
private void RenderVehicle() private void RenderVehicle()
{ {
ClipMapEntry clip = null;
YftFile yft = GameFileCache.GetYft(SelectedModelHash); if (PlayConvRoofAnim)
if (yft != null)
{ {
if (yft.Loaded) clip = SelectedVehicle.ConvRoofClip;
{
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;
}
}
} }
Renderer.RenderVehicle(SelectedVehicle, clip);
} }

View File

@ -467,44 +467,40 @@ namespace CodeWalker.World
{ {
foreach (var obj in SceneObjects.Values) 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); ycd.CutsceneMap.TryGetValue(obj.AnimHash, out cme);
var pos = Position;
var rot = Rotation;
if (cme != null) if (cme != null)
{ {
cme.OverridePlayTime = true; cme.OverridePlayTime = true;
cme.PlayTime = cutOffset; cme.PlayTime = cutOffset;
updateObjectTransform(obj, cme, 0, 5, 6); //using root animation bone ids
updateObjectTransform(obj, cme, 0, 5, 6);
pos = pos + rot.Multiply(obj.Position); pos = pos + rot.Multiply(obj.Position);
rot = rot * obj.Rotation; rot = rot * obj.Rotation;
} }
}
if (obj.Ped != null)
{
obj.Ped.Position = pos; obj.Ped.Position = pos;
obj.Ped.Rotation = rot; obj.Ped.Rotation = rot;
obj.Ped.AnimClip = cme; obj.Ped.AnimClip = cme;
} }
if (obj.Prop != null) 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.Position = pos;
obj.Prop.Orientation = rot; obj.Prop.Orientation = rot;
obj.AnimClip = cme; 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); renderer.RenderArchetype(obj.Prop.Archetype, obj.Prop, null, true, obj.AnimClip);
} }
if (obj.Vehicle != null)
{
renderer.RenderVehicle(obj.Vehicle, obj.AnimClip);
}
} }
} }
@ -1026,13 +1026,15 @@ namespace CodeWalker.World
public Quaternion Rotation { get; set; } public Quaternion Rotation { get; set; }
public Ped Ped { get; set; } public Ped Ped { get; set; }
public YmapEntityDef Prop { get; set; } public YmapEntityDef Prop { get; set; }
public Vehicle Vehicle { get; set; }
public MetaHash AnimHash { get; set; } public MetaHash AnimHash { get; set; }
public ClipMapEntry AnimClip { get; set; } public ClipMapEntry AnimClip { get; set; }
public void Init(CutObject obj, GameFileCache gfc) public void Init(CutObject obj, GameFileCache gfc)
{ {
CutObject = obj; CutObject = obj;
@ -1141,7 +1143,12 @@ namespace CodeWalker.World
private void InitVehicle(CutVehicleModelObject veh, GameFileCache gfc) 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) private void InitWeapon(CutWeaponModelObject weap, GameFileCache gfc)