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";