Render and select audio zones (box shapes only, no spheres yet)

This commit is contained in:
dexyfex 2017-12-22 07:26:04 +11:00
parent b1f2918d12
commit d8fd82c350
8 changed files with 582 additions and 175 deletions

View File

@ -415,6 +415,7 @@
<Compile Include="WorldSearchForm.Designer.cs">
<DependentUpon>WorldSearchForm.cs</DependentUpon>
</Compile>
<Compile Include="World\AudioZones.cs" />
<Compile Include="World\Camera.cs" />
<Compile Include="Rendering\DirectX\DXForm.cs" />
<Compile Include="Rendering\DirectX\DXManager.cs" />
@ -435,7 +436,7 @@
<Compile Include="GameFiles\FileTypes\YtdFile.cs" />
<Compile Include="World\Clouds.cs" />
<Compile Include="World\Entity.cs" />
<Compile Include="World\PopZone.cs" />
<Compile Include="World\PopZones.cs" />
<Compile Include="World\Scenarios.cs" />
<Compile Include="World\Space.cs" />
<Compile Include="World\Timecycle.cs" />

View File

@ -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)
{ }
}
}
//FlagsUint[] flags = new FlagsUint[t4];
//for (int i = 0; i < t4; i++)
//byte[] remainder = br.ReadBytes((int)bytesleft);
//for (int i = 0; i < remainder.Length; i++)
//{
// flags[i] = br.ReadUInt32();
// if (remainder[i] != 0)
// { } //no hits here! probably got everything, i'm assuming the block is padded to 0x10 or something.
//}
//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);
//RecVec(Size02);
//RecVec(Size03);
//RecVec(Size04);
//RecVec(Vec05);
RecVec(Pos06);
//RecVec(Size07);
//RecVec(Size08);
//RecVec(Size09);
//RecVec(Vec10);
//RecVec(Vec11);
//RecVec(Vec12);
//RecVec(Vec13);
//RecVec(Pos01);//debug coords output
//RecVec(Pos06);
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();

246
World/AudioZones.cs Normal file
View File

@ -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<AudioPlacement> Zones = new List<AudioPlacement>();
public List<AudioPlacement> Emitters = new List<AudioPlacement>();
public List<AudioPlacement> AllItems = new List<AudioPlacement>();
public void Init(GameFileCache gameFileCache, Action<string> updateStatus)
{
Inited = false;
GameFileCache = gameFileCache;
var rpfman = gameFileCache.RpfMan;
Zones.Clear();
Emitters.Clear();
AllItems.Clear();
Dictionary<uint, RpfFileEntry> dat151entries = new Dictionary<uint, RpfFileEntry>();
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<RelFile>(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<uint, RpfFileEntry> 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;
}
}
}
}
}

16
WorldForm.Designer.cs generated
View File

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

View File

@ -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<MapSphere> BoundingSpheres = new List<MapSphere>();
List<MapBox> HilightBoxes = new List<MapBox>();
List<MapBox> SelectionBoxes = new List<MapBox>();
List<MapBox> WhiteBoxes = new List<MapBox>();
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);
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));
if (mode == BoundsShaderMode.Box)
{
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,14 +3538,20 @@ 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++)
{
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++)
{
@ -3468,7 +3560,6 @@ namespace CodeWalker
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,
}

View File

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

View File

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