diff --git a/CodeWalker.Core/CodeWalker.Core.csproj b/CodeWalker.Core/CodeWalker.Core.csproj index ebe3724..757b713 100644 --- a/CodeWalker.Core/CodeWalker.Core.csproj +++ b/CodeWalker.Core/CodeWalker.Core.csproj @@ -143,6 +143,7 @@ + diff --git a/CodeWalker.Core/GameFiles/FileTypes/CacheDatFile.cs b/CodeWalker.Core/GameFiles/FileTypes/CacheDatFile.cs index a42b209..08ee6c0 100644 --- a/CodeWalker.Core/GameFiles/FileTypes/CacheDatFile.cs +++ b/CodeWalker.Core/GameFiles/FileTypes/CacheDatFile.cs @@ -118,7 +118,7 @@ namespace CodeWalker.GameFiles { } //just testing else { - dates.Add(new CacheFileDate(line));//eg: 2740459947 130680580712018938 8944 + dates.Add(new CacheFileDate(line));//eg: 2740459947 (hash of: platform:/data/cdimages/scaleform_frontend.rpf) 130680580712018938 8944 } break; } diff --git a/CodeWalker.Core/GameFiles/FileTypes/CutFile.cs b/CodeWalker.Core/GameFiles/FileTypes/CutFile.cs index 0064e6f..6fb5d61 100644 --- a/CodeWalker.Core/GameFiles/FileTypes/CutFile.cs +++ b/CodeWalker.Core/GameFiles/FileTypes/CutFile.cs @@ -101,6 +101,11 @@ namespace CodeWalker.GameFiles public CutConcatData[] concatDataList { get; set; } // PsoDataType.Array, 784, 1, (MetaName)2621475),//ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.rage__cutfCutsceneFile2__SConcatData), public CutHaltFrequency[] discardFrameList { get; set; } // PsoDataType.Array, 5280, 0, (MetaName)37)//ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.vHaltFrequency), + + public Dictionary ObjectsDict { get; set; } = new Dictionary(); + + + public override void ReadXml(XmlNode node) { fTotalDuration = Xml.GetChildFloatAttribute(node, "fTotalDuration", "value"); @@ -134,9 +139,98 @@ namespace CodeWalker.GameFiles sectionSplitList = Xml.GetChildRawFloatArray(node, "sectionSplitList"); concatDataList = XmlMeta.ReadItemArrayNullable(node, "concatDataList"); discardFrameList = XmlMeta.ReadItemArrayNullable(node, "discardFrameList"); + + AssociateObjects(); } + public void AssociateObjects() + { + ObjectsDict.Clear(); + if (pCutsceneObjects != null) + { + foreach (var obj in pCutsceneObjects) + { + if (obj is CutObject cobj) + { + ObjectsDict[cobj.iObjectId] = cobj; + } + } + } + + + CutEventArgs getEventArgs(int i) + { + if (i < 0) return null; + if (i >= pCutsceneEventArgsList?.Length) return null; + var args = pCutsceneEventArgsList[i]; + if (!(args is CutEventArgs)) + { } + return args as CutEventArgs; + } + CutObject getObject(int i) + { + CutObject o = null; + ObjectsDict.TryGetValue(i, out o); + return o; + } + + if (pCutsceneEventArgsList != null) + { + foreach (var arg in pCutsceneEventArgsList) + { + if (arg is CutObjectIdEventArgs oarg) + { + oarg.Object = getObject(oarg.iObjectId); + } + if (arg is CutObjectIdListEventArgs larg) + { + var objs = new CutObject[larg.iObjectIdList?.Length ?? 0]; + for (int i = 0; i < objs.Length; i++) + { + objs[i] = getObject(larg.iObjectIdList[i]); + } + larg.ObjectList = objs; + } + } + } + if (pCutsceneEventList != null) + { + foreach (var evt in pCutsceneEventList) + { + if (evt is CutObjectIdEvent oevt) + { + oevt.Object = getObject(oevt.iObjectId); + } + if (evt is CutEvent cevt) + { + cevt.EventArgs = getEventArgs(cevt.iEventArgsIndex); + } + else + { } + } + } + if (pCutsceneLoadEventList != null) + { + foreach (var evt in pCutsceneLoadEventList) + { + if (evt is CutObjectIdEvent oevt) + { + oevt.Object = getObject(oevt.iObjectId); + } + if (evt is CutEvent cevt) + { + cevt.EventArgs = getEventArgs(cevt.iEventArgsIndex); + } + else + { } + } + } + + } + + + public static CutBase ConstructObject(string type) { switch (type) @@ -233,6 +327,9 @@ namespace CodeWalker.GameFiles { UserData1 = (byte)Xml.GetChildUIntAttribute(node, "UserData1", "value"); UserData2 = (byte)Xml.GetChildUIntAttribute(node, "UserData2", "value"); + + if ((UserData1 != 0) || (UserData2 != 0)) + { } } public override string ToString() @@ -248,6 +345,9 @@ namespace CodeWalker.GameFiles public override void ReadXml(XmlNode node) { Items = CutsceneFile2.ReadObjectArray(node, "Items"); + + if (Items?.Length > 0) + { } } public override string ToString() @@ -358,7 +458,7 @@ namespace CodeWalker.GameFiles public override string ToString() { - return iObjectId.ToString() + ": " + base.ToString(); + return iObjectId.ToString() + ": " + base.ToString().Replace("CodeWalker.GameFiles.Cut", ""); } } [TC(typeof(EXP))] public class CutAssetManagerObject : CutObject // rage__cutfAssetManagerObject @@ -376,6 +476,11 @@ namespace CodeWalker.GameFiles base.ReadXml(node); cName = XmlMeta.GetHash(Xml.GetChildInnerText(node, "cName")); } + + public override string ToString() + { + return base.ToString() + ": " + cName.ToString(); + } } [TC(typeof(EXP))] public class CutCameraObject : CutNamedObject // rage__cutfCameraObject { @@ -726,19 +831,74 @@ namespace CodeWalker.GameFiles } + public enum CutEventType : int + { + LoadScene = 0, + LoadAnimation = 2, + LoadAudio = 4, + LoadModels = 6, + UnloadModels = 7, + LoadParticles = 8, + LoadOverlays = 10, + LoadGxt2 = 12, + EnableHideObject = 14, + DisableHideObject = 15, + EnableFixupModel = 16, + EnableBlockBounds = 18, + DisableBlockBounds = 19, + EnableScreenFade = 20, + DisableScreenFade = 21, + EnableAnimation = 22, + DisableAnimation = 23, + EnableParticleEffect = 24, + DisableParticleEffect = 25, + EnableOverlay = 26, + DisableOverlay = 27, + EnableAudio = 28, + DisableAudio = 29, + Subtitle = 30, + PedVariation = 34, + CameraCut = 43, + LoadRayfireDes = 46, + UnloadRayfireDes = 47, + EnableCamera = 48, + CameraUnk1 = 49, + CameraUnk2 = 50, + DisableCamera = 51, + DecalUnk1 = 52, + DecalUnk2 = 53, + CameraShadowCascade = 54, + CameraUnk3 = 55, + CameraUnk4 = 59, + CameraUnk5 = 63, + CameraUnk6 = 64, + PropUnk1 = 73, + EnableLight = 74, + DisableLight = 75, + CameraUnk7 = 76, + Unk1 = 77, + Unk2 = 78, + CameraUnk8 = 79, + VehicleUnk1 = 258, + PedUnk1 = 262, + } [TC(typeof(EXP))] public class CutEvent : CutBase // rage__cutfEvent { public float fTime { get; set; } // PsoDataType.Float, 16, 0, 0), - public int iEventId { get; set; } // PsoDataType.SInt, 20, 0, 0), + public CutEventType iEventId { get; set; } // PsoDataType.SInt, 20, 0, 0), public int iEventArgsIndex { get; set; } // PsoDataType.SInt, 24, 0, 0), - public object pChildEvents { get; set; } // PsoDataType.Structure, 32, 3, 0), + //public object pChildEvents { get; set; } // PsoDataType.Structure, 32, 3, 0), public uint StickyId { get; set; } // PsoDataType.UInt, 40, 0, 0), public bool IsChild { get; set; } // PsoDataType.Bool, 44, 0, 0) + public CutEventArgs EventArgs { get; set; } + + + public override void ReadXml(XmlNode node) { fTime = Xml.GetChildFloatAttribute(node, "fTime", "value"); - iEventId = Xml.GetChildIntAttribute(node, "iEventId", "value"); + iEventId = (CutEventType)Xml.GetChildIntAttribute(node, "iEventId", "value"); iEventArgsIndex = Xml.GetChildIntAttribute(node, "iEventArgsIndex", "value"); //pChildEvents = CutsceneFile2.ReadObject(node, "pChildEvents"); //seems never used StickyId = Xml.GetChildUIntAttribute(node, "StickyId", "value"); @@ -746,13 +906,20 @@ namespace CodeWalker.GameFiles var cNode = node.SelectSingleNode("pChildEvents"); if ((cNode?.ChildNodes?.Count > 0) || (cNode?.Attributes?.Count > 0)) - { } + { }//nothing gets here? + } + + public override string ToString() + { + return fTime.ToString("0.00") + " : " + iEventId.ToString(); } } [TC(typeof(EXP))] public class CutObjectIdEvent : CutEvent // rage__cutfObjectIdEvent { public int iObjectId { get; set; } // PsoDataType.SInt, 48, 0, 0) + public CutObject Object { get; set; } + public override void ReadXml(XmlNode node) { base.ReadXml(node); @@ -795,6 +962,8 @@ namespace CodeWalker.GameFiles { public int iObjectId { get; set; } // PsoDataType.SInt, 32, 0, 0) + public CutObject Object { get; set; } + public override void ReadXml(XmlNode node) { base.ReadXml(node); @@ -805,6 +974,8 @@ namespace CodeWalker.GameFiles { public int[] iObjectIdList { get; set; } // PsoDataType.Array, 32, 0, (MetaName)2)//ARRAYINFO, PsoDataType.SInt, 0, 0, 0), + public CutObject[] ObjectList { get; set; } + public override void ReadXml(XmlNode node) { base.ReadXml(node); diff --git a/CodeWalker.Core/GameFiles/FileTypes/YcdFile.cs b/CodeWalker.Core/GameFiles/FileTypes/YcdFile.cs index fa85720..afcd771 100644 --- a/CodeWalker.Core/GameFiles/FileTypes/YcdFile.cs +++ b/CodeWalker.Core/GameFiles/FileTypes/YcdFile.cs @@ -16,6 +16,7 @@ namespace CodeWalker.GameFiles public Dictionary ClipMap { get; set; } public Dictionary AnimMap { get; set; } + public Dictionary CutsceneMap { get; set; } //used for ycd's that are indexed in cutscenes, since name hashes all appended with -n public ClipMapEntry[] ClipMapEntries { get; set; } public AnimationMapEntry[] AnimMapEntries { get; set; } @@ -78,6 +79,29 @@ namespace CodeWalker.GameFiles } + public void BuildCutsceneMap(int cutIndex) + { + CutsceneMap = new Dictionary(); + + var replstr = "-" + cutIndex.ToString(); + + foreach (var cme in ClipMapEntries) + { + var sn = cme?.Clip?.ShortName ?? ""; + if (sn.EndsWith(replstr)) + { + sn = sn.Substring(0, sn.Length - replstr.Length); + } + if (sn.EndsWith("_dual")) + { + sn = sn.Substring(0, sn.Length - 5); + } + JenkIndex.Ensure(sn); + var h = JenkHash.GenHash(sn); + CutsceneMap[h] = cme; + } + } + diff --git a/CodeWalker.Core/GameFiles/GameFileCache.cs b/CodeWalker.Core/GameFiles/GameFileCache.cs index 3e6ba1e..8e713b7 100644 --- a/CodeWalker.Core/GameFiles/GameFileCache.cs +++ b/CodeWalker.Core/GameFiles/GameFileCache.cs @@ -48,6 +48,7 @@ namespace CodeWalker.GameFiles public Dictionary YbnDict { get; private set; } public Dictionary YcdDict { get; private set; } public Dictionary YnvDict { get; private set; } + public Dictionary Gxt2Dict { get; private set; } public Dictionary AllYmapsDict { get; private set; } @@ -1202,7 +1203,7 @@ namespace CodeWalker.GameFiles { var dat = RpfMan.GetFile(dlccachefile); if (dat == null) - { continue; } //update\\x64\\dlcpacks\\mpspecialraces\\dlc.rpf\\x64\\data\\cacheloaderdata_dlc\\mpspecialraces_3336915258_cache_y.dat + { continue; } //update\\x64\\dlcpacks\\mpspecialraces\\dlc.rpf\\x64\\data\\cacheloaderdata_dlc\\mpspecialraces_3336915258_cache_y.dat (hash of: mpspecialraces_interior_additions) AllCacheFiles.Add(dat); foreach (var node in dat.AllMapNodes) { @@ -1402,6 +1403,24 @@ namespace CodeWalker.GameFiles string langstr2 = "americandlc.rpf"; string langstr3 = "american.rpf"; + Gxt2Dict = new Dictionary(); + foreach (var rpf in AllRpfs) + { + foreach (var entry in rpf.AllEntries) + { + if (entry is RpfFileEntry fentry) + { + var p = entry.Path; + if (entry.NameLower.EndsWith(".gxt2") && (p.Contains(langstr) || p.Contains(langstr2) || p.Contains(langstr3))) + { + Gxt2Dict[entry.ShortNameHash] = fentry; + } + } + } + } + + + if (!DoFullStringIndex) { string globalgxt2path = "x64b.rpf\\data\\lang\\" + langstr + ".rpf\\global.gxt2"; @@ -1419,24 +1438,17 @@ namespace CodeWalker.GameFiles List gxt2files = new List(); - foreach (var rpf in AllRpfs) + foreach (var entry in Gxt2Dict.Values) { - foreach (var entry in rpf.AllEntries) + var gxt2 = RpfMan.GetFile(entry); + if (gxt2 != null) { - var p = entry.Path; - if (entry.NameLower.EndsWith(".gxt2") && (p.Contains(langstr)|| p.Contains(langstr2)|| p.Contains(langstr3))) + for (int i = 0; i < gxt2.TextEntries.Length; i++) { - 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); - } + var e = gxt2.TextEntries[i]; + GlobalText.Ensure(e.Text, e.Hash); } + gxt2files.Add(gxt2); } } diff --git a/CodeWalker.Core/GameFiles/MetaTypes/MetaNames.cs b/CodeWalker.Core/GameFiles/MetaTypes/MetaNames.cs index 8ff3453..7e6a3b5 100644 --- a/CodeWalker.Core/GameFiles/MetaTypes/MetaNames.cs +++ b/CodeWalker.Core/GameFiles/MetaTypes/MetaNames.cs @@ -3546,6 +3546,14 @@ namespace CodeWalker.GameFiles @null = 987444055, // how best to handle this? C# doesn't like it + exportcamera = 962998194, //cutscene related stuff + + + + + + + diff --git a/CodeWalker.Core/GameFiles/MetaTypes/PsoTypes.cs b/CodeWalker.Core/GameFiles/MetaTypes/PsoTypes.cs index 72e2b49..ad7576d 100644 --- a/CodeWalker.Core/GameFiles/MetaTypes/PsoTypes.cs +++ b/CodeWalker.Core/GameFiles/MetaTypes/PsoTypes.cs @@ -16276,7 +16276,7 @@ namespace CodeWalker.GameFiles { public MetaHash Name { get; set; } //0 Name: INT_0Bh: 0 public uint Unused0 { get; set; } //4 - public Array_uint Bounds { get; set; } //8 Bounds//3298223272: Array: 8: 1 {256: INT_0Bh: 0} + public Array_uint Bounds { get; set; } //8 Bounds: Array: 8: 1 {256: INT_0Bh: 0} public ushort Flags { get; set; } //24 Flags: SHORT_0Fh: 24: 2097155 public ushort Unused1 { get; set; }//26 public uint Unused2 { get; set; }//28 @@ -16379,7 +16379,7 @@ namespace CodeWalker.GameFiles { public MetaHash Name { get; set; } //0 Name: INT_0Bh: 0 public uint Unused0 { get; set; } //4 - public Array_uint Bounds { get; set; } //8 Bounds//3298223272: Array: 8: 1 {256: INT_0Bh: 0} + public Array_uint Bounds { get; set; } //8 Bounds: Array: 8: 1 {256: INT_0Bh: 0} public override string ToString() { diff --git a/CodeWalker.Core/GameFiles/Resources/Clip.cs b/CodeWalker.Core/GameFiles/Resources/Clip.cs index 2f01959..2cdab41 100644 --- a/CodeWalker.Core/GameFiles/Resources/Clip.cs +++ b/CodeWalker.Core/GameFiles/Resources/Clip.cs @@ -876,6 +876,70 @@ namespace CodeWalker.GameFiles AssignSequenceBoneIds(); } + + + + public struct FramePosition + { + public int Frame0; + public int Frame1; + public float Alpha0; + public float Alpha1; + } + public FramePosition GetFramePosition(float t) + { + bool ignoreLastFrame = true;//if last frame is equivalent to the first one, eg rollercoaster small light "globes" don't + + FramePosition p = new FramePosition(); + var nframes = (ignoreLastFrame) ? (Frames - 1) : Frames; + + var curPos = (t / Duration) * nframes; + p.Frame0 = ((ushort)curPos) % Frames; + p.Frame1 = (p.Frame0 + 1);// % frames; + p.Alpha1 = (float)(curPos - Math.Floor(curPos)); + p.Alpha0 = 1.0f - p.Alpha1; + + return p; + } + public Vector4 EvaluateVector4(FramePosition frame, int boneIndex, bool interpolate) + { + var s = frame.Frame0 / SequenceFrameLimit; + int f0 = frame.Frame0 % SequenceFrameLimit; + int f1 = f0 + 1; + var seq = Sequences.data_items[s]; + var aseq = seq.Sequences[boneIndex]; + var v0 = aseq.EvaluateVector(f0); + var v1 = aseq.EvaluateVector(f1); + var v = interpolate ? (v0 * frame.Alpha0) + (v1 * frame.Alpha1) : v0; + return v; + } + public Quaternion EvaluateQuaternion(FramePosition frame, int boneIndex, bool interpolate) + { + var s = frame.Frame0 / SequenceFrameLimit; + int f0 = frame.Frame0 % SequenceFrameLimit; + int f1 = f0 + 1; + var seq = Sequences.data_items[s]; + var aseq = seq.Sequences[boneIndex]; + var q0 = aseq.EvaluateQuaternion(f0); + var q1 = aseq.EvaluateQuaternion(f1); + var q = interpolate ? Quaternion.Slerp(q0, q1, frame.Alpha1) : q0; + return q; + } + + public int FindBoneIndex(ushort boneTag, byte track) + { + //TODO: make this use a dict?? + if (BoneIds?.data_items != null) + { + for (int i = 0; i < BoneIds.data_items.Length; i++) + { + var b = BoneIds.data_items[i]; + if ((b.BoneId == boneTag) && (b.Track == track)) return i; + } + } + return -1; + } + } [TypeConverter(typeof(ExpandableObjectConverter))] public struct AnimationBoneId : IMetaXmlItem { diff --git a/CodeWalker.Core/GameFiles/Resources/Drawable.cs b/CodeWalker.Core/GameFiles/Resources/Drawable.cs index 791bb48..e622573 100644 --- a/CodeWalker.Core/GameFiles/Resources/Drawable.cs +++ b/CodeWalker.Core/GameFiles/Resources/Drawable.cs @@ -119,14 +119,14 @@ namespace CodeWalker.GameFiles // structure data public ulong ParametersPointer { get; set; } - public MetaHash Name { get; set; } //530103687, 2401522793, 1912906641 + public MetaHash Name { get; set; } //decal_emissive_only, emissive, spec public uint Unknown_Ch { get; set; } // 0x00000000 public byte ParameterCount { get; set; } public byte RenderBucket { get; set; } // 2, 0, public ushort Unknown_12h { get; set; } // 32768 HasComment? public ushort ParameterSize { get; set; } //112, 208, 320 (with 16h) 10485872, 17826000, 26214720 public ushort ParameterDataSize { get; set; } //160, 272, 400 - public MetaHash FileName { get; set; } //2918136469, 2635608835, 2247429097 + public MetaHash FileName { get; set; } //decal_emissive_only.sps, emissive.sps, spec.sps public uint Unknown_1Ch { get; set; } // 0x00000000 public uint RenderBucketMask { get; set; } //65284, 65281 DrawBucketMask? (1< DrawableFilesDict { get; set; } = null; + public Dictionary TextureFilesDict { get; set; } = null; + public RpfFileEntry[] DrawableFiles { get; set; } = null; + public RpfFileEntry[] TextureFiles { get; set; } = null; + public ClipMapEntry AnimClip { get; set; } = null; + public string[] DrawableNames { get; set; } = new string[12]; + public Drawable[] Drawables { get; set; } = new Drawable[12]; + public Texture[] Textures { get; set; } = new Texture[12]; + public bool EnableRootMotion { get; set; } = false; //used to toggle whether or not to include root motion when playing animations + + public Vector3 Position { get; set; } = Vector3.Zero; + public Quaternion Rotation { get; set; } = Quaternion.Identity; + + + public void Init(string name, GameFileCache gfc) + { + var hash = JenkHash.GenHash(name.ToLowerInvariant()); + Init(hash, gfc); + Name = name; + } + public void Init(MetaHash pedhash, GameFileCache gfc) + { + + Name = string.Empty; + NameHash = 0; + InitData = null; + Ydd = null; + Ytd = null; + Ycd = null; + Yft = null; + Ymt = null; + AnimClip = null; + for (int i = 0; i < 12; i++) + { + Drawables[i] = null; + Textures[i] = null; + } + + + CPedModelInfo__InitData initdata = null; + if (!gfc.PedsInitDict.TryGetValue(pedhash, out initdata)) return; + + var ycdhash = JenkHash.GenHash(initdata.ClipDictionaryName.ToLowerInvariant()); + + //bool pedchange = NameHash != pedhash; + //Name = pedname; + NameHash = pedhash; + InitData = initdata; + Ydd = gfc.GetYdd(pedhash); + Ytd = gfc.GetYtd(pedhash); + Ycd = gfc.GetYcd(ycdhash); + Yft = gfc.GetYft(pedhash); + + PedFile pedFile = null; + gfc.PedVariationsDict?.TryGetValue(pedhash, out pedFile); + Ymt = pedFile; + + Dictionary 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(); + + + while ((Ydd != null) && (!Ydd.Loaded)) + { + Thread.Sleep(20);//kinda hacky + Ydd = gfc.GetYdd(pedhash); + } + while ((Ytd != null) && (!Ytd.Loaded)) + { + Thread.Sleep(20);//kinda hacky + Ytd = gfc.GetYtd(pedhash); + } + while ((Ycd != null) && (!Ycd.Loaded)) + { + Thread.Sleep(20);//kinda hacky + Ycd = gfc.GetYcd(ycdhash); + } + while ((Yft != null) && (!Yft.Loaded)) + { + Thread.Sleep(20);//kinda hacky + Yft = gfc.GetYft(pedhash); + } + + + MetaHash cliphash = JenkHash.GenHash("idle"); + ClipMapEntry cme = null; + Ycd?.ClipMap?.TryGetValue(cliphash, out cme); + AnimClip = cme; + + } + + + + } +} diff --git a/CodeWalker.Core/World/Space.cs b/CodeWalker.Core/World/Space.cs index ae2b6ef..98eee1d 100644 --- a/CodeWalker.Core/World/Space.cs +++ b/CodeWalker.Core/World/Space.cs @@ -150,9 +150,9 @@ namespace CodeWalker.World //foreach (var dg in dataGroupDict.Values) //{ // sb.AppendLine(dg.ToString()); - // if (dg.YBNHashes_3298223272 != null) + // if (dg.Bounds != null) // { - // foreach (var ybnh in dg.YBNHashes_3298223272) + // foreach (var ybnh in dg.Bounds) // { // sb.AppendLine(" " + ybnh.ToString()); // } diff --git a/CodeWalker.csproj b/CodeWalker.csproj index f7c74b7..59a671c 100644 --- a/CodeWalker.csproj +++ b/CodeWalker.csproj @@ -540,6 +540,12 @@ SelectFolderForm.cs + + Form + + + CutsceneForm.cs + Form @@ -794,6 +800,9 @@ SelectFolderForm.cs + + CutsceneForm.cs + SettingsForm.cs diff --git a/Forms/YcdForm.Designer.cs b/Forms/YcdForm.Designer.cs index 274e64c..bdb2d88 100644 --- a/Forms/YcdForm.Designer.cs +++ b/Forms/YcdForm.Designer.cs @@ -160,7 +160,7 @@ this.XmlTextBox.AutoIndentChars = false; this.XmlTextBox.AutoIndentCharsPatterns = ""; this.XmlTextBox.AutoIndentExistingLines = false; - this.XmlTextBox.AutoScrollMinSize = new System.Drawing.Size(27, 14); + this.XmlTextBox.AutoScrollMinSize = new System.Drawing.Size(2, 14); this.XmlTextBox.BackBrush = null; this.XmlTextBox.CharHeight = 14; this.XmlTextBox.CharWidth = 8; @@ -169,7 +169,6 @@ this.XmlTextBox.DelayedEventsInterval = 1; this.XmlTextBox.DisabledColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(180)))), ((int)(((byte)(180)))), ((int)(((byte)(180))))); this.XmlTextBox.Dock = System.Windows.Forms.DockStyle.Fill; - this.XmlTextBox.Font = new System.Drawing.Font("Courier New", 9.75F); this.XmlTextBox.IsReplaceMode = false; this.XmlTextBox.Language = FastColoredTextBoxNS.Language.XML; this.XmlTextBox.LeftBracket = '<'; diff --git a/PedsForm.cs b/PedsForm.cs index 929a311..e2e7bb4 100644 --- a/PedsForm.cs +++ b/PedsForm.cs @@ -64,7 +64,6 @@ namespace CodeWalker.Peds int toolsPanelResizeStartLeft = 0; int toolsPanelResizeStartRight = 0; - Dictionary DrawableDrawFlags = new Dictionary(); bool enableGrid = false; float gridSize = 1.0f; @@ -75,28 +74,8 @@ namespace CodeWalker.Peds - [TypeConverter(typeof(ExpandableObjectConverter))] public class PedSelection - { - public string Name { get; set; } = string.Empty; - public MetaHash NameHash { get; set; } = 0;//ped name hash - public CPedModelInfo__InitData InitData { get; set; } = null; //ped init data - public YddFile Ydd { get; set; } = null; //ped drawables - public YtdFile Ytd { get; set; } = null; //ped textures - public YcdFile Ycd { get; set; } = null; //ped animations - public YftFile Yft { get; set; } = null; //ped skeleton YFT - public PedFile Ymt { get; set; } = null; //ped variation info - public Dictionary DrawableFilesDict { get; set; } = null; - public Dictionary TextureFilesDict { get; set; } = null; - public RpfFileEntry[] DrawableFiles { get; set; } = null; - public RpfFileEntry[] TextureFiles { get; set; } = null; - public ClipMapEntry AnimClip { get; set; } = null; - public string[] DrawableNames { get; set; } = new string[12]; - public Drawable[] Drawables { get; set; } = new Drawable[12]; - public Texture[] Textures { get; set; } = new Texture[12]; - public bool EnableRootMotion { get; set; } = false; //used to toggle whether or not to include root motion when playing animations - } - PedSelection SelectedPed = new PedSelection(); + Ped SelectedPed = new Ped(); ComboBox[] ComponentComboBoxes = null; @@ -256,7 +235,7 @@ namespace CodeWalker.Peds Renderer.SelectedDrawable = null;// SelectedItem.Drawable; - RenderPed(); + Renderer.RenderPed(SelectedPed); //UpdateMouseHitsFromRenderer(); //RenderSelection(); @@ -616,14 +595,14 @@ namespace CodeWalker.Peds { if (rem) { - if (DrawableDrawFlags.ContainsKey(drwbl)) + if (Renderer.SelectionDrawableDrawFlags.ContainsKey(drwbl)) { - DrawableDrawFlags.Remove(drwbl); + Renderer.SelectionDrawableDrawFlags.Remove(drwbl); } } else { - DrawableDrawFlags[drwbl] = false; + Renderer.SelectionDrawableDrawFlags[drwbl] = false; } } if (model != null) @@ -709,7 +688,7 @@ namespace CodeWalker.Peds { //TODO: change to go through each component and add/update/remove treeview item accordingly? - DrawableDrawFlags.Clear(); + Renderer.SelectionDrawableDrawFlags.Clear(); Renderer.SelectionModelDrawFlags.Clear(); Renderer.SelectionGeometryDrawFlags.Clear(); ModelsTreeView.Nodes.Clear(); @@ -739,75 +718,17 @@ namespace CodeWalker.Peds public void LoadPed() { var pedname = PedNameComboBox.Text; - var pednamel = pedname.ToLowerInvariant(); - MetaHash pedhash = JenkHash.GenHash(pednamel); + var pedhash = JenkHash.GenHash(pedname.ToLowerInvariant()); + var pedchange = SelectedPed.NameHash != pedhash; - SelectedPed.Name = string.Empty; - SelectedPed.NameHash = 0; - SelectedPed.InitData = null; - SelectedPed.Ydd = null; - SelectedPed.Ytd = null; - SelectedPed.Ycd = null; - SelectedPed.Yft = null; - SelectedPed.Ymt = null; - SelectedPed.AnimClip = null; for (int i = 0; i < 12; i++) { ClearCombo(ComponentComboBoxes[i]); - SelectedPed.Drawables[i] = null; - SelectedPed.Textures[i] = null; } DetailsPropertyGrid.SelectedObject = null; - - CPedModelInfo__InitData initdata = null; - if (!GameFileCache.PedsInitDict.TryGetValue(pedhash, out initdata)) return; - - var ycdhash = JenkHash.GenHash(initdata.ClipDictionaryName.ToLowerInvariant()); - - bool pedchange = SelectedPed.NameHash != pedhash; - SelectedPed.Name = pedname; - SelectedPed.NameHash = pedhash; - SelectedPed.InitData = initdata; - SelectedPed.Ydd = GameFileCache.GetYdd(pedhash); - SelectedPed.Ytd = GameFileCache.GetYtd(pedhash); - SelectedPed.Ycd = GameFileCache.GetYcd(ycdhash); - SelectedPed.Yft = GameFileCache.GetYft(pedhash); - - PedFile pedFile = null; - GameFileCache.PedVariationsDict?.TryGetValue(pedhash, out pedFile); - SelectedPed.Ymt = pedFile; - - Dictionary peddict = null; - GameFileCache.PedDrawableDicts.TryGetValue(SelectedPed.NameHash, out peddict); - SelectedPed.DrawableFilesDict = peddict; - SelectedPed.DrawableFiles = SelectedPed.DrawableFilesDict?.Values.ToArray(); - GameFileCache.PedTextureDicts.TryGetValue(SelectedPed.NameHash, out peddict); - SelectedPed.TextureFilesDict = peddict; - SelectedPed.TextureFiles = SelectedPed.TextureFilesDict?.Values.ToArray(); - - - while ((SelectedPed.Ydd != null) && (!SelectedPed.Ydd.Loaded)) - { - Thread.Sleep(20);//kinda hacky - SelectedPed.Ydd = GameFileCache.GetYdd(pedhash); - } - while ((SelectedPed.Ytd != null) && (!SelectedPed.Ytd.Loaded)) - { - Thread.Sleep(20);//kinda hacky - SelectedPed.Ytd = GameFileCache.GetYtd(pedhash); - } - while ((SelectedPed.Ycd != null) && (!SelectedPed.Ycd.Loaded)) - { - Thread.Sleep(20);//kinda hacky - SelectedPed.Ycd = GameFileCache.GetYcd(ycdhash); - } - while ((SelectedPed.Yft != null) && (!SelectedPed.Yft.Loaded)) - { - Thread.Sleep(20);//kinda hacky - SelectedPed.Yft = GameFileCache.GetYft(pedhash); - } + SelectedPed.Init(pedname, GameFileCache); LoadModel(SelectedPed.Yft, pedchange); @@ -821,14 +742,8 @@ namespace CodeWalker.Peds } } - - ClipDictComboBox.Text = SelectedPed.InitData?.ClipDictionaryName ?? ""; ClipComboBox.Text = "idle"; - MetaHash cliphash = JenkHash.GenHash("idle"); - ClipMapEntry cme = null; - SelectedPed.Ycd?.ClipMap?.TryGetValue(cliphash, out cme); - SelectedPed.AnimClip = cme; DetailsPropertyGrid.SelectedObject = SelectedPed; @@ -1208,96 +1123,6 @@ namespace CodeWalker.Peds - private void RenderPed() - { - - YftFile yft = SelectedPed.Yft;// GameFileCache.GetYft(SelectedModelHash); - if (yft != null) - { - if (yft.Loaded) - { - if (yft.Fragment != null) - { - //var f = yft.Fragment; - //var txdhash = 0u;// SelectedVehicleHash;// yft.RpfFileEntry?.ShortNameHash ?? 0; - //var namelower = yft.RpfFileEntry?.GetShortNameLower(); - //Archetype arch = null;// TryGetArchetype(hash); - //Renderer.RenderFragment(arch, null, f, txdhash); - //seldrwbl = f.Drawable; - } - } - - - var vi = SelectedPed.Ymt?.VariationInfo; - if (vi != null) - { - for (int i = 0; i < 12; i++) - { - RenderPedComponent(i); - } - } - - } - - } - - private void RenderPedComponent(int i) - { - //var compData = SelectedPed.Ymt?.VariationInfo?.GetComponentData(i); - var drawable = SelectedPed.Drawables[i]; - var texture = SelectedPed.Textures[i]; - - //if (compData == null) return; - if (drawable == null) return; - - var td = SelectedPed.Ytd?.TextureDict; - var ac = SelectedPed.AnimClip; - if (ac != null) - { - ac.EnableRootMotion = SelectedPed.EnableRootMotion; - } - - var skel = SelectedPed.Yft?.Fragment?.Drawable?.Skeleton; - if (skel != null) - { - if (drawable.Skeleton == null) - { - drawable.Skeleton = skel;//force the drawable to use this skeleton. - } - else if (drawable.Skeleton != skel) - { - var dskel = drawable.Skeleton; //put the bones of the fragment into the drawable. drawable's bones in this case seem messed up! - for (int b = 0; b < skel.Bones.Count; b++) - { - var srcbone = skel.Bones[b]; - var dstbone = srcbone; - if (dskel.BonesMap.TryGetValue(srcbone.Tag, out dstbone)) - { - if (srcbone == dstbone) break; //bone reassignment already done! - dskel.Bones[dstbone.Index] = srcbone; - dskel.BonesMap[srcbone.Tag] = srcbone; - } - } - } - } - - - bool drawFlag = true; - if (!DrawableDrawFlags.TryGetValue(drawable, out drawFlag)) - { drawFlag = true; } - - if (drawFlag) - { - Renderer.RenderDrawable(drawable, null, null, 0, td, texture, ac); - } - - - } - - - - - diff --git a/Project/ProjectForm.cs b/Project/ProjectForm.cs index e65d34e..c7375dd 100644 --- a/Project/ProjectForm.cs +++ b/Project/ProjectForm.cs @@ -5038,7 +5038,7 @@ namespace CodeWalker.Project room.NameHash = JenkHash.GenHash(room.Name); room.Flags0 = 0xAAAAAAAA; - room.Unk06 = 3817852694;//?? + room.Unk06 = (uint)MetaName.null_sound; room.Unk14 = 3565506855;//? diff --git a/Rendering/Renderable.cs b/Rendering/Renderable.cs index c2db1b0..e983107 100644 --- a/Rendering/Renderable.cs +++ b/Rendering/Renderable.cs @@ -483,18 +483,8 @@ namespace CodeWalker.Rendering { return; } bool interpolate = true; //how to know? eg. cs4_14_hickbar_anim shouldn't - bool ignoreLastFrame = true;//if last frame is equivalent to the first one, eg rollercoaster small light "globes" don't - - var duration = anim.Duration; - var frames = anim.Frames; - var nframes = (ignoreLastFrame) ? (frames - 1) : frames; - - var curPos = (t/duration) * nframes; - var frame0 = ((ushort)curPos) % frames; - var frame1 = (frame0 + 1);// % frames; - var falpha = (float)(curPos - Math.Floor(curPos)); - var ialpha = 1.0f - falpha; + var frame = anim.GetFramePosition(t); var dwbl = this.Key; var skel = dwbl?.Skeleton; @@ -502,8 +492,8 @@ namespace CodeWalker.Rendering if (bones == null) { return; } - Vector4 v0, v1, v; - Quaternion q0, q1, q; + Vector4 v; + Quaternion q; for (int i = 0; i < anim.BoneIds.data_items.Length; i++) { @@ -513,50 +503,38 @@ namespace CodeWalker.Rendering Bone bone = null; skel?.BonesMap?.TryGetValue(boneiditem.BoneId, out bone); if (bone == null) - { continue; } + { + continue; + //skel.BoneTagsMap?.TryGetValue(boneiditem.BoneId, out bone); + //if (bone == null) + //{ continue; } + } - var sfl = anim.SequenceFrameLimit; - var s = frame0 / sfl; - int f0 = frame0 % sfl; - int f1 = f0 + 1; - - var seq = anim.Sequences.data_items[s]; - var aseq = seq.Sequences[i]; switch (track) { case 0: //bone position - v0 = aseq.EvaluateVector(f0); - v1 = aseq.EvaluateVector(f1); - v = interpolate ? (v0 * ialpha) + (v1 * falpha) : v0; + v = anim.EvaluateVector4(frame, i, interpolate); bone.AnimTranslation = v.XYZ(); break; case 1: //bone orientation - q0 = aseq.EvaluateQuaternion(f0); - q1 = aseq.EvaluateQuaternion(f1); - q = interpolate ? Quaternion.Slerp(q0, q1, falpha) : q0; + q = anim.EvaluateQuaternion(frame, i, interpolate); bone.AnimRotation = q; break; case 2: //scale? - v0 = aseq.EvaluateVector(f0); - v1 = aseq.EvaluateVector(f1); - v = interpolate ? (v0 * ialpha) + (v1 * falpha) : v0; + v = anim.EvaluateVector4(frame, i, interpolate); bone.AnimScale = v.XYZ(); break; case 5://root motion vector if (EnableRootMotion) { - v0 = aseq.EvaluateVector(f0); - v1 = aseq.EvaluateVector(f1); - v = interpolate ? (v0 * ialpha) + (v1 * falpha) : v0; + v = anim.EvaluateVector4(frame, i, interpolate); bone.AnimTranslation += v.XYZ(); } break; case 6://quaternion... root rotation if (EnableRootMotion) { - q0 = aseq.EvaluateQuaternion(f0); - q1 = aseq.EvaluateQuaternion(f1); - q = interpolate ? Quaternion.Slerp(q0, q1, falpha) : q0; + q = anim.EvaluateQuaternion(frame, i, interpolate); bone.AnimRotation = q * bone.AnimRotation; } break; @@ -564,6 +542,12 @@ namespace CodeWalker.Rendering break; case 8://quaternion... (camera rotation?) break; + case 24://face stuff? + break; + case 25://face stuff? + break; + case 26://face stuff? + break; case 27: case 50: case 134://single float? @@ -655,17 +639,8 @@ namespace CodeWalker.Rendering { return; } bool interpolate = true; //how to know? eg. cs4_14_hickbar_anim shouldn't - bool ignoreLastFrame = true;//if last frame is equivalent to the first one, eg rollercoaster small light "globes" don't - var duration = anim.Duration; - var frames = anim.Frames; - var nframes = (ignoreLastFrame) ? (frames - 1) : frames; - - var curPos = (t / duration) * nframes; - var frame0 = ((ushort)curPos) % frames; - var frame1 = (frame0 + 1);// % frames; - var falpha = (float)(curPos - Math.Floor(curPos)); - var ialpha = 1.0f - falpha; + var frame = anim.GetFramePosition(t); var globalAnimUV0 = new Vector4(1.0f, 0.0f, 0.0f, 0.0f); var globalAnimUV1 = new Vector4(0.0f, 1.0f, 0.0f, 0.0f); @@ -678,16 +653,8 @@ namespace CodeWalker.Rendering if ((track != 17) && (track != 18)) { continue; }//17 and 18 would be UV0 and UV1 - var sfl = anim.SequenceFrameLimit; - var s = frame0 / sfl; - int f0 = frame0 % sfl; - int f1 = f0 + 1; + var v = anim.EvaluateVector4(frame, i, interpolate); - var seq = anim.Sequences.data_items[s]; - var aseq = seq.Sequences[i]; - var v0 = aseq.EvaluateVector(f0); - var v1 = aseq.EvaluateVector(f1); - var v = interpolate ? (v0 * ialpha) + (v1 * falpha) : v0; switch (track) { case 17: globalAnimUV0 = v; break; //could be overwriting values here... diff --git a/Rendering/Renderer.cs b/Rendering/Renderer.cs index 1bca9af..d3274f1 100644 --- a/Rendering/Renderer.cs +++ b/Rendering/Renderer.cs @@ -138,6 +138,7 @@ namespace CodeWalker.Rendering private YmapEntityDef SelectedCarGenEntity = new YmapEntityDef(); //placeholder entity object for drawing cars public DrawableBase SelectedDrawable = null; + public Dictionary SelectionDrawableDrawFlags = new Dictionary(); public Dictionary SelectionModelDrawFlags = new Dictionary(); public Dictionary SelectionGeometryDrawFlags = new Dictionary(); public bool SelectionFlagsTestAll = false; //to test all renderables for draw flags; for model form @@ -2718,6 +2719,97 @@ namespace CodeWalker.Rendering + public void RenderPed(Ped ped) + { + + YftFile yft = ped.Yft;// GameFileCache.GetYft(SelectedModelHash); + if (yft != null) + { + if (yft.Loaded) + { + if (yft.Fragment != null) + { + //var f = yft.Fragment; + //var txdhash = 0u;// SelectedVehicleHash;// yft.RpfFileEntry?.ShortNameHash ?? 0; + //var namelower = yft.RpfFileEntry?.GetShortNameLower(); + //Archetype arch = null;// TryGetArchetype(hash); + //Renderer.RenderFragment(arch, null, f, txdhash); + //seldrwbl = f.Drawable; + } + } + + + var vi = ped.Ymt?.VariationInfo; + if (vi != null) + { + for (int i = 0; i < 12; i++) + { + RenderPedComponent(ped, i); + } + } + + } + + } + + private void RenderPedComponent(Ped ped, int i) + { + //var compData = ped.Ymt?.VariationInfo?.GetComponentData(i); + var drawable = ped.Drawables[i]; + var texture = ped.Textures[i]; + + //if (compData == null) return; + if (drawable == null) return; + + var td = ped.Ytd?.TextureDict; + var ac = ped.AnimClip; + if (ac != null) + { + ac.EnableRootMotion = ped.EnableRootMotion; + } + + var skel = ped.Yft?.Fragment?.Drawable?.Skeleton; + if (skel != null) + { + if (drawable.Skeleton == null) + { + drawable.Skeleton = skel;//force the drawable to use this skeleton. + } + else if (drawable.Skeleton != skel) + { + var dskel = drawable.Skeleton; //put the bones of the fragment into the drawable. drawable's bones in this case seem messed up! + for (int b = 0; b < skel.Bones.Count; b++) + { + var srcbone = skel.Bones[b]; + var dstbone = srcbone; + if (dskel.BonesMap.TryGetValue(srcbone.Tag, out dstbone)) + { + if (srcbone == dstbone) break; //bone reassignment already done! + dskel.Bones[dstbone.Index] = srcbone; + dskel.BonesMap[srcbone.Tag] = srcbone; + } + } + } + } + + + bool drawFlag = true; + if (!SelectionDrawableDrawFlags.TryGetValue(drawable, out drawFlag)) + { drawFlag = true; } + + if (drawFlag) + { + RenderDrawable(drawable, null, null, 0, td, texture, ac); + } + + + } + + + + + + private void RenderInteriorCollisionMesh(YmapEntityDef mlo) diff --git a/World/CutsceneForm.Designer.cs b/World/CutsceneForm.Designer.cs new file mode 100644 index 0000000..4a02b8a --- /dev/null +++ b/World/CutsceneForm.Designer.cs @@ -0,0 +1,203 @@ +namespace CodeWalker.World +{ + partial class CutsceneForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CutsceneForm)); + this.label3 = new System.Windows.Forms.Label(); + this.CutsceneComboBox = new System.Windows.Forms.ComboBox(); + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.CutsceneTreeView = new System.Windows.Forms.TreeView(); + this.InfoPropertyGrid = new System.Windows.Forms.PropertyGrid(); + this.AnimateCameraCheckBox = new System.Windows.Forms.CheckBox(); + this.TimeTrackBar = new System.Windows.Forms.TrackBar(); + this.TimeLabel = new System.Windows.Forms.Label(); + this.PlayStopButton = new System.Windows.Forms.Button(); + this.PlaybackTimer = new System.Windows.Forms.Timer(this.components); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); + this.splitContainer1.Panel1.SuspendLayout(); + this.splitContainer1.Panel2.SuspendLayout(); + this.splitContainer1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.TimeTrackBar)).BeginInit(); + this.SuspendLayout(); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(10, 10); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(55, 13); + this.label3.TabIndex = 3; + this.label3.Text = "Cutscene:"; + // + // CutsceneComboBox + // + this.CutsceneComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.CutsceneComboBox.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; + this.CutsceneComboBox.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; + this.CutsceneComboBox.FormattingEnabled = true; + this.CutsceneComboBox.Location = new System.Drawing.Point(71, 7); + this.CutsceneComboBox.Name = "CutsceneComboBox"; + this.CutsceneComboBox.Size = new System.Drawing.Size(529, 21); + this.CutsceneComboBox.TabIndex = 2; + this.CutsceneComboBox.SelectedIndexChanged += new System.EventHandler(this.CutsceneComboBox_SelectedIndexChanged); + // + // splitContainer1 + // + this.splitContainer1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.splitContainer1.Location = new System.Drawing.Point(1, 70); + this.splitContainer1.Name = "splitContainer1"; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add(this.CutsceneTreeView); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.Controls.Add(this.InfoPropertyGrid); + this.splitContainer1.Size = new System.Drawing.Size(722, 330); + this.splitContainer1.SplitterDistance = 259; + this.splitContainer1.TabIndex = 4; + // + // CutsceneTreeView + // + this.CutsceneTreeView.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.CutsceneTreeView.Dock = System.Windows.Forms.DockStyle.Fill; + this.CutsceneTreeView.FullRowSelect = true; + this.CutsceneTreeView.HideSelection = false; + this.CutsceneTreeView.Location = new System.Drawing.Point(0, 0); + this.CutsceneTreeView.Name = "CutsceneTreeView"; + this.CutsceneTreeView.ShowLines = false; + this.CutsceneTreeView.ShowRootLines = false; + this.CutsceneTreeView.Size = new System.Drawing.Size(259, 330); + this.CutsceneTreeView.TabIndex = 1; + this.CutsceneTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.CutsceneTreeView_AfterSelect); + // + // InfoPropertyGrid + // + this.InfoPropertyGrid.Dock = System.Windows.Forms.DockStyle.Fill; + this.InfoPropertyGrid.HelpVisible = false; + this.InfoPropertyGrid.Location = new System.Drawing.Point(0, 0); + this.InfoPropertyGrid.Name = "InfoPropertyGrid"; + this.InfoPropertyGrid.Size = new System.Drawing.Size(459, 330); + this.InfoPropertyGrid.TabIndex = 0; + // + // AnimateCameraCheckBox + // + this.AnimateCameraCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.AnimateCameraCheckBox.AutoSize = true; + this.AnimateCameraCheckBox.Checked = true; + this.AnimateCameraCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.AnimateCameraCheckBox.Location = new System.Drawing.Point(617, 9); + this.AnimateCameraCheckBox.Name = "AnimateCameraCheckBox"; + this.AnimateCameraCheckBox.Size = new System.Drawing.Size(102, 17); + this.AnimateCameraCheckBox.TabIndex = 5; + this.AnimateCameraCheckBox.Text = "Animate camera"; + this.AnimateCameraCheckBox.UseVisualStyleBackColor = true; + this.AnimateCameraCheckBox.CheckedChanged += new System.EventHandler(this.AnimateCameraCheckBox_CheckedChanged); + // + // TimeTrackBar + // + this.TimeTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TimeTrackBar.AutoSize = false; + this.TimeTrackBar.Location = new System.Drawing.Point(91, 34); + this.TimeTrackBar.Maximum = 100; + this.TimeTrackBar.Name = "TimeTrackBar"; + this.TimeTrackBar.Size = new System.Drawing.Size(509, 30); + this.TimeTrackBar.TabIndex = 7; + // + // TimeLabel + // + this.TimeLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.TimeLabel.AutoSize = true; + this.TimeLabel.Location = new System.Drawing.Point(614, 41); + this.TimeLabel.Name = "TimeLabel"; + this.TimeLabel.Size = new System.Drawing.Size(60, 13); + this.TimeLabel.TabIndex = 8; + this.TimeLabel.Text = "0.00 / 0.00"; + // + // PlayStopButton + // + this.PlayStopButton.Location = new System.Drawing.Point(10, 36); + this.PlayStopButton.Name = "PlayStopButton"; + this.PlayStopButton.Size = new System.Drawing.Size(75, 23); + this.PlayStopButton.TabIndex = 9; + this.PlayStopButton.Text = "Play"; + this.PlayStopButton.UseVisualStyleBackColor = true; + this.PlayStopButton.Click += new System.EventHandler(this.PlayStopButton_Click); + // + // PlaybackTimer + // + this.PlaybackTimer.Tick += new System.EventHandler(this.PlaybackTimer_Tick); + // + // CutsceneForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(724, 401); + this.Controls.Add(this.PlayStopButton); + this.Controls.Add(this.TimeLabel); + this.Controls.Add(this.TimeTrackBar); + this.Controls.Add(this.AnimateCameraCheckBox); + this.Controls.Add(this.splitContainer1); + this.Controls.Add(this.label3); + this.Controls.Add(this.CutsceneComboBox); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "CutsceneForm"; + this.Text = "Cutscene Viewer - CodeWalker by dexyfex"; + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.CutsceneForm_FormClosed); + this.Load += new System.EventHandler(this.CutsceneForm_Load); + this.splitContainer1.Panel1.ResumeLayout(false); + this.splitContainer1.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); + this.splitContainer1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.TimeTrackBar)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label3; + private System.Windows.Forms.ComboBox CutsceneComboBox; + private System.Windows.Forms.SplitContainer splitContainer1; + private System.Windows.Forms.TreeView CutsceneTreeView; + private System.Windows.Forms.PropertyGrid InfoPropertyGrid; + private System.Windows.Forms.CheckBox AnimateCameraCheckBox; + private System.Windows.Forms.TrackBar TimeTrackBar; + private System.Windows.Forms.Label TimeLabel; + private System.Windows.Forms.Button PlayStopButton; + private System.Windows.Forms.Timer PlaybackTimer; + } +} \ No newline at end of file diff --git a/World/CutsceneForm.cs b/World/CutsceneForm.cs new file mode 100644 index 0000000..1f2910f --- /dev/null +++ b/World/CutsceneForm.cs @@ -0,0 +1,944 @@ +using CodeWalker.GameFiles; +using SharpDX; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CodeWalker.World +{ + public partial class CutsceneForm : Form + { + private WorldForm WorldForm; + + private GameFileCache GameFileCache; + + private Cutscene Cutscene = null; + + private bool AnimateCamera = true; + private bool Playing = false; + + + class CutsceneDropdownItem + { + public RpfEntry RpfEntry { get; set; } + + public override string ToString() + { + return RpfEntry?.Path ?? ""; + } + } + + public CutsceneForm(WorldForm worldForm) + { + WorldForm = worldForm; + GameFileCache = WorldForm.GameFileCache; + InitializeComponent(); + } + + + + public void UpdateAnimation(float elapsed) + { + if (Cutscene != null) + { + if (Playing) + { + var newt = Cutscene.PlaybackTime + elapsed; + if (newt > Cutscene.Duration) + { + newt = 0.0f; //stop or loop? + } + Cutscene.Update(newt); + } + + if (AnimateCamera && (Cutscene.CameraObject != null)) + { + var cori = Quaternion.RotationAxis(Vector3.UnitX, -1.57079632679f) * Quaternion.RotationAxis(Vector3.UnitZ, 3.141592653f); + + var pos = Cutscene.Position + Cutscene.CameraObject.Position; + var rot = Cutscene.Rotation * Cutscene.CameraObject.Rotation * cori; + + WorldForm.SetCameraTransform(pos, rot); + + } + + } + } + + public void GetVisibleYmaps(Camera camera, Dictionary ymaps) + { + //use a temporary ymap for entities. + + } + + + + + + private void SelectCutscene(CutsceneDropdownItem dditem) + { + Cursor = Cursors.WaitCursor; + Task.Run(() => + { + CutFile cutFile = null; + Cutscene cutscene = null; + + if (GameFileCache.IsInited) + { + var entry = dditem?.RpfEntry as RpfFileEntry; + if (entry != null) + { + + cutFile = new CutFile(entry); + GameFileCache.RpfMan.LoadFile(cutFile, entry); + + cutscene = new Cutscene(); + cutscene.Init(cutFile, GameFileCache); + + } + } + + CutsceneLoaded(cutscene); + + }); + } + private void CutsceneLoaded(Cutscene cs) + { + if (InvokeRequired) + { + try + { + Invoke(new Action(() => { CutsceneLoaded(cs); })); + } + catch + { } + return; + } + + Cutscene = cs; + + LoadTreeView(cs); + + TimeTrackBar.Maximum = (int)(cs.Duration * 10.0f); + TimeTrackBar.Value = 0; + UpdateTimeLabel(); + + Cursor = Cursors.Default; + } + + + private void LoadTreeView(Cutscene cs) + { + CutsceneTreeView.Nodes.Clear(); + + var cutFile = cs?.CutFile; + var cf = cutFile?.CutsceneFile2; + if (cf != null) + { + var csnode = CutsceneTreeView.Nodes.Add(cutFile.FileEntry?.Name); + csnode.Tag = cs; + + if (cf.pCutsceneObjects != null) + { + var objsnode = csnode.Nodes.Add("Objects"); + objsnode.Name = "Objects"; + + foreach (var obj in cf.pCutsceneObjects) + { + var objnode = objsnode.Nodes.Add(obj.ToString()); + objnode.Tag = obj; + } + } + if (cf.pCutsceneEventList != null) + { + var evtsnode = csnode.Nodes.Add("Events"); + evtsnode.Name = "Events"; + + foreach (var evt in cf.pCutsceneEventList) + { + var evtnode = evtsnode.Nodes.Add(evt.ToString()); + evtnode.Tag = evt; + } + } + if (cf.pCutsceneLoadEventList != null) + { + var ldesnode = csnode.Nodes.Add("Load Events"); + ldesnode.Name = "Load Events"; + + foreach (var lev in cf.pCutsceneLoadEventList) + { + var ldenode = ldesnode.Nodes.Add(lev.ToString()); + ldenode.Tag = lev; + } + } + + + + csnode.Expand(); + CutsceneTreeView.SelectedNode = csnode; + } + + } + + + + private void UpdateTimeTrackBar() + { + var tim = Cutscene?.PlaybackTime ?? 0.0f; + var itim = (int)(tim * 10.0f); + TimeTrackBar.Value = itim; + } + private void UpdateTimeLabel() + { + var tim = Cutscene?.PlaybackTime ?? 0.0f; + var dur = Cutscene?.Duration ?? 0.0f; + TimeLabel.Text = tim.ToString("0.00") + " / " + dur.ToString("0.00"); + } + + + + + + + + private void CutsceneForm_Load(object sender, EventArgs e) + { + if (!GameFileCache.IsInited) return;//what to do here? + + var rpfman = GameFileCache.RpfMan; + var rpflist = rpfman.AllRpfs; //loadedOnly ? gfc.ActiveMapRpfFiles.Values.ToList() : + + var dditems = new List(); + foreach (var rpf in rpflist) + { + foreach (var entry in rpf.AllEntries) + { + if (entry.NameLower.EndsWith(".cut")) + { + var dditem = new CutsceneDropdownItem(); + dditem.RpfEntry = entry; + dditems.Add(dditem); + } + } + } + + CutsceneComboBox.Items.Clear(); + CutsceneComboBox.Items.AddRange(dditems.ToArray()); + + + } + + private void CutsceneForm_FormClosed(object sender, FormClosedEventArgs e) + { + WorldForm?.OnCutsceneFormClosed(); + } + + private void CutsceneComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + var item = CutsceneComboBox.SelectedItem as CutsceneDropdownItem; + SelectCutscene(item); + } + + private void CutsceneTreeView_AfterSelect(object sender, TreeViewEventArgs e) + { + InfoPropertyGrid.SelectedObject = CutsceneTreeView.SelectedNode?.Tag; + } + + private void AnimateCameraCheckBox_CheckedChanged(object sender, EventArgs e) + { + AnimateCamera = AnimateCameraCheckBox.Checked; + } + + private void PlayStopButton_Click(object sender, EventArgs e) + { + if (Playing) + { + Playing = false; + PlayStopButton.Text = "Play"; + PlaybackTimer.Enabled = false; + } + else + { + Playing = true; + PlayStopButton.Text = "Stop"; + PlaybackTimer.Enabled = true; + } + } + + private void PlaybackTimer_Tick(object sender, EventArgs e) + { + if (Playing) + { + UpdateTimeTrackBar(); + UpdateTimeLabel(); + } + } + } + + + + [TypeConverter(typeof(ExpandableObjectConverter))] public class Cutscene + { + public CutFile CutFile { get; set; } = null; + private GameFileCache GameFileCache = null; + + public float[] CameraCutList { get; set; } = null; + public YcdFile[] Ycds { get; set; } = null; + + + public float Duration { get; set; } = 0.0f; + public float PlaybackTime { get; set; } = 0.0f; + + + public Dictionary Objects { get; set; } = null; + public Dictionary SceneObjects { get; set; } = null; + public CutEvent[] LoadEvents { get; set; } = null; + public CutEvent[] PlayEvents { get; set; } = null; + + public int NextLoadEvent { get; set; } = 0; + public int NextPlayEvent { get; set; } = 0; + public int NextCameraCut { get; set; } = 0; + + public Gxt2File Gxt2File { get; set; } = null; + + public Vector3 Position { get; set; } + public Quaternion Rotation { get; set; } + + + public CutsceneObject CameraObject = null; + + + + + public void Init(CutFile cutFile, GameFileCache gfc) + { + CutFile = cutFile; + GameFileCache = gfc; + + var csf = cutFile?.CutsceneFile2; + if (csf == null) return; + if (gfc == null) return; + + + Duration = csf.fTotalDuration; + CameraCutList = csf.cameraCutList; + Position = csf.vOffset; + Rotation = Quaternion.RotationAxis(Vector3.UnitZ, csf.fRotation); + Objects = csf.ObjectsDict; + LoadEvents = RecastArray(csf.pCutsceneLoadEventList); + PlayEvents = RecastArray(csf.pCutsceneEventList); + + + LoadYcds(); + CreateSceneObjects(); + RaiseEvents(0.0f); + } + + private void LoadYcds() + { + int cutListCount = (CameraCutList?.Length ?? 0) + 1; + var shortName = CutFile.FileEntry?.GetShortNameLower() ?? ""; + Ycds = new YcdFile[cutListCount]; + if (!string.IsNullOrEmpty(shortName)) + { + for (int i = 0; i < cutListCount; i++) + { + var ycdname = shortName + "-" + i.ToString(); + var ycdhash = JenkHash.GenHash(ycdname); + var ycd = GameFileCache.GetYcd(ycdhash); + while ((ycd != null) && (!ycd.Loaded)) + { + Thread.Sleep(20);//bite me + ycd = GameFileCache.GetYcd(ycdhash); + } + if (ycd != null) + { + ycd.BuildCutsceneMap(i); + } + Ycds[i] = ycd; + } + } + } + + + public void Update(float newTime) + { + if (newTime >= PlaybackTime) + { + RaiseEvents(newTime); + } + else + { + //reset playback to beginning, and seek to 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 + + var ycd = (cutIndex < (Ycds?.Length ?? 0)) ? Ycds[cutIndex] : null; + if (ycd?.CutsceneMap != null) + { + if (CameraObject != null) + { + ClipMapEntry cme = null; + ycd.CutsceneMap.TryGetValue(CameraObject.Name, out cme); + + if (cme != null) + { + if (cme.Clip is ClipAnimation canim) + { + if (canim.Animation != null) + { + var t = canim.GetPlaybackTime(PlaybackTime); + var f = canim.Animation.GetFramePosition(t); + var p = canim.Animation.FindBoneIndex(0, 7);//camera position + var r = canim.Animation.FindBoneIndex(0, 8);//camera rotation + if (p >= 0) CameraObject.Position = canim.Animation.EvaluateVector4(f, p, true).XYZ(); + if (r >= 0) CameraObject.Rotation = canim.Animation.EvaluateQuaternion(f, r, true); + } + + } + + } + + //var animname = CameraObject.Name.ToString() + "-" + cutIndex.ToString(); + //MetaHash animhash = JenkHash.GenHash() + + + } + + + } + + + } + + + private void RaiseEvents(float upToTime) + { + + int i; + for (i = NextLoadEvent; i < LoadEvents?.Length; i++) + { + var e = LoadEvents[i]; + if (e != null) + { + if (e.fTime > upToTime) break; + RaiseEvent(e); + } + } + NextLoadEvent = i; + + for (i = NextPlayEvent; i < PlayEvents?.Length; i++) + { + var e = PlayEvents[i]; + if (e != null) + { + if (e.fTime > upToTime) break; + RaiseEvent(e); + } + } + NextPlayEvent = i; + + for (i = NextCameraCut; i < CameraCutList?.Length; i++) + { + var c = CameraCutList[i]; + if (c > upToTime) break; + } + NextCameraCut = i; + + } + private void RaiseEvent(CutEvent e) + { + + switch (e.iEventId) + { + case CutEventType.LoadScene: LoadScene(e); break; + case CutEventType.LoadAnimation: LoadAnimation(e); break; + case CutEventType.LoadAudio: LoadAudio(e); break; + case CutEventType.LoadModels: LoadModels(e); break; + case CutEventType.LoadRayfireDes: LoadRayfireDes(e); break; + case CutEventType.LoadParticles: LoadParticles(e); break; + case CutEventType.LoadOverlays: LoadOverlays(e); break; + case CutEventType.LoadGxt2: LoadGxt2(e); break; + case CutEventType.UnloadModels: UnloadModels(e); break; + case CutEventType.UnloadRayfireDes: UnloadRayfireDes(e); break; + case CutEventType.EnableScreenFade: EnableScreenFade(e); break; + case CutEventType.EnableHideObject: EnableHideObject(e); break; + case CutEventType.EnableFixupModel: EnableFixupModel(e); break; + case CutEventType.EnableBlockBounds: EnableBlockBounds(e); break; + case CutEventType.EnableAnimation: EnableAnimation(e); break; + case CutEventType.EnableParticleEffect: EnableParticleEffect(e); break; + case CutEventType.EnableOverlay: EnableOverlay(e); break; + case CutEventType.EnableAudio: EnableAudio(e); break; + case CutEventType.EnableCamera: EnableCamera(e); break; + case CutEventType.EnableLight: EnableLight(e); break; + case CutEventType.DisableScreenFade: DisableScreenFade(e); break; + case CutEventType.DisableHideObject: DisableHideObject(e); break; + case CutEventType.DisableBlockBounds: DisableBlockBounds(e); break; + case CutEventType.DisableAnimation: DisableAnimation(e); break; + case CutEventType.DisableParticleEffect: DisableParticleEffect(e); break; + case CutEventType.DisableOverlay: DisableOverlay(e); break; + case CutEventType.DisableAudio: DisableAudio(e); break; + case CutEventType.DisableCamera: DisableCamera(e); break; + case CutEventType.DisableLight: DisableLight(e); break; + case CutEventType.Subtitle: Subtitle(e); break; + case CutEventType.PedVariation: PedVariation(e); break; + case CutEventType.CameraCut: CameraCut(e); break; + case CutEventType.CameraShadowCascade: CameraShadowCascade(e); break; + case CutEventType.CameraUnk1: CameraUnk1(e); break; + case CutEventType.CameraUnk2: CameraUnk2(e); break; + case CutEventType.CameraUnk3: CameraUnk3(e); break; + case CutEventType.CameraUnk4: CameraUnk4(e); break; + case CutEventType.CameraUnk5: CameraUnk5(e); break; + case CutEventType.CameraUnk6: CameraUnk6(e); break; + case CutEventType.CameraUnk7: CameraUnk7(e); break; + case CutEventType.CameraUnk8: CameraUnk8(e); break; + case CutEventType.DecalUnk1: DecalUnk1(e); break; + case CutEventType.DecalUnk2: DecalUnk2(e); break; + case CutEventType.PropUnk1: PropUnk1(e); break; + case CutEventType.Unk1: Unk1(e); break; + case CutEventType.Unk2: Unk2(e); break; + case CutEventType.VehicleUnk1: VehicleUnk1(e); break; + case CutEventType.PedUnk1: PedUnk1(e); break; + default: break; + } + + } + + private void LoadScene(CutEvent e) + { + var args = e.EventArgs as CutLoadSceneEventArgs; + if (args == null) + { return; } + + + Position = args.vOffset; + Rotation = Quaternion.RotationAxis(Vector3.UnitZ, args.fRotation * 0.0174532925f);//is this right? + + } + private void LoadAnimation(CutEvent e) + { + var args = e.EventArgs as CutNameEventArgs; + if (args == null) + { return; } + + } + private void LoadAudio(CutEvent e) + { + var args = e.EventArgs as CutNameEventArgs; + if (args == null) + { return; } + + } + private void LoadModels(CutEvent e) + { + var args = e.EventArgs as CutObjectIdListEventArgs; + if (args == null) + { return; } + + } + private void LoadRayfireDes(CutEvent e) + { + } + private void LoadParticles(CutEvent e) + { + var args = e.EventArgs as CutObjectIdListEventArgs; + if (args == null) + { return; } + + } + private void LoadOverlays(CutEvent e) + { + var args = e.EventArgs as CutObjectIdListEventArgs; + if (args == null) + { return; } + + } + private void LoadGxt2(CutEvent e) + { + if (GameFileCache == null) + { return; } + if (Gxt2File != null) + { } + + var args = e.EventArgs as CutFinalNameEventArgs; + if (args == null) + { return; } + + var namel = args.cName?.ToLowerInvariant(); + var namehash = JenkHash.GenHash(namel); + + RpfFileEntry gxt2entry = null; + GameFileCache.Gxt2Dict.TryGetValue(namehash, out gxt2entry); + + if (gxt2entry != null) //probably should do this load async + { + Gxt2File = GameFileCache.RpfMan.GetFile(gxt2entry); + + if (Gxt2File != null) + { + for (int i = 0; i < Gxt2File.TextEntries.Length; i++) + { + var te = Gxt2File.TextEntries[i]; + GlobalText.Ensure(te.Text, te.Hash); + } + } + } + + } + private void UnloadModels(CutEvent e) + { + var args = e.EventArgs as CutObjectIdListEventArgs; + if (args == null) + { return; } + + } + private void UnloadRayfireDes(CutEvent e) + { + } + private void EnableHideObject(CutEvent e) + { + var args = e.EventArgs as CutObjectIdEventArgs; + if (args == null) + { return; } + + var obj = args.Object; + + } + private void EnableFixupModel(CutEvent e) + { + } + private void EnableBlockBounds(CutEvent e) + { + var args = e.EventArgs as CutObjectIdEventArgs; + if (args == null) + { return; } + + var obj = args.Object; + + } + private void EnableScreenFade(CutEvent e) + { + } + private void EnableAnimation(CutEvent e) + { + var args = e.EventArgs as CutObjectIdEventArgs; + if (args == null) + { return; } + + var obj = args.Object; + + } + private void EnableParticleEffect(CutEvent e) + { + } + private void EnableOverlay(CutEvent e) + { + } + private void EnableAudio(CutEvent e) + { + var args = e.EventArgs as CutNameEventArgs; + if (args == null) + { return; } + + } + private void EnableCamera(CutEvent e) + { + var args = e.EventArgs as CutObjectIdEventArgs; + if (args == null) + { return; } + + var obj = args.Object; + + } + private void EnableLight(CutEvent e) + { + } + private void DisableHideObject(CutEvent e) + { + var args = e.EventArgs as CutObjectIdEventArgs; + if (args == null) + { return; } + + var obj = args.Object; + + } + private void DisableBlockBounds(CutEvent e) + { + var args = e.EventArgs as CutObjectIdEventArgs; + if (args == null) + { return; } + + var obj = args.Object; + + } + private void DisableScreenFade(CutEvent e) + { + } + private void DisableAnimation(CutEvent e) + { + var args = e.EventArgs as CutObjectIdEventArgs; + if (args == null) + { return; } + + var obj = args.Object; + + } + private void DisableParticleEffect(CutEvent e) + { + } + private void DisableOverlay(CutEvent e) + { + } + private void DisableAudio(CutEvent e) + { + var args = e.EventArgs as CutNameEventArgs; + if (args == null) + { return; } + + } + private void DisableCamera(CutEvent e) + { + var args = e.EventArgs as CutObjectIdEventArgs; + if (args == null) + { return; } + + var obj = args.Object; + + } + private void DisableLight(CutEvent e) + { + } + private void Subtitle(CutEvent e) + { + var args = e.EventArgs as CutSubtitleEventArgs; + if (args == null) + { return; } + + } + private void PedVariation(CutEvent e) + { + var args = e.EventArgs as CutObjectVariationEventArgs; + if (args == null) + { return; } + + var oe = e as CutObjectIdEvent; + if (oe == null) + { return; } + + } + private void CameraCut(CutEvent e) + { + var args = e.EventArgs as CutCameraCutEventArgs; + if (args == null) + { return; } + + var oe = e as CutObjectIdEvent; + if (oe == null) + { return; } + + + CutsceneObject obj = null; + SceneObjects.TryGetValue(oe.iObjectId, out obj); + if (obj == null) + { return; } + + + obj.Position = args.vPosition; + obj.Rotation = args.vRotationQuaternion; + + CameraObject = obj; + } + private void CameraShadowCascade(CutEvent e) + { + } + private void CameraUnk1(CutEvent e) + { + } + private void CameraUnk2(CutEvent e) + { + } + private void CameraUnk3(CutEvent e) + { + } + private void CameraUnk4(CutEvent e) + { + } + private void CameraUnk5(CutEvent e) + { + } + private void CameraUnk6(CutEvent e) + { + } + private void CameraUnk7(CutEvent e) + { + } + private void CameraUnk8(CutEvent e) + { + } + private void DecalUnk1(CutEvent e) + { + } + private void DecalUnk2(CutEvent e) + { + } + private void PropUnk1(CutEvent e) + { + } + private void Unk1(CutEvent e) + { + } + private void Unk2(CutEvent e) + { + } + private void VehicleUnk1(CutEvent e) + { + } + private void PedUnk1(CutEvent e) + { + } + + + + private T[] RecastArray(object[] arr) where T : class + { + if (arr == null) return null; + var r = new T[arr.Length]; + for (int i = 0; i < arr.Length; i++) + { + r[i] = arr[i] as T; + } + return r; + } + + + private void CreateSceneObjects() + { + SceneObjects = new Dictionary(); + + if (Objects == null) return; + + foreach (var obj in Objects.Values) + { + var sobj = new CutsceneObject(); + sobj.Init(obj); + SceneObjects[sobj.ObjectID] = sobj; + } + } + } + + [TypeConverter(typeof(ExpandableObjectConverter))] public class CutsceneObject + { + public int ObjectID { get; set; } + public CutObject CutObject { get; set; } + public MetaHash Name { get; set; } + + public Vector3 Position { get; set; } + public Quaternion Rotation { get; set; } + + + public void Init(CutObject obj) + { + CutObject = obj; + ObjectID = obj?.iObjectId ?? -1; + + if (obj is CutNamedObject nobj) + { + Name = nobj.cName; + } + + if (obj is CutAnimationManagerObject anim) + { + } + else if (obj is CutAssetManagerObject ass) + { + } + else if (obj is CutCameraObject cam) + { + } + else if (obj is CutPedModelObject ped) + { + } + else if (obj is CutPropModelObject prop) + { + } + else if (obj is CutVehicleModelObject veh) + { + } + else if (obj is CutWeaponModelObject weap) + { + } + else if (obj is CutHiddenModelObject hid) + { + } + else if (obj is CutFixupModelObject fix) + { + } + else if (obj is CutRayfireObject rayf) + { + } + else if (obj is CutParticleEffectObject eff) + { + } + else if (obj is CutAnimatedParticleEffectObject aeff) + { + } + else if (obj is CutLightObject light) + { + } + else if (obj is CutAnimatedLightObject alight) + { + } + else if (obj is CutDecalObject dec) + { + } + else if (obj is CutOverlayObject ovr) + { + } + else if (obj is CutAudioObject aud) + { + } + else if (obj is CutSubtitleObject sub) + { + } + else if (obj is CutBlockingBoundsObject blk) + { + } + else if (obj is CutScreenFadeObject fad) + { + } + else + { } + } + + + + public override string ToString() + { + return CutObject?.ToString() ?? (ObjectID.ToString() + ": " + Name.ToString()); + } + } + + + + +} diff --git a/World/CutsceneForm.resx b/World/CutsceneForm.resx new file mode 100644 index 0000000..c7b4266 --- /dev/null +++ b/World/CutsceneForm.resx @@ -0,0 +1,412 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + 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 + 6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f// + /wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA + AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc + skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU + 0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq + +ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz + /eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR + p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm + +P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB + AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/ + /f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/ + +fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd + 4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/ + 1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + /v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA + /v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/ + 9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA + AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA + /v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/ + /P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/ + /f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////// + ///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB/////// + //AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA + H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A + A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA + /f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A + AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf + AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4 + AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A// + ///////gD/////////Af//////////////8= + + + \ No newline at end of file diff --git a/WorldForm.Designer.cs b/WorldForm.Designer.cs index f05a249..67715f5 100644 --- a/WorldForm.Designer.cs +++ b/WorldForm.Designer.cs @@ -136,6 +136,10 @@ namespace CodeWalker this.TimedEntitiesCheckBox = new System.Windows.Forms.CheckBox(); this.FieldOfViewTrackBar = new System.Windows.Forms.TrackBar(); this.tabPage14 = new System.Windows.Forms.TabPage(); + this.FarClipUpDown = new System.Windows.Forms.NumericUpDown(); + this.label32 = new System.Windows.Forms.Label(); + this.NearClipUpDown = new System.Windows.Forms.NumericUpDown(); + this.label31 = new System.Windows.Forms.Label(); this.HDTexturesCheckBox = new System.Windows.Forms.CheckBox(); this.WireframeCheckBox = new System.Windows.Forms.CheckBox(); this.RenderModeComboBox = new System.Windows.Forms.ComboBox(); @@ -288,10 +292,7 @@ namespace CodeWalker this.ToolbarCameraMapViewButton = new System.Windows.Forms.ToolStripMenuItem(); this.ToolbarCameraOrthographicButton = new System.Windows.Forms.ToolStripMenuItem(); this.ToolbarPanel = new System.Windows.Forms.Panel(); - this.NearClipUpDown = new System.Windows.Forms.NumericUpDown(); - this.label31 = new System.Windows.Forms.Label(); - this.FarClipUpDown = new System.Windows.Forms.NumericUpDown(); - this.label32 = new System.Windows.Forms.Label(); + this.ToolsMenuCutsceneViewer = new System.Windows.Forms.ToolStripMenuItem(); this.StatusStrip.SuspendLayout(); this.ToolsPanel.SuspendLayout(); this.ToolsTabControl.SuspendLayout(); @@ -321,6 +322,8 @@ namespace CodeWalker ((System.ComponentModel.ISupportInitialize)(this.CollisionMeshRangeTrackBar)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.FieldOfViewTrackBar)).BeginInit(); this.tabPage14.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.FarClipUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.NearClipUpDown)).BeginInit(); this.tabPage9.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.SnapGridSizeUpDown)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.BoundsRangeTrackBar)).BeginInit(); @@ -333,8 +336,6 @@ namespace CodeWalker this.ToolsMenu.SuspendLayout(); this.Toolbar.SuspendLayout(); this.ToolbarPanel.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.NearClipUpDown)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.FarClipUpDown)).BeginInit(); this.SuspendLayout(); // // StatusStrip @@ -1673,6 +1674,81 @@ namespace CodeWalker this.tabPage14.Text = "Render"; this.tabPage14.UseVisualStyleBackColor = true; // + // FarClipUpDown + // + this.FarClipUpDown.Increment = new decimal(new int[] { + 100, + 0, + 0, + 0}); + this.FarClipUpDown.Location = new System.Drawing.Point(80, 346); + this.FarClipUpDown.Maximum = new decimal(new int[] { + 100000, + 0, + 0, + 0}); + this.FarClipUpDown.Minimum = new decimal(new int[] { + 100, + 0, + 0, + 0}); + this.FarClipUpDown.Name = "FarClipUpDown"; + this.FarClipUpDown.Size = new System.Drawing.Size(114, 20); + this.FarClipUpDown.TabIndex = 61; + this.FarClipUpDown.Value = new decimal(new int[] { + 12000, + 0, + 0, + 0}); + this.FarClipUpDown.ValueChanged += new System.EventHandler(this.FarClipUpDown_ValueChanged); + // + // label32 + // + this.label32.AutoSize = true; + this.label32.Location = new System.Drawing.Point(4, 348); + this.label32.Name = "label32"; + this.label32.Size = new System.Drawing.Size(45, 13); + this.label32.TabIndex = 60; + this.label32.Text = "Far Clip:"; + // + // NearClipUpDown + // + this.NearClipUpDown.DecimalPlaces = 3; + this.NearClipUpDown.Increment = new decimal(new int[] { + 1, + 0, + 0, + 65536}); + this.NearClipUpDown.Location = new System.Drawing.Point(80, 320); + this.NearClipUpDown.Maximum = new decimal(new int[] { + 10, + 0, + 0, + 0}); + this.NearClipUpDown.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 196608}); + this.NearClipUpDown.Name = "NearClipUpDown"; + this.NearClipUpDown.Size = new System.Drawing.Size(114, 20); + this.NearClipUpDown.TabIndex = 59; + this.NearClipUpDown.Value = new decimal(new int[] { + 5, + 0, + 0, + 65536}); + this.NearClipUpDown.ValueChanged += new System.EventHandler(this.NearClipUpDown_ValueChanged); + // + // label31 + // + this.label31.AutoSize = true; + this.label31.Location = new System.Drawing.Point(4, 322); + this.label31.Name = "label31"; + this.label31.Size = new System.Drawing.Size(53, 13); + this.label31.TabIndex = 58; + this.label31.Text = "Near Clip:"; + // // HDTexturesCheckBox // this.HDTexturesCheckBox.AutoSize = true; @@ -2594,6 +2670,7 @@ namespace CodeWalker this.ToolsMenuRPFExplorer, this.ToolsMenuSelectionInfo, this.ToolsMenuProjectWindow, + this.ToolsMenuCutsceneViewer, this.ToolsMenuWorldSearch, this.ToolsMenuBinarySearch, this.ToolsMenuJenkGen, @@ -2604,12 +2681,12 @@ namespace CodeWalker this.ToolsMenuExtractShaders, this.ToolsMenuOptions}); this.ToolsMenu.Name = "ToolsMenu"; - this.ToolsMenu.Size = new System.Drawing.Size(166, 290); + this.ToolsMenu.Size = new System.Drawing.Size(181, 334); // // ToolsMenuRPFBrowser // this.ToolsMenuRPFBrowser.Name = "ToolsMenuRPFBrowser"; - this.ToolsMenuRPFBrowser.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuRPFBrowser.Size = new System.Drawing.Size(180, 22); this.ToolsMenuRPFBrowser.Text = "RPF Browser..."; this.ToolsMenuRPFBrowser.Visible = false; this.ToolsMenuRPFBrowser.Click += new System.EventHandler(this.ToolsMenuRPFBrowser_Click); @@ -2617,14 +2694,14 @@ namespace CodeWalker // ToolsMenuRPFExplorer // this.ToolsMenuRPFExplorer.Name = "ToolsMenuRPFExplorer"; - this.ToolsMenuRPFExplorer.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuRPFExplorer.Size = new System.Drawing.Size(180, 22); this.ToolsMenuRPFExplorer.Text = "RPF Explorer..."; this.ToolsMenuRPFExplorer.Click += new System.EventHandler(this.ToolsMenuRPFExplorer_Click); // // ToolsMenuSelectionInfo // this.ToolsMenuSelectionInfo.Name = "ToolsMenuSelectionInfo"; - this.ToolsMenuSelectionInfo.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuSelectionInfo.Size = new System.Drawing.Size(180, 22); this.ToolsMenuSelectionInfo.Text = "Selection info..."; this.ToolsMenuSelectionInfo.Click += new System.EventHandler(this.ToolsMenuSelectionInfo_Click); // @@ -2632,14 +2709,14 @@ namespace CodeWalker // this.ToolsMenuProjectWindow.Enabled = false; this.ToolsMenuProjectWindow.Name = "ToolsMenuProjectWindow"; - this.ToolsMenuProjectWindow.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuProjectWindow.Size = new System.Drawing.Size(180, 22); this.ToolsMenuProjectWindow.Text = "Project window..."; this.ToolsMenuProjectWindow.Click += new System.EventHandler(this.ToolsMenuProjectWindow_Click); // // ToolsMenuWorldSearch // this.ToolsMenuWorldSearch.Name = "ToolsMenuWorldSearch"; - this.ToolsMenuWorldSearch.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuWorldSearch.Size = new System.Drawing.Size(180, 22); this.ToolsMenuWorldSearch.Text = "World search..."; this.ToolsMenuWorldSearch.Click += new System.EventHandler(this.ToolsMenuWorldSearch_Click); // @@ -2647,14 +2724,14 @@ namespace CodeWalker // this.ToolsMenuBinarySearch.Enabled = false; this.ToolsMenuBinarySearch.Name = "ToolsMenuBinarySearch"; - this.ToolsMenuBinarySearch.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuBinarySearch.Size = new System.Drawing.Size(180, 22); this.ToolsMenuBinarySearch.Text = "Binary search..."; this.ToolsMenuBinarySearch.Click += new System.EventHandler(this.ToolsMenuBinarySearch_Click); // // ToolsMenuJenkGen // this.ToolsMenuJenkGen.Name = "ToolsMenuJenkGen"; - this.ToolsMenuJenkGen.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuJenkGen.Size = new System.Drawing.Size(180, 22); this.ToolsMenuJenkGen.Text = "JenkGen..."; this.ToolsMenuJenkGen.Click += new System.EventHandler(this.ToolsMenuJenkGen_Click); // @@ -2662,42 +2739,42 @@ namespace CodeWalker // this.ToolsMenuJenkInd.Enabled = false; this.ToolsMenuJenkInd.Name = "ToolsMenuJenkInd"; - this.ToolsMenuJenkInd.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuJenkInd.Size = new System.Drawing.Size(180, 22); this.ToolsMenuJenkInd.Text = "JenkInd..."; this.ToolsMenuJenkInd.Click += new System.EventHandler(this.ToolsMenuJenkInd_Click); // // ToolsMenuExtractScripts // this.ToolsMenuExtractScripts.Name = "ToolsMenuExtractScripts"; - this.ToolsMenuExtractScripts.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuExtractScripts.Size = new System.Drawing.Size(180, 22); this.ToolsMenuExtractScripts.Text = "Extract scripts..."; this.ToolsMenuExtractScripts.Click += new System.EventHandler(this.ToolsMenuExtractScripts_Click); // // ToolsMenuExtractTextures // this.ToolsMenuExtractTextures.Name = "ToolsMenuExtractTextures"; - this.ToolsMenuExtractTextures.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuExtractTextures.Size = new System.Drawing.Size(180, 22); this.ToolsMenuExtractTextures.Text = "Extract textures..."; this.ToolsMenuExtractTextures.Click += new System.EventHandler(this.ToolsMenuExtractTextures_Click); // // ToolsMenuExtractRawFiles // this.ToolsMenuExtractRawFiles.Name = "ToolsMenuExtractRawFiles"; - this.ToolsMenuExtractRawFiles.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuExtractRawFiles.Size = new System.Drawing.Size(180, 22); this.ToolsMenuExtractRawFiles.Text = "Extract raw files..."; this.ToolsMenuExtractRawFiles.Click += new System.EventHandler(this.ToolsMenuExtractRawFiles_Click); // // ToolsMenuExtractShaders // this.ToolsMenuExtractShaders.Name = "ToolsMenuExtractShaders"; - this.ToolsMenuExtractShaders.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuExtractShaders.Size = new System.Drawing.Size(180, 22); this.ToolsMenuExtractShaders.Text = "Extract shaders..."; this.ToolsMenuExtractShaders.Click += new System.EventHandler(this.ToolsMenuExtractShaders_Click); // // ToolsMenuOptions // this.ToolsMenuOptions.Name = "ToolsMenuOptions"; - this.ToolsMenuOptions.Size = new System.Drawing.Size(165, 22); + this.ToolsMenuOptions.Size = new System.Drawing.Size(180, 22); this.ToolsMenuOptions.Text = "Options..."; this.ToolsMenuOptions.Click += new System.EventHandler(this.ToolsMenuOptions_Click); // @@ -3306,80 +3383,13 @@ namespace CodeWalker this.ToolbarPanel.TabIndex = 7; this.ToolbarPanel.Visible = false; // - // NearClipUpDown + // ToolsMenuCutsceneViewer // - this.NearClipUpDown.DecimalPlaces = 3; - this.NearClipUpDown.Increment = new decimal(new int[] { - 1, - 0, - 0, - 65536}); - this.NearClipUpDown.Location = new System.Drawing.Point(80, 320); - this.NearClipUpDown.Maximum = new decimal(new int[] { - 10, - 0, - 0, - 0}); - this.NearClipUpDown.Minimum = new decimal(new int[] { - 1, - 0, - 0, - 196608}); - this.NearClipUpDown.Name = "NearClipUpDown"; - this.NearClipUpDown.Size = new System.Drawing.Size(114, 20); - this.NearClipUpDown.TabIndex = 59; - this.NearClipUpDown.Value = new decimal(new int[] { - 5, - 0, - 0, - 65536}); - this.NearClipUpDown.ValueChanged += new System.EventHandler(this.NearClipUpDown_ValueChanged); - // - // label31 - // - this.label31.AutoSize = true; - this.label31.Location = new System.Drawing.Point(4, 322); - this.label31.Name = "label31"; - this.label31.Size = new System.Drawing.Size(53, 13); - this.label31.TabIndex = 58; - this.label31.Text = "Near Clip:"; - // - // FarClipUpDown - // - this.FarClipUpDown.Increment = new decimal(new int[] { - 100, - 0, - 0, - 0}); - this.FarClipUpDown.Location = new System.Drawing.Point(80, 346); - this.FarClipUpDown.Maximum = new decimal(new int[] { - 100000, - 0, - 0, - 0}); - this.FarClipUpDown.Minimum = new decimal(new int[] { - 100, - 0, - 0, - 0}); - this.FarClipUpDown.Name = "FarClipUpDown"; - this.FarClipUpDown.Size = new System.Drawing.Size(114, 20); - this.FarClipUpDown.TabIndex = 61; - this.FarClipUpDown.Value = new decimal(new int[] { - 12000, - 0, - 0, - 0}); - this.FarClipUpDown.ValueChanged += new System.EventHandler(this.FarClipUpDown_ValueChanged); - // - // label32 - // - this.label32.AutoSize = true; - this.label32.Location = new System.Drawing.Point(4, 348); - this.label32.Name = "label32"; - this.label32.Size = new System.Drawing.Size(45, 13); - this.label32.TabIndex = 60; - this.label32.Text = "Far Clip:"; + this.ToolsMenuCutsceneViewer.Enabled = false; + this.ToolsMenuCutsceneViewer.Name = "ToolsMenuCutsceneViewer"; + this.ToolsMenuCutsceneViewer.Size = new System.Drawing.Size(180, 22); + this.ToolsMenuCutsceneViewer.Text = "Cutscene viewer..."; + this.ToolsMenuCutsceneViewer.Click += new System.EventHandler(this.ToolsMenuCutsceneViewer_Click); // // WorldForm // @@ -3444,6 +3454,8 @@ namespace CodeWalker ((System.ComponentModel.ISupportInitialize)(this.FieldOfViewTrackBar)).EndInit(); this.tabPage14.ResumeLayout(false); this.tabPage14.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.FarClipUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.NearClipUpDown)).EndInit(); this.tabPage9.ResumeLayout(false); this.tabPage9.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.SnapGridSizeUpDown)).EndInit(); @@ -3462,8 +3474,6 @@ namespace CodeWalker this.Toolbar.PerformLayout(); this.ToolbarPanel.ResumeLayout(false); this.ToolbarPanel.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)(this.NearClipUpDown)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.FarClipUpDown)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -3731,5 +3741,6 @@ namespace CodeWalker private System.Windows.Forms.Label label32; private System.Windows.Forms.NumericUpDown NearClipUpDown; private System.Windows.Forms.Label label31; + private System.Windows.Forms.ToolStripMenuItem ToolsMenuCutsceneViewer; } } \ No newline at end of file diff --git a/WorldForm.cs b/WorldForm.cs index 442efc1..fa79861 100644 --- a/WorldForm.cs +++ b/WorldForm.cs @@ -197,6 +197,7 @@ namespace CodeWalker WorldSearchForm SearchForm = null; + CutsceneForm CutsceneForm = null; InputManager Input = new InputManager(); @@ -404,7 +405,10 @@ namespace CodeWalker space.Update(elapsed); - + if (CutsceneForm != null) + { + CutsceneForm.UpdateAnimation(elapsed); + } Renderer.Update(elapsed, MouseLastPoint.X, MouseLastPoint.Y); @@ -678,6 +682,10 @@ namespace CodeWalker ProjectForm.GetVisibleYmaps(camera, renderworldVisibleYmapDict); } + if (CutsceneForm != null) + { + CutsceneForm.GetVisibleYmaps(camera, renderworldVisibleYmapDict); + } Renderer.RenderWorld(renderworldVisibleYmapDict, spaceEnts); @@ -1876,6 +1884,15 @@ namespace CodeWalker } + public void SetCameraTransform(Vector3 pos, Quaternion rot) + { + camera.FollowEntity.Position = pos; + camera.FollowEntity.Orientation = rot; + camera.FollowEntity.OrientationInv = Quaternion.Invert(rot); + camera.TargetRotation = Vector3.Zero; + camera.TargetDistance = 0.01f; + } + public Vector3 GetCameraPosition() { //currently used by ProjectForm when creating entities @@ -4098,6 +4115,29 @@ namespace CodeWalker //ToolbarSearchWindowButton.Checked = false; } + private void ShowCutsceneForm() + { + if (CutsceneForm == null) + { + CutsceneForm = new CutsceneForm(this); + CutsceneForm.Show(this); + } + else + { + if (CutsceneForm.WindowState == FormWindowState.Minimized) + { + CutsceneForm.WindowState = FormWindowState.Normal; + } + CutsceneForm.Focus(); + } + //ToolbarCutsceneWindowButton.Checked = true; + } + public void OnCutsceneFormClosed() + { + CutsceneForm = null; + //ToolbarCutsceneWindowButton.Checked = false; + } + public void ShowModel(string name) { ViewModeComboBox.Text = "Model view"; @@ -4904,6 +4944,7 @@ namespace CodeWalker ToolbarOpenButton.Enabled = true; ToolbarProjectWindowButton.Enabled = true; ToolsMenuProjectWindow.Enabled = true; + ToolsMenuCutsceneViewer.Enabled = true; ToolsMenuBinarySearch.Enabled = true; ToolsMenuJenkInd.Enabled = true; } @@ -6984,6 +7025,11 @@ namespace CodeWalker ShowProjectForm(); } + private void ToolsMenuCutsceneViewer_Click(object sender, EventArgs e) + { + ShowCutsceneForm(); + } + private void ToolsMenuWorldSearch_Click(object sender, EventArgs e) { ShowSearchForm(); diff --git a/WorldForm.resx b/WorldForm.resx index 8689d72..fe93ed0 100644 --- a/WorldForm.resx +++ b/WorldForm.resx @@ -240,14 +240,6 @@ ufo YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAB4SURBVDhP3ZC7DcAgDEQZKTMwHOvSIFriS7BlEB+HMic9 QJbvFThLUkpXzjkSpaeuzMPlEELx3jdsBauyCHBY6UWYPQI93KEljQD3jL6EGzN6x0bASyNYwkKU8Udm gd6TMnIikDJyIqjVNz8T7FgKrAwFX6lVinM3aJ05lWDPRRcAAAAASUVORK5CYII= - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAB0SURBVDhP7ZNBCoAgEEXnSJ3BqxmetNpaMLhVv5DNRJS2 - CxIeuvA9XSjtg5mHEILPxB6U7JyLxphmSkDK1o5x9dst87SUfTXwRsYsA+paT0BGDGsVOJ92hdz3Bz4f - wGPC48uu7w5IGd+gBlpRMgYCnRwyESUj3CsQkYNFDwAAAABJRU5ErkJggg== @@ -269,13 +261,12 @@ ufo WBXYx9R1nV75RuyHKrrnzCcGjE1u9ZyD4BugoZigQ9xrngAAAABJRU5ErkJggg== - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACtSURBVDhPrZBBEsIgEAR5Gy/wFV55T/wHr+KgHuCKNsVY - ZI2JiU7VVIVlp7OL+1mllIr7cb8Ie++PQwQYITnnM24NWxoBgsQYm/l+gk699bMsRA4h1JTSPsg0Xert - em/mGwh3vW1Z7MvIABSWqXG3+iZHAEw1m4wD49oVANgVOL/VeSgeDAiX1mpWeKy9BIQiI+OxWQF77tG5 - 2Fc729BmeElf/3lNhORe+oecewDObEqX49RqCgAAAABJRU5ErkJggg== + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAB0SURBVDhP7ZNBCoAgEEXnSJ3BqxmetNpaMLhVv5DNRJS2 + CxIeuvA9XSjtg5mHEILPxB6U7JyLxphmSkDK1o5x9dst87SUfTXwRsYsA+paT0BGDGsVOJ92hdz3Bz4f + wGPC48uu7w5IGd+gBlpRMgYCnRwyESUj3CsQkYNFDwAAAABJRU5ErkJggg== @@ -304,6 +295,15 @@ ufo EcMw2DzPDMEke9AsYBrHs10vN4I1QqImwwDcFyMjQGaBHr5Bo8nEoYCnCQTGzVeI4oj6fIi+KHgoPBhC 4knCjTww9vxfbIUQNDEyiGIZ8t6tW/k0vC/AOpuiueNOLwVkUeylvju9FJCg8E1vM/2PlTv5UoervVTJ uQAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACtSURBVDhPrZBBEsIgEAR5Gy/wFV55T/wHr+KgHuCKNsVY + ZI2JiU7VVIVlp7OL+1mllIr7cb8Ie++PQwQYITnnM24NWxoBgsQYm/l+gk699bMsRA4h1JTSPsg0Xert + em/mGwh3vW1Z7MvIABSWqXG3+iZHAEw1m4wD49oVANgVOL/VeSgeDAiX1mpWeKy9BIQiI+OxWQF77tG5 + 2Fc729BmeElf/3lNhORe+oecewDObEqX49RqCgAAAABJRU5ErkJggg== @@ -389,17 +389,6 @@ ufo 4BJN+IjGo5O8ZJndGVhKxpjWWts551aih0fre+0BLaVchRAezPB2NXSSV/gVwXGYPJiVUt6ns1ghCDjn UQG86w3FToVgDcWCWS9Fvi/Ao0RVAcwUjwpyhzmf4n8BFApS5HZRwRuONGMbrIJ1JIN8O2QAAAAASUVO RK5CYII= - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEvSURBVDhP3dK/K0dRGMfxKxRJopCSEkLya/guUhQRmQwG - WfwIkYySgYUSKUKJlOK/MBoMFMofYLUIsfJ+f3NuF3+A8tRree5zP/fcc070f6oHT/jAPTqQj6WvXvCM - TZQgG3H58gFGcYVLtGIN15jBNDbwiGNUIg4pQx8GsQuHhrCDW8yjHyns4Q0DcCXpykM5bFzgHGPYxw1G - UIVMtMHfWUUj4nIg/KurGIYrSAZYOXDGlbhXcZlegUO8Yxzb+BlQAwNW0G0jVAYK0AwHtnCEOyQDZvGC - ObTbKIIvLMA9WIYDizhFMsDjfsAZptCA9JcdfoVBvryOSbgCe4HPTuCz+BQMKEUvJmCy96ET1ehCuAf2 - 5ZF+uwdZKEYtmuBGFSIXhtejBe5PHX7dxL+qKPoEppRHcXOtiDsAAAAASUVORK5CYII= @@ -435,6 +424,17 @@ ufo rp3fhGJScIRLzKMLFTC9cMIu3nCDVUyjB6WkYA93mEWbAyH9cMImPuA+rWMA31YwBU82kF6BS32Er/aO M8zAh+OEghpcwQ2bg3uwBW8ewFd7xQkm0IA4oaAS7bh2KHjBIZbhV/D6GJkFphrdcIP8lFrAGPwPOjCO QdQiTqrAWNICd7gPnUj+xBKaU9dxfhTkjwV/FxU+AbsiGnc46OYIAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEvSURBVDhP3dK/K0dRGMfxKxRJopCSEkLya/guUhQRmQwG + WfwIkYySgYUSKUKJlOK/MBoMFMofYLUIsfJ+f3NuF3+A8tRree5zP/fcc070f6oHT/jAPTqQj6WvXvCM + TZQgG3H58gFGcYVLtGIN15jBNDbwiGNUIg4pQx8GsQuHhrCDW8yjHyns4Q0DcCXpykM5bFzgHGPYxw1G + UIVMtMHfWUUj4nIg/KurGIYrSAZYOXDGlbhXcZlegUO8Yxzb+BlQAwNW0G0jVAYK0AwHtnCEOyQDZvGC + ObTbKIIvLMA9WIYDizhFMsDjfsAZptCA9JcdfoVBvryOSbgCe4HPTuCz+BQMKEUvJmCy96ET1ehCuAf2 + 5ZF+uwdZKEYtmuBGFSIXhtejBe5PHX7dxL+qKPoEppRHcXOtiDsAAAAASUVORK5CYII=