From d8fd82c350b33af5f4d968a4bbbbb59e46e63dd7 Mon Sep 17 00:00:00 2001 From: dexyfex Date: Fri, 22 Dec 2017 07:26:04 +1100 Subject: [PATCH] Render and select audio zones (box shapes only, no spheres yet) --- CodeWalker.csproj | 3 +- GameFiles/FileTypes/RelFile.cs | 191 ++++++++++--------- World/AudioZones.cs | 246 +++++++++++++++++++++++++ World/{PopZone.cs => PopZones.cs} | 0 WorldForm.Designer.cs | 16 +- WorldForm.cs | 293 ++++++++++++++++++++++-------- WorldInfoForm.Designer.cs | 3 +- WorldInfoForm.cs | 5 + 8 files changed, 582 insertions(+), 175 deletions(-) create mode 100644 World/AudioZones.cs rename World/{PopZone.cs => PopZones.cs} (100%) diff --git a/CodeWalker.csproj b/CodeWalker.csproj index 2ef8749..57bd1b2 100644 --- a/CodeWalker.csproj +++ b/CodeWalker.csproj @@ -415,6 +415,7 @@ WorldSearchForm.cs + @@ -435,7 +436,7 @@ - + diff --git a/GameFiles/FileTypes/RelFile.cs b/GameFiles/FileTypes/RelFile.cs index 6ea39e0..b8143b5 100644 --- a/GameFiles/FileTypes/RelFile.cs +++ b/GameFiles/FileTypes/RelFile.cs @@ -236,7 +236,7 @@ namespace CodeWalker.GameFiles } RelDatas = reldatas.ToArray(); - reldatas.Sort((d1, d2) => d1.Offset.CompareTo(d2.Offset)); + reldatas.Sort((d1, d2) => d1.DataOffset.CompareTo(d2.DataOffset)); RelDatasSorted = reldatas.ToArray(); @@ -306,8 +306,8 @@ namespace CodeWalker.GameFiles RelData d = new RelData(); //use this base object to construct the derived one... d.Name = name; d.NameHash = hash; - d.Offset = offset; - d.Length = length; + d.DataOffset = offset; + d.DataLength = length; d.Data = data; @@ -445,7 +445,7 @@ namespace CodeWalker.GameFiles { //speech.dat4.rel, audioconfig.dat4.rel - if (d.Length == 1) + if (d.DataLength == 1) { byte b = br.ReadByte(); switch (b) @@ -463,7 +463,7 @@ namespace CodeWalker.GameFiles } return; } - if (d.Length == 2) + if (d.DataLength == 2) { byte b = br.ReadByte(); switch (b) @@ -526,7 +526,7 @@ namespace CodeWalker.GameFiles } return; } - if (d.Length == 4) + if (d.DataLength == 4) { uint h = br.ReadUInt32(); return; @@ -928,8 +928,8 @@ namespace CodeWalker.GameFiles { public MetaHash NameHash { get; set; } public string Name { get; set; } - public uint Offset { get; set; } - public uint Length { get; set; } + public uint DataOffset { get; set; } + public uint DataLength { get; set; } public byte[] Data { get; set; } public byte TypeID { get; set; } @@ -938,8 +938,8 @@ namespace CodeWalker.GameFiles { NameHash = d.NameHash; Name = d.Name; - Offset = d.Offset; - Length = d.Length; + DataOffset = d.DataOffset; + DataLength = d.DataLength; Data = d.Data; TypeID = d.TypeID; } @@ -955,7 +955,7 @@ namespace CodeWalker.GameFiles } public string GetBaseString() { - return Offset.ToString() + ", " + Length.ToString() + ": " + GetNameString(); + return DataOffset.ToString() + ", " + DataLength.ToString() + ": " + GetNameString(); } public override string ToString() { @@ -2143,7 +2143,7 @@ namespace CodeWalker.GameFiles { SpeechParams = 14, - Unk37 = 37, //eg parent for sos/altruist - contains coords - toggle sound? + Unk37 = 37, //audio zone? eg parent for sos/altruist - contains coords - toggle sound? Unk38 = 38, //eg sos, altruist morse - contains coords StartTrackAction = 63, @@ -2207,38 +2207,38 @@ namespace CodeWalker.GameFiles } } - [TC(typeof(EXP))] public class Dat151Unk37 : Dat151RelData //toggle sound? + public enum Dat151ZoneShape : uint + { + Box = 0, + Sphere = 1, + Line = 2, + } + + [TC(typeof(EXP))] public class Dat151Unk37 : Dat151RelData //audio zone? toggle sound? { public uint UnkOffset0 { get; set; } public FlagsUint Flags00 { get; set; } - public FlagsUint Flags01 { get; set; } + public Dat151ZoneShape Shape { get; set; } public FlagsUint Flags02 { get; set; } - public Vector3 Pos01 { get; set; } - public float Unk01 { get; set; } - public Vector3 Size02 { get; set; } - public float Unk02 { get; set; } - public Vector3 Size03 { get; set; } - public float Unk03 { get; set; } - public Vector3 Size04 { get; set; } - public float Unk04 { get; set; } - public FlagsUint Flags03 { get; set; } - public Vector3 Vec05 { get; set; } - public Vector3 Pos06 { get; set; } - public float Unk06 { get; set; } - public Vector3 Size07 { get; set; } - public float Unk07 { get; set; } - public Vector3 Size08 { get; set; } - public float Unk08 { get; set; } - public Vector3 Size09 { get; set; } - public float Unk09 { get; set; } - public FlagsUint Flags04 { get; set; } - public Vector3 Vec10 { get; set; } - public Vector3 Vec11 { get; set; } - public float Unk11 { get; set; } - public Vector3 Vec12 { get; set; } - public float Unk12 { get; set; } - public Vector3 Vec13 { get; set; } - public float Unk13 { get; set; } + public Vector3 OuterPos { get; set; } + public float Unused01 { get; set; } + public Vector3 OuterSize { get; set; } + public float Unused02 { get; set; } + public Vector4 OuterVec1 { get; set; } + public Vector4 OuterVec2 { get; set; } + public uint OuterAngle { get; set; } + public Vector3 OuterVec3 { get; set; } + public Vector3 InnerPos { get; set; } + public float Unused06 { get; set; } + public Vector3 InnerSize { get; set; } + public float Unused07 { get; set; } + public Vector4 InnerVec1 { get; set; } + public Vector4 InnerVec2 { get; set; } + public uint InnerAngle { get; set; } + public Vector3 InnerVec3 { get; set; } + public Vector4 Vec11 { get; set; } + public Vector4 Vec12 { get; set; } + public Vector4 Vec13 { get; set; } public FlagsUint Flags05 { get; set; } public byte Unk14 { get; set; } @@ -2264,40 +2264,35 @@ namespace CodeWalker.GameFiles } } + + public Dat151Unk37(RelData d, BinaryReader br) : base(d, br) { br.BaseStream.Position = 0; //1 byte was read already (TypeID) UnkOffset0 = ((br.ReadUInt32() >> 8) & 0xFFFFFF); Flags00 = br.ReadUInt32(); - Flags01 = br.ReadUInt32(); + Shape = (Dat151ZoneShape)br.ReadUInt32(); Flags02 = br.ReadUInt32(); - Pos01 = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); - Unk01 = br.ReadSingle(); - Size02 = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); - Unk02 = br.ReadSingle(); - Size03 = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); - Unk03 = br.ReadSingle(); - Size04 = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); - Unk04 = br.ReadSingle(); - Flags03 = br.ReadUInt32();//### - Vec05 = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); - Pos06 = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); - Unk06 = br.ReadSingle(); - Size07 = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); - Unk07 = br.ReadSingle(); - Size08 = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); - Unk08 = br.ReadSingle(); - Size09 = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); - Unk09 = br.ReadSingle(); - Flags04 = br.ReadUInt32();//### - Vec10 = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); - Vec11 = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); - Unk11 = br.ReadSingle(); - Vec12 = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); - Unk12 = br.ReadSingle(); - Vec13 = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());//perhaps not float - Unk13 = br.ReadSingle(); + OuterPos = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + Unused01 = br.ReadSingle(); + OuterSize = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + Unused02 = br.ReadSingle(); + OuterVec1 = new Vector4(br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + OuterVec2 = new Vector4(br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + OuterAngle = br.ReadUInt32();//### + OuterVec3 = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + InnerPos = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + Unused06 = br.ReadSingle(); + InnerSize = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + Unused07 = br.ReadSingle(); + InnerVec1 = new Vector4(br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + InnerVec2 = new Vector4(br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + InnerAngle = br.ReadUInt32();//### + InnerVec3 = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + Vec11 = new Vector4(br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + Vec12 = new Vector4(br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + Vec13 = new Vector4(br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); Flags05 = br.ReadUInt32(); Unk14 = br.ReadByte(); @@ -2324,39 +2319,37 @@ namespace CodeWalker.GameFiles long bytesleft = br.BaseStream.Length - br.BaseStream.Position; if (bytesleft != 0) { - byte[] remainder = br.ReadBytes((int)bytesleft); - for (int i = 0; i < remainder.Length; i++) - { - if (remainder[i] != 0) - { } - } + //byte[] remainder = br.ReadBytes((int)bytesleft); + //for (int i = 0; i < remainder.Length; i++) + //{ + // if (remainder[i] != 0) + // { } //no hits here! probably got everything, i'm assuming the block is padded to 0x10 or something. + //} } - //FlagsUint[] flags = new FlagsUint[t4]; - //for (int i = 0; i < t4; i++) - //{ - // flags[i] = br.ReadUInt32(); - //} - //var t2 = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); - //var t3 = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); - //var t4 = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + //RecVec(Pos01);//debug coords output + //RecVec(Pos06); - RecVec(Pos01); - //RecVec(Size02); - //RecVec(Size03); - //RecVec(Size04); - //RecVec(Vec05); - RecVec(Pos06); - //RecVec(Size07); - //RecVec(Size08); - //RecVec(Size09); - //RecVec(Vec10); - //RecVec(Vec11); - //RecVec(Vec12); - //RecVec(Vec13); - + if (Unused01 != 0) + { }//no hit + if (Unused02 != 0) + { }//no hit + if (Unused06 != 0) + { }//no hit + if (Unused07 != 0) + { }//no hit + if (Shape != 0) + { }//eg 1, 2 + if (Flags02.Value != 0) + { }//no hit + if (OuterAngle > 360) + { }//no hit + if (InnerAngle > 360) + { }//no hit + if (Flags05.Value != 0) + { }//eg 0xAE64583B, 0x61083310, 0xCAE96294, 0x1C376176 } } @@ -2374,8 +2367,8 @@ namespace CodeWalker.GameFiles public FlagsUint Unk07 { get; set; } //0xFFFFFFFF public FlagsUint Unk08 { get; set; } //0 public float Unk09 { get; set; } //1, 5, 100, ... - public float Unk10 { get; set; } //0, 4, ... 100 ... min value? - public float Unk11 { get; set; } //15, 16, 12, 10, 20, 300 ... max value? + public float InnerRad { get; set; } //0, 4, ... 100 ... min value? + public float OuterRad { get; set; } //15, 16, 12, 10, 20, 300 ... max value? public FlagsByte Unk12 { get; set; } public FlagsByte Unk13 { get; set; } //0,1,2,3,4,5 public FlagsByte Unk14 { get; set; } @@ -2425,8 +2418,8 @@ namespace CodeWalker.GameFiles Unk07 = br.ReadUInt32(); //0xFFFFFFFF Unk08 = br.ReadUInt32(); //0 Unk09 = br.ReadSingle(); //1, 5, 100, ... - Unk10 = br.ReadSingle(); //0, 4, ... 100 ... min value? - Unk11 = br.ReadSingle(); //15, 16, 12, 10, 20, 300 ... max value? + InnerRad = br.ReadSingle(); //0, 4, ... 100 ... min value? + OuterRad = br.ReadSingle(); //15, 16, 12, 10, 20, 300 ... max value? Unk12 = br.ReadByte(); Unk13 = br.ReadByte(); //0,1,2,3,4,5 Unk14 = br.ReadByte(); diff --git a/World/AudioZones.cs b/World/AudioZones.cs new file mode 100644 index 0000000..debe728 --- /dev/null +++ b/World/AudioZones.cs @@ -0,0 +1,246 @@ +using CodeWalker.GameFiles; +using SharpDX; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeWalker.World +{ + public class AudioZones // : BasePathData + { + public volatile bool Inited = false; + public GameFileCache GameFileCache; + + //public Vector4[] GetNodePositions() + //{ + // return null; + //} + //public EditorVertex[] GetPathVertices() + //{ + // return null; + //} + //public EditorVertex[] GetTriangleVertices() + //{ + // return TriangleVerts; + //} + //public EditorVertex[] TriangleVerts; + + public List Zones = new List(); + public List Emitters = new List(); + public List AllItems = new List(); + + + + public void Init(GameFileCache gameFileCache, Action updateStatus) + { + Inited = false; + + GameFileCache = gameFileCache; + + var rpfman = gameFileCache.RpfMan; + + + Zones.Clear(); + Emitters.Clear(); + AllItems.Clear(); + + + Dictionary dat151entries = new Dictionary(); + var audrpf = rpfman.FindRpfFile("x64\\audio\\audio_rel.rpf"); + if (audrpf != null) + { + AddRpfDat151s(audrpf, dat151entries); + } + + if (gameFileCache.EnableDlc) + { + var updrpf = rpfman.FindRpfFile("update\\update.rpf"); + if (updrpf != null) + { + AddRpfDat151s(updrpf, dat151entries); + } + foreach (var dlcrpf in GameFileCache.DlcActiveRpfs) //load from current dlc rpfs + { + AddRpfDat151s(dlcrpf, dat151entries); + } + } + + + foreach (var dat151entry in dat151entries.Values) + { + var relfile = rpfman.GetFile(dat151entry); + if (relfile != null) + { + foreach (var reldata in relfile.RelDatas) + { + if (reldata is Dat151Unk37) + { + Zones.Add(new AudioPlacement(relfile, reldata as Dat151Unk37)); + } + else if (reldata is Dat151Unk38) + { + Emitters.Add(new AudioPlacement(relfile, reldata as Dat151Unk38)); + } + } + } + } + + AllItems.AddRange(Zones); + AllItems.AddRange(Emitters); + + Inited = true; + } + + + + private void AddRpfDat151s(RpfFile rpffile, Dictionary dat151entries) + { + if (rpffile.AllEntries == null) return; + foreach (var entry in rpffile.AllEntries) + { + if (entry is RpfFileEntry) + { + RpfFileEntry fentry = entry as RpfFileEntry; + if (entry.NameLower.EndsWith(".dat151.rel")) + { + if (dat151entries.ContainsKey(entry.NameHash)) + { } + dat151entries[entry.NameHash] = fentry; + } + } + } + } + + + + } + + + + public class AudioPlacement + { + public RelFile RelFile { get; set; } + public Dat151Unk37 AudioZone { get; set; } + public Dat151Unk38 AudioEmitter { get; set; } + public Dat151ZoneShape Shape { get; set; } + public string ShortTypeName { get; set; } + public string FullTypeName { get; set; } + public Vector3 InnerPos { get; set; } + public Vector3 InnerMin { get; set; } + public Vector3 InnerMax { get; set; } + public float InnerRad { get; set; } + public Quaternion InnerOri { get; set; } + public Vector3 OuterPos { get; set; } + public Vector3 OuterMin { get; set; } + public Vector3 OuterMax { get; set; } + public float OuterRad { get; set; } + public Quaternion OuterOri { get; set; } + public Vector3 HitboxPos { get; set; } + public Vector3 HitboxMin { get; set; } + public Vector3 HitboxMax { get; set; } + public Quaternion HitboxOri { get; set; } + public Quaternion HitboxOriInv { get; set; } + public float HitSphereRad { get; set; } + + + + public AudioPlacement(RelFile rel, Dat151Unk37 zone) + { + RelFile = rel; + AudioZone = zone; + Shape = zone.Shape; + ShortTypeName = "AudioZone"; + FullTypeName = "Audio Zone"; + + float deg2rad = (float)(Math.PI / 180.0); + + switch (zone.Shape) + { + case Dat151ZoneShape.Box: + InnerPos = zone.InnerPos; + InnerMax = zone.InnerSize * 0.5f; + InnerMin = -InnerMax; + InnerOri = Quaternion.RotationAxis(Vector3.UnitZ, zone.InnerAngle * deg2rad); + break; + case Dat151ZoneShape.Sphere: + break; + case Dat151ZoneShape.Line: + InnerPos = zone.InnerPos; + InnerMin = new Vector3(-1.0f, -1.0f, 0.0f); + InnerMax = new Vector3(1.0f, 1.0f, (zone.InnerSize - zone.InnerPos).Length()); + InnerOri = Quaternion.Invert(Quaternion.LookAtLH(zone.InnerPos, zone.InnerSize, Vector3.UnitZ)); + break; + } + + OuterPos = zone.OuterPos; + OuterMax = zone.OuterSize * 0.5f; + OuterMin = -OuterMax; + OuterOri = Quaternion.RotationAxis(Vector3.UnitZ, zone.OuterAngle * deg2rad); + + bool useouter = ((InnerMax.X == 0) || (InnerMax.Y == 0) || (InnerMax.Z == 0)); + HitboxPos = useouter ? OuterPos : InnerPos; + HitboxMax = useouter ? OuterMax : InnerMax; + HitboxMin = useouter ? OuterMin : InnerMin; + HitboxOri = useouter ? OuterOri : InnerOri; + HitboxOriInv = Quaternion.Invert(HitboxOri); + } + public AudioPlacement(RelFile rel, Dat151Unk38 emitter) + { + RelFile = rel; + AudioEmitter = emitter; + Shape = Dat151ZoneShape.Sphere; + ShortTypeName = "AudioEmitter"; + FullTypeName = "Audio Emitter"; + + HitboxOri = Quaternion.Identity; + HitboxOriInv = Quaternion.Identity; + InnerPos = emitter.Position; + InnerRad = emitter.InnerRad; + OuterRad = emitter.OuterRad; + + bool useouter = (InnerRad == 0); + HitboxPos = InnerPos; + HitSphereRad = useouter ? OuterRad : InnerRad; + } + + + public void SetPosition(Vector3 pos) + { + bool useouter = ((InnerMax.X == 0) || (InnerMax.Y == 0) || (InnerMax.Z == 0)); + Vector3 delta = pos - InnerPos; + InnerPos = pos; + OuterPos += delta; + HitboxPos = useouter ? OuterPos : InnerPos; + } + public void SetOrientation(Quaternion ori) + { + HitboxOri = ori; + HitboxOriInv = Quaternion.Invert(ori); + + if (InnerOri == OuterOri) + { + InnerOri = HitboxOri; + OuterOri = HitboxOri; + } + else + { + //not sure yet how to allow independent rotation of inner & outer boxes... + //maybe only in project window? + bool useouter = ((InnerMax.X == 0) || (InnerMax.Y == 0) || (InnerMax.Z == 0)); + if (useouter) + { + OuterOri = HitboxOri; + } + else + { + InnerOri = HitboxOri; + } + } + } + + } + + +} diff --git a/World/PopZone.cs b/World/PopZones.cs similarity index 100% rename from World/PopZone.cs rename to World/PopZones.cs diff --git a/WorldForm.Designer.cs b/WorldForm.Designer.cs index 879272b..1df3cb1 100644 --- a/WorldForm.Designer.cs +++ b/WorldForm.Designer.cs @@ -248,6 +248,7 @@ namespace CodeWalker this.ToolbarSelectDistantLodLightsButton = new System.Windows.Forms.ToolStripMenuItem(); this.ToolbarSelectMloInstanceButton = new System.Windows.Forms.ToolStripMenuItem(); this.ToolbarSelectScenarioButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarSelectAudioButton = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); this.ToolbarMoveButton = new System.Windows.Forms.ToolStripButton(); this.ToolbarRotateButton = new System.Windows.Forms.ToolStripButton(); @@ -986,6 +987,7 @@ namespace CodeWalker | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.MultiFindTextBox.Location = new System.Drawing.Point(0, 117); + this.MultiFindTextBox.MaxLength = 1048576; this.MultiFindTextBox.Multiline = true; this.MultiFindTextBox.Name = "MultiFindTextBox"; this.MultiFindTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; @@ -1033,7 +1035,8 @@ namespace CodeWalker "Train Track", "Distant Lod Lights", "Mlo Instance", - "Scenario"}); + "Scenario", + "Audio"}); this.SelectionModeComboBox.Location = new System.Drawing.Point(51, 30); this.SelectionModeComboBox.Name = "SelectionModeComboBox"; this.SelectionModeComboBox.Size = new System.Drawing.Size(121, 21); @@ -2754,7 +2757,8 @@ namespace CodeWalker this.ToolbarSelectTrainTrackButton, this.ToolbarSelectDistantLodLightsButton, this.ToolbarSelectMloInstanceButton, - this.ToolbarSelectScenarioButton}); + this.ToolbarSelectScenarioButton, + this.ToolbarSelectAudioButton}); this.ToolbarSelectButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolbarSelectButton.Image"))); this.ToolbarSelectButton.ImageTransparentColor = System.Drawing.Color.Magenta; this.ToolbarSelectButton.Name = "ToolbarSelectButton"; @@ -2863,6 +2867,13 @@ namespace CodeWalker this.ToolbarSelectScenarioButton.Text = "Scenario"; this.ToolbarSelectScenarioButton.Click += new System.EventHandler(this.ToolbarSelectScenarioButton_Click); // + // ToolbarSelectAudioButton + // + this.ToolbarSelectAudioButton.Name = "ToolbarSelectAudioButton"; + this.ToolbarSelectAudioButton.Size = new System.Drawing.Size(181, 22); + this.ToolbarSelectAudioButton.Text = "Audio"; + this.ToolbarSelectAudioButton.Click += new System.EventHandler(this.ToolbarSelectAudioButton_Click); + // // toolStripSeparator1 // this.toolStripSeparator1.Name = "toolStripSeparator1"; @@ -3445,5 +3456,6 @@ namespace CodeWalker private System.Windows.Forms.ToolStripMenuItem ToolbarNewScenarioButton; private System.Windows.Forms.ToolStripMenuItem ToolbarOpenScenarioButton; private System.Windows.Forms.CheckBox PopZonesCheckBox; + private System.Windows.Forms.ToolStripMenuItem ToolbarSelectAudioButton; } } \ No newline at end of file diff --git a/WorldForm.cs b/WorldForm.cs index 708da9a..50857b7 100644 --- a/WorldForm.cs +++ b/WorldForm.cs @@ -57,6 +57,7 @@ namespace CodeWalker Trains trains = new Trains(); Scenarios scenarios = new Scenarios(); PopZones popzones = new PopZones(); + AudioZones audiozones = new AudioZones(); bool MouseLButtonDown = false; @@ -136,6 +137,7 @@ namespace CodeWalker List BoundingSpheres = new List(); List HilightBoxes = new List(); List SelectionBoxes = new List(); + List WhiteBoxes = new List(); bool controllightdir = false; //if not, use timecycle @@ -185,6 +187,8 @@ namespace CodeWalker bool renderpopzones = false; + bool renderaudiozones = false; + float timeofday = 12.0f; bool controltimeofday = true; @@ -565,6 +569,7 @@ namespace CodeWalker UpdateWidgets(); + WhiteBoxes.Clear(); SelectionBoxes.Clear(); HilightBoxes.Clear(); BoundingBoxes.Clear(); @@ -855,7 +860,7 @@ namespace CodeWalker Vector3 movevec = Vector3.Zero; - if (MapViewEnabled == true) + if (MapViewEnabled) { if (kbmovefwd) movevec.Y += 1.0f; if (kbmovebck) movevec.Y -= 1.0f; @@ -1566,7 +1571,7 @@ namespace CodeWalker if (((ent.Position.X + r) > cvwmin) && ((ent.Position.X - r) < cvwmax) && ((ent.Position.Y + r) > cvhmin) && ((ent.Position.Y - r) < cvhmax)) { //minZ = Math.Min(minZ, ent.BBMin.Z); - maxZ = Math.Max(maxZ, ent.BBMax.Z); + maxZ = Math.Max(maxZ, ent.BBMax.Z+50.0f);//add some bias to avoid clipping things... } } } @@ -1770,6 +1775,10 @@ namespace CodeWalker { RenderWorldPopZones(); } + if (renderaudiozones || (SelectionMode == MapSelectionMode.Audio)) + { + RenderWorldAudioZones(); + } } private bool RenderWorldYmapIsVisible(YmapFile ymap) { @@ -2063,14 +2072,101 @@ namespace CodeWalker { shaders.Enqueue(rnd); } + } + private void RenderWorldAudioZones() + { + if (!audiozones.Inited) return; + + //renderaudzonelist.Clear(); + //renderaudzonelist.AddRange(audzones.Zones.Values); + + if (ProjectForm != null) + { + //ProjectForm.GetVisibleAudioZones(camera, renderaudzonelist); + } + + + //RenderablePathBatch rnd = renderableCache.GetRenderablePathBatch(audiozones); + //if ((rnd != null) && (rnd.IsLoaded)) + //{ + // shaders.Enqueue(rnd); + //} + + + BoundingBox bbox = new BoundingBox(); + Ray mray = new Ray(); + mray.Position = camera.MouseRay.Position + camera.Position; + mray.Direction = camera.MouseRay.Direction; + float hitdist = float.MaxValue; + + MapBox lastHitOuterBox = new MapBox(); + MapBox mb = new MapBox(); + + for (int i = 0; i < audiozones.AllItems.Count; i++) + { + var placement = audiozones.AllItems[i]; + switch (placement.Shape) + { + case Dat151ZoneShape.Box: + case Dat151ZoneShape.Line: + + mb.CamRelPos = placement.InnerPos - camera.Position; + mb.BBMin = placement.InnerMin; + mb.BBMax = placement.InnerMax; + mb.Orientation = placement.InnerOri; + mb.Scale = Vector3.One; + HilightBoxes.Add(mb); + + mb.CamRelPos = placement.OuterPos - camera.Position; + mb.BBMin = placement.OuterMin; + mb.BBMax = placement.OuterMax; + mb.Orientation = placement.OuterOri; + mb.Scale = Vector3.One; + BoundingBoxes.Add(mb); + + Vector3 hbcamrel = (placement.HitboxPos - camera.Position); + Ray mraytrn = new Ray(); + mraytrn.Position = placement.HitboxOriInv.Multiply(camera.MouseRay.Position - hbcamrel); + mraytrn.Direction = placement.HitboxOriInv.Multiply(mray.Direction); + bbox.Minimum = placement.HitboxMin; + bbox.Maximum = placement.HitboxMax; + if (mraytrn.Intersects(ref bbox, out hitdist) && (hitdist < CurMouseHit.HitDist) && (hitdist > 0)) + { + CurMouseHit.Audio = placement; + CurMouseHit.HitDist = hitdist; + CurMouseHit.CamRel = hbcamrel; + CurMouseHit.AABB = bbox; + lastHitOuterBox = mb; //highlight the outer box + } + break; + case Dat151ZoneShape.Sphere: + break; + default: + break;//shouldn't get here + } + } + + if (CurMouseHit.Audio != null) + { + //hilight the outer bounds of moused item + switch (CurMouseHit.Audio.Shape) + { + case Dat151ZoneShape.Box: + case Dat151ZoneShape.Line: + HilightBoxes.Add(lastHitOuterBox); + break; + case Dat151ZoneShape.Sphere: + //HilightSpheres.Add(lastHitOuterSphere); + break; + } + } } - private void RenderSingleItem() { //start point for model view mode rendering @@ -2869,72 +2965,31 @@ namespace CodeWalker //immediately render the entity bounding boxes/spheres - depending on boundsmode - //////rendering grass instance batch bounding boxes... - ////shaders.SetDepthStencilMode(context, renderboundsclip ? DepthStencilMode.Enabled : DepthStencilMode.DisableAll); - ////var shader = shaders.Bounds; - ////shader.SetMode(BoundsShaderMode.Box); - ////shader.SetShader(context); - ////shader.SetInputLayout(context, VertexType.Default); - ////shader.SetSceneVars(context, camera); - ////shader.SetColourVars(context, new Vector4(0, 0, 1, 1)); - ////for (int i = 0; i < shaders.RenderInstBatches.Count; i++) - ////{ - //// var b = shaders.RenderInstBatches[i]; - //// var bpos = b.Batch.GrassInstanceBatch.Position; - //// var camrel = bpos - camera.Position; - //// var bbmin = b.Batch.GrassInstanceBatch.Batch.BatchAABB.min.XYZ() - bpos; - //// var bbmax = b.Batch.GrassInstanceBatch.Batch.BatchAABB.max.XYZ() - bpos; - //// shader.SetBoxVars(context, camrel, bbmin, bbmax, Quaternion.Identity, Vector3.One); - //// shader.DrawBox(context); - ////} - ////shader.UnbindResources(context); - - - - - var mode = boundsmode; //try avoid multithreading issues bool clip = renderboundsclip; switch (SelectionMode) { - case MapSelectionMode.EntityExtension: - case MapSelectionMode.ArchetypeExtension: - case MapSelectionMode.TimeCycleModifier: - case MapSelectionMode.CarGenerator: - case MapSelectionMode.DistantLodLights: - case MapSelectionMode.Grass: - case MapSelectionMode.Collision: - case MapSelectionMode.NavMesh: - case MapSelectionMode.Path: - case MapSelectionMode.TrainTrack: - case MapSelectionMode.Scenario: - mode = BoundsShaderMode.Box; - break; case MapSelectionMode.WaterQuad: case MapSelectionMode.MloInstance: - mode = BoundsShaderMode.Box; clip = false; break; } - if (mode == BoundsShaderMode.None) - { return; } - Vector3 colour = new Vector3(0, 0, 1) * globalLights.HdrIntensity; Vector3 colourhi = new Vector3(0, 1, 1) * globalLights.HdrIntensity; shaders.SetDepthStencilMode(context, clip ? DepthStencilMode.Enabled : DepthStencilMode.DisableAll); var shader = shaders.Bounds; - shader.SetMode(mode); - shader.SetShader(context); - shader.SetInputLayout(context, VertexType.Default); - shader.SetSceneVars(context, camera, null, globalLights); - shader.SetColourVars(context, new Vector4(colour, 1)); - - if (mode == BoundsShaderMode.Box) + if ((BoundingBoxes.Count > 0) || (HilightBoxes.Count > 0)) { + shader.SetMode(BoundsShaderMode.Box); + shader.SetShader(context); + shader.SetInputLayout(context, VertexType.Default); + shader.SetSceneVars(context, camera, null, globalLights); + shader.SetColourVars(context, new Vector4(colour, 1)); + for (int i = 0; i < BoundingBoxes.Count; i++) { MapBox mb = BoundingBoxes[i]; @@ -2949,8 +3004,15 @@ namespace CodeWalker shader.DrawBox(context); } } - else if (mode == BoundsShaderMode.Sphere) + + if (BoundingSpheres.Count > 0) { + shader.SetMode(BoundsShaderMode.Sphere); + shader.SetShader(context); + shader.SetInputLayout(context, VertexType.Default); + shader.SetSceneVars(context, camera, null, globalLights); + shader.SetColourVars(context, new Vector4(colour, 1)); + for (int i = 0; i < BoundingSpheres.Count; i++) { MapSphere ms = BoundingSpheres[i]; @@ -2960,6 +3022,7 @@ namespace CodeWalker } + shader.UnbindResources(context); } @@ -3019,6 +3082,9 @@ namespace CodeWalker case MapSelectionMode.Scenario: change = change || (LastMouseHit.ScenarioNode != PrevMouseHit.ScenarioNode); break; + case MapSelectionMode.Audio: + change = change || (LastMouseHit.Audio != PrevMouseHit.Audio); + break; } @@ -3086,6 +3152,10 @@ namespace CodeWalker ori = sp.Orientation; } } + if (CurMouseHit.Audio != null) + { + ori = CurMouseHit.Audio.HitboxOri; + } shaders.SetDepthStencilMode(context, clip ? DepthStencilMode.Enabled : DepthStencilMode.DisableAll); @@ -3272,6 +3342,22 @@ namespace CodeWalker //clip = false; } + if (selectionItem.Audio != null) + { + var au = selectionItem.Audio; + camrel = au.HitboxPos - camera.Position; + ori = au.HitboxOri; + bbmin = au.HitboxMin; + bbmax = au.HitboxMax; + + MapBox wbox = new MapBox(); + wbox.CamRelPos = au.OuterPos - camera.Position; + wbox.BBMin = au.OuterMin; + wbox.BBMax = au.OuterMax; + wbox.Orientation = au.OuterOri; + wbox.Scale = scale; + WhiteBoxes.Add(wbox); + } @@ -3452,23 +3538,28 @@ namespace CodeWalker - if (SelectionBoxes.Count > 0) + Vector3 coloursel = new Vector3(0, 1, 0) * globalLights.HdrIntensity * 5.0f; + Vector3 colourwht = new Vector3(1, 1, 1) * globalLights.HdrIntensity * 10.0f; + var shader = shaders.Bounds; + shader.SetMode(BoundsShaderMode.Box); + shader.SetShader(context); + shader.SetInputLayout(context, VertexType.Default); + shader.SetSceneVars(context, camera, null, globalLights); + shader.SetColourVars(context, new Vector4(colourwht, 1)); + for (int i = 0; i < WhiteBoxes.Count; i++) { - Vector3 coloursel = new Vector3(0, 1, 0) * globalLights.HdrIntensity * 5.0f; - var shader = shaders.Bounds; - shader.SetMode(BoundsShaderMode.Box); - shader.SetShader(context); - shader.SetInputLayout(context, VertexType.Default); - shader.SetSceneVars(context, camera, null, globalLights); - shader.SetColourVars(context, new Vector4(coloursel, 1)); - for (int i = 0; i < SelectionBoxes.Count; i++) - { - MapBox mb = SelectionBoxes[i]; - shader.SetBoxVars(context, mb.CamRelPos, mb.BBMin, mb.BBMax, mb.Orientation, mb.Scale); - shader.DrawBox(context); - } - shader.UnbindResources(context); + MapBox mb = WhiteBoxes[i]; + shader.SetBoxVars(context, mb.CamRelPos, mb.BBMin, mb.BBMax, mb.Orientation, mb.Scale); + shader.DrawBox(context); } + shader.SetColourVars(context, new Vector4(coloursel, 1)); + for (int i = 0; i < SelectionBoxes.Count; i++) + { + MapBox mb = SelectionBoxes[i]; + shader.SetBoxVars(context, mb.CamRelPos, mb.BBMin, mb.BBMax, mb.Orientation, mb.Scale); + shader.DrawBox(context); + } + shader.UnbindResources(context); } @@ -5539,6 +5630,11 @@ namespace CodeWalker ToolbarDeleteItemButton.Enabled = true; ToolbarDeleteItemButton.Text = "Delete scenario point"; } + else if (item.Audio != null) + { + SelectionEntityTabPage.Text = item.Audio.ShortTypeName; + SelEntityPropertyGrid.SelectedObject = item.Audio; + } else { SelectionEntityTabPage.Text = "Entity"; @@ -5883,6 +5979,9 @@ namespace CodeWalker UpdateStatus("Loading popzones..."); popzones.Init(gameFileCache, UpdateStatus); + UpdateStatus("Loading audio zones..."); + audiozones.Init(gameFileCache, UpdateStatus); + UpdateStatus("Loading world..."); space.Init(gameFileCache, UpdateStatus); @@ -7357,6 +7456,10 @@ namespace CodeWalker mode = MapSelectionMode.Scenario; ToolbarSelectScenarioButton.Checked = true; break; + case "Audio": + mode = MapSelectionMode.Audio; + ToolbarSelectAudioButton.Checked = true; + break; } SelectionMode = mode; @@ -8930,6 +9033,12 @@ namespace CodeWalker SetMouseSelect(true); } + private void ToolbarSelectAudioButton_Click(object sender, EventArgs e) + { + SetSelectionMode("Audio"); + SetMouseSelect(true); + } + private void ToolbarMoveButton_Click(object sender, EventArgs e) { SetWidgetMode(ToolbarMoveButton.Checked ? "Default" : "Position"); @@ -9324,6 +9433,7 @@ namespace CodeWalker public TrainTrackNode TrainTrackNode { get; set; } public ScenarioNode ScenarioNode { get; set; } public MCScenarioChainingEdge ScenarioEdge { get; set; } + public AudioPlacement Audio { get; set; } public bool MultipleSelection { get; set; } public Vector3 MultipleSelectionCenter { get; set; } @@ -9354,7 +9464,8 @@ namespace CodeWalker (TrainTrackNode != null) || (DistantLodLights != null) || (MloEntityDef != null) || - (ScenarioNode != null); + (ScenarioNode != null) || + (Audio != null); } } @@ -9381,7 +9492,8 @@ namespace CodeWalker || (NavPoly != mhit.NavPoly) || (PathNode != mhit.PathNode) || (TrainTrackNode != mhit.TrainTrackNode) - || (ScenarioNode != mhit.ScenarioNode); + || (ScenarioNode != mhit.ScenarioNode) + || (Audio != mhit.Audio); } public bool CheckForChanges() { @@ -9401,7 +9513,8 @@ namespace CodeWalker || (PathNode != null) || (PathLink != null) || (TrainTrackNode != null) - || (ScenarioNode != null); + || (ScenarioNode != null) + || (Audio != null); } @@ -9426,6 +9539,7 @@ namespace CodeWalker MloEntityDef = null; ScenarioNode = null; ScenarioEdge = null; + Audio = null; MultipleSelection = false; AABB = new BoundingBox(); GeometryIndex = 0; @@ -9492,6 +9606,10 @@ namespace CodeWalker { name = ScenarioNode.ToString(); } + if (Audio != null) + { + name = Audio.ShortTypeName + " " + FloatUtil.GetVector3String(Audio.InnerPos); + } return name; } @@ -9554,6 +9672,10 @@ namespace CodeWalker { name = ScenarioNode.ToString(); } + if (Audio != null) + { + name = Audio.ShortTypeName + " " + FloatUtil.GetVector3String(Audio.InnerPos); + } return name; } @@ -9593,7 +9715,10 @@ namespace CodeWalker { res = true; } - + else if (Audio != null) + { + res = true; + } return res; } } @@ -9629,6 +9754,10 @@ namespace CodeWalker { return ScenarioNode.Position; } + else if (Audio != null) + { + return Audio.InnerPos; + } return Vector3.Zero; } } @@ -9664,6 +9793,10 @@ namespace CodeWalker { return ScenarioNode.Orientation; } + else if (Audio != null) + { + return Audio.HitboxOri; + } return Quaternion.Identity; } } @@ -9699,6 +9832,10 @@ namespace CodeWalker { return WidgetAxis.Z; } + else if (Audio != null) + { + return WidgetAxis.XYZ; + } return WidgetAxis.None; } } @@ -9734,6 +9871,10 @@ namespace CodeWalker { return Vector3.One; } + else if (Audio != null) + { + return Vector3.One; + } return Vector3.One; } } @@ -9783,6 +9924,10 @@ namespace CodeWalker { ScenarioNode.SetPosition(newpos); } + else if (Audio != null) + { + Audio.SetPosition(newpos); + } } public void SetRotation(Quaternion newrot, Quaternion oldrot, bool editPivot) @@ -9806,7 +9951,10 @@ namespace CodeWalker { ScenarioNode.SetOrientation(newrot); } - + else if (Audio != null) + { + Audio.SetOrientation(newrot); + } } public void SetScale(Vector3 newscale, Vector3 oldscale, bool editPivot) { @@ -9846,6 +9994,7 @@ namespace CodeWalker MloInstance = 13, Scenario = 14, PopZone = 15, + Audio = 16, } diff --git a/WorldInfoForm.Designer.cs b/WorldInfoForm.Designer.cs index 265ddf3..51ccf9c 100644 --- a/WorldInfoForm.Designer.cs +++ b/WorldInfoForm.Designer.cs @@ -544,7 +544,8 @@ namespace CodeWalker "Train Track", "Distant Lod Lights", "Mlo Instance", - "Scenario"}); + "Scenario", + "Audio"}); this.SelectionModeComboBox.Location = new System.Drawing.Point(453, 12); this.SelectionModeComboBox.Name = "SelectionModeComboBox"; this.SelectionModeComboBox.Size = new System.Drawing.Size(121, 21); diff --git a/WorldInfoForm.cs b/WorldInfoForm.cs index f994dcb..42cf591 100644 --- a/WorldInfoForm.cs +++ b/WorldInfoForm.cs @@ -139,6 +139,11 @@ namespace CodeWalker SelectionEntityTabPage.Text = item.ScenarioNode.FullTypeName; SelEntityPropertyGrid.SelectedObject = item.ScenarioNode; } + else if (item.Audio != null) + { + SelectionEntityTabPage.Text = item.Audio.FullTypeName; + SelEntityPropertyGrid.SelectedObject = item.Audio; + } else { SelectionEntityTabPage.Text = "Entity";