LodLights editing basics

This commit is contained in:
dexy 2021-04-26 04:41:02 +10:00
parent edd8916c1f
commit 5cdde7a34f
12 changed files with 2282 additions and 28 deletions

View File

@ -554,7 +554,6 @@ namespace CodeWalker.GameFiles
CCarGens[i] = CarGenerators[i].CCarGen; CCarGens[i] = CarGenerators[i].CCarGen;
} }
} }
public void BuildInstances() public void BuildInstances()
{ {
if (GrassInstanceBatches == null) if (GrassInstanceBatches == null)
@ -580,6 +579,16 @@ namespace CodeWalker.GameFiles
GrassInstanceBatches[i].Batch = b; GrassInstanceBatches[i].Batch = b;
} }
} }
public void BuildLodLights()
{
if (LODLights == null) return;
LODLights.RebuildFromLodLights();
}
public void BuildDistantLodLights()
{
//how to rebuild these here? the LODlights array is on the child ymap...
//for now, they are being updated as they are edited in project window
}
public byte[] Save() public byte[] Save()
{ {
@ -590,10 +599,10 @@ namespace CodeWalker.GameFiles
BuildCEntityDefs(); //technically this isn't required anymore since the CEntityDefs is no longer used for saving. BuildCEntityDefs(); //technically this isn't required anymore since the CEntityDefs is no longer used for saving.
BuildCCarGens(); BuildCCarGens();
BuildInstances(); BuildInstances();
BuildLodLights();
BuildDistantLodLights();
//TODO: //TODO:
//BuildLodLights();
//BuildDistantLodLights();
//BuildTimecycleModifiers(); //already being saved - update them.. //BuildTimecycleModifiers(); //already being saved - update them..
//BuildBoxOccluders(); //BuildBoxOccluders();
//BuildOccludeModels(); //BuildOccludeModels();
@ -654,8 +663,6 @@ namespace CodeWalker.GameFiles
if (mapdata.occludeModels.Count1 != 0) LogSaveWarning("occludeModels were not saved. (TODO!)"); if (mapdata.occludeModels.Count1 != 0) LogSaveWarning("occludeModels were not saved. (TODO!)");
if (mapdata.boxOccluders.Count1 != 0) LogSaveWarning("boxOccluders were not saved. (TODO!)"); if (mapdata.boxOccluders.Count1 != 0) LogSaveWarning("boxOccluders were not saved. (TODO!)");
if (mapdata.instancedData.PropInstanceList.Count1 != 0) LogSaveWarning("instancedData.PropInstanceList was not saved. (TODO!)"); if (mapdata.instancedData.PropInstanceList.Count1 != 0) LogSaveWarning("instancedData.PropInstanceList was not saved. (TODO!)");
if (mapdata.LODLightsSOA.direction.Count1 != 0) LogSaveWarning("LODLightsSOA was not saved. (TODO!)");
if (mapdata.DistantLODLightsSOA.position.Count1 != 0) LogSaveWarning("DistantLODLightsSOA was not saved. (TODO!)");
mapdata.containerLods = new Array_Structure(); mapdata.containerLods = new Array_Structure();
mapdata.occludeModels = new Array_Structure(); mapdata.occludeModels = new Array_Structure();
mapdata.boxOccluders = new Array_Structure(); mapdata.boxOccluders = new Array_Structure();
@ -1019,6 +1026,70 @@ namespace CodeWalker.GameFiles
} }
public void AddLodLight(YmapLODLight lodlight)
{
if (LODLights == null)
{
LODLights = new YmapLODLights();
LODLights.Ymap = this;
}
List<YmapLODLight> lodlights = new List<YmapLODLight>();
if (LODLights?.LodLights != null) lodlights.AddRange(LODLights.LodLights);
lodlight.LodLights = this.LODLights;
lodlight.Index = lodlights.Count;
lodlights.Add(lodlight);
LODLights.LodLights = lodlights.ToArray();
HasChanged = true;
if (Parent?.DistantLODLights != null)
{
Parent.DistantLODLights.RebuildFromLodLights(LODLights.LodLights);
Parent.HasChanged = true;
}
}
public bool RemoveLodLight(YmapLODLight lodlight)
{
if (lodlight == null) return false;
List<YmapLODLight> newlodlights = new List<YmapLODLight>();
var lodlights = LODLights?.LodLights;
if (lodlights != null)
{
for (int i = 0; i < lodlights.Length; i++)
{
var ll = lodlights[i];
if (ll != lodlight)
{
newlodlights.Add(ll);
}
}
if (newlodlights.Count == lodlights.Length)
{
return false; //nothing removed... wasn't present?
}
}
for (int i = 0; i < newlodlights.Count; i++)
{
newlodlights[i].Index = i;
}
LODLights.LodLights = newlodlights.ToArray();
HasChanged = true;
if (Parent?.DistantLODLights != null)
{
Parent.DistantLODLights.RebuildFromLodLights(LODLights.LodLights);
Parent.HasChanged = true;
}
return true;
}
public void AddGrassBatch(YmapGrassInstanceBatch newbatch) public void AddGrassBatch(YmapGrassInstanceBatch newbatch)
{ {
List<YmapGrassInstanceBatch> batches = new List<YmapGrassInstanceBatch>(); List<YmapGrassInstanceBatch> batches = new List<YmapGrassInstanceBatch>();
@ -1118,6 +1189,14 @@ namespace CodeWalker.GameFiles
{ {
contentFlags = SetBit(contentFlags, 10); //64 contentFlags = SetBit(contentFlags, 10); //64
} }
if ((LODLights != null) && ((LODLights.direction?.Length ?? 0) > 0))
{
contentFlags = SetBit(contentFlags, 7); //128
}
if ((DistantLODLights != null) && ((DistantLODLights.positions?.Length ?? 0) > 0))
{
flags = SetBit(flags, 1); //2
}
bool change = false; bool change = false;
@ -1203,7 +1282,6 @@ namespace CodeWalker.GameFiles
emin = Vector3.Min(emin, bbmin); emin = Vector3.Min(emin, bbmin);
emax = Vector3.Max(emax, bbmax); emax = Vector3.Max(emax, bbmax);
smin = Vector3.Min(smin, sbmin); smin = Vector3.Min(smin, sbmin);
smax = Vector3.Max(smax, sbmax); smax = Vector3.Max(smax, sbmax);
} }
@ -1216,7 +1294,6 @@ namespace CodeWalker.GameFiles
{ {
emin = Vector3.Min(emin, batch.AABBMin); emin = Vector3.Min(emin, batch.AABBMin);
emax = Vector3.Max(emax, batch.AABBMax); emax = Vector3.Max(emax, batch.AABBMax);
smin = Vector3.Min(smin, (batch.AABBMin - batch.Batch.lodDist)); // + lodoffset smin = Vector3.Min(smin, (batch.AABBMin - batch.Batch.lodDist)); // + lodoffset
smax = Vector3.Max(smax, (batch.AABBMax + batch.Batch.lodDist)); // - lodoffset smax = Vector3.Max(smax, (batch.AABBMax + batch.Batch.lodDist)); // - lodoffset
} }
@ -1226,14 +1303,31 @@ namespace CodeWalker.GameFiles
{ {
foreach (var cargen in CarGenerators) foreach (var cargen in CarGenerators)
{ {
emin = Vector3.Min(emin, cargen.BBMin); var len = cargen._CCarGen.perpendicularLength;
emax = Vector3.Max(emax, cargen.BBMax); emin = Vector3.Min(emin, cargen.Position - len);
emax = Vector3.Max(emax, cargen.Position + len);
smin = Vector3.Min(smin, cargen.BBMin - cargen._CCarGen.perpendicularLength); //just a random guess, maybe should be more? smin = Vector3.Min(smin, cargen.Position - len*2.0f); //just a random guess, maybe should be more?
smax = Vector3.Max(smax, cargen.BBMax + cargen._CCarGen.perpendicularLength); smax = Vector3.Max(smax, cargen.Position + len*2.0f);
} }
} }
if (LODLights != null)
{
LODLights.CalcBB();
emin = Vector3.Min(emin, LODLights.BBMin - 20.0f); //about right
emax = Vector3.Max(emax, LODLights.BBMax + 20.0f);
smin = Vector3.Min(smin, (LODLights.BBMin - 950.0f)); //seems correct
smax = Vector3.Max(smax, (LODLights.BBMax + 950.0f));
}
if (DistantLODLights != null)
{
DistantLODLights.CalcBB();
emin = Vector3.Min(emin, DistantLODLights.BBMin - 20.0f); //not exact, but probably close enough
emax = Vector3.Max(emax, DistantLODLights.BBMax + 20.0f);
smin = Vector3.Min(smin, (DistantLODLights.BBMin - 3000.0f)); //seems correct
smax = Vector3.Max(smax, (DistantLODLights.BBMax + 3000.0f));
}
bool change = false; bool change = false;
if (_CMapData.entitiesExtentsMin != emin) if (_CMapData.entitiesExtentsMin != emin)
@ -2293,6 +2387,34 @@ namespace CodeWalker.GameFiles
} }
public void RebuildFromLodLights(YmapLODLight[] lodlights)
{
var n = lodlights?.Length ?? 0;
if (n == 0) return;
colours = new uint[n];
positions = new MetaVECTOR3[n];
var nstreetlights = 0;
for (int i = 0; i < n; i++)
{
var ll = lodlights[i];
colours[i] = (uint)(ll.Colour.ToBgra());
positions[i] = new MetaVECTOR3(ll.Position);
if ((ll.StateFlags1 & 1) > 0)
{
nstreetlights++;
}
}
var cdll = CDistantLODLight;
cdll.numStreetLights = (ushort)nstreetlights;
CalcBB();
}
public override string ToString() public override string ToString()
{ {
if (Ymap != null) if (Ymap != null)
@ -2320,7 +2442,7 @@ namespace CodeWalker.GameFiles
public Vector3 BBMax { get; set; } public Vector3 BBMax { get; set; }
public YmapFile Ymap { get; set; } public YmapFile Ymap { get; set; }
public YmapLODLight[] Lights { get; set; } public YmapLODLight[] LodLights { get; set; }
public PathBVH BVH { get; set; } public PathBVH BVH { get; set; }
@ -2340,20 +2462,21 @@ namespace CodeWalker.GameFiles
n = Math.Min(n, coronaIntensity?.Length ?? 0); n = Math.Min(n, coronaIntensity?.Length ?? 0);
if (n == 0) return; if (n == 0) return;
Lights = new YmapLODLight[n]; LodLights = new YmapLODLight[n];
for (int i = 0; i < n; i++) for (int i = 0; i < n; i++)
{ {
var l = new YmapLODLight(); var l = new YmapLODLight();
l.Init(this, parent, i); l.Init(this, parent, i);
Lights[i] = l; LodLights[i] = l;
} }
CalcBB();
BuildBVH(); BuildBVH();
} }
public void BuildBVH() public void BuildBVH()
{ {
BVH = new PathBVH(Lights, 10, 10); BVH = new PathBVH(LodLights, 10, 10);
} }
@ -2383,6 +2506,48 @@ namespace CodeWalker.GameFiles
{ } { }
} }
public void RebuildFromLodLights()
{
var n = LodLights?.Length ?? 0;
if (n <= 0)
{
direction = null;
falloff = null;
falloffExponent = null;
timeAndStateFlags = null;
hash = null;
coneInnerAngle = null;
coneOuterAngleOrCapExt = null;
coronaIntensity = null;
}
else
{
direction = new MetaVECTOR3[n];
falloff = new float[n];
falloffExponent = new float[n];
timeAndStateFlags = new uint[n];
hash = new uint[n];
coneInnerAngle = new byte[n];
coneOuterAngleOrCapExt = new byte[n];
coronaIntensity = new byte[n];
for (int i = 0; i < n; i++)
{
var ll = LodLights[i];
direction[i] = new MetaVECTOR3(ll.Direction);
falloff[i] = ll.Falloff;
falloffExponent[i] = ll.FalloffExponent;
timeAndStateFlags[i] = ll.TimeAndStateFlags;
hash[i] = ll.Hash;
coneInnerAngle[i] = ll.ConeInnerAngle;
coneOuterAngleOrCapExt[i] = ll.ConeOuterAngleOrCapExt;
coronaIntensity[i] = ll.CoronaIntensity;
}
}
}
public override string ToString() public override string ToString()
{ {
if (Ymap != null) if (Ymap != null)
@ -2396,6 +2561,7 @@ namespace CodeWalker.GameFiles
[TypeConverter(typeof(ExpandableObjectConverter))] [TypeConverter(typeof(ExpandableObjectConverter))]
public class YmapLODLight : BasePathNode public class YmapLODLight : BasePathNode
{ {
public YmapFile Ymap { get { return LodLights?.Ymap ?? DistLodLights?.Ymap; } }
public YmapLODLights LodLights { get; set; } public YmapLODLights LodLights { get; set; }
public YmapDistantLODLights DistLodLights { get; set; } public YmapDistantLODLights DistLodLights { get; set; }
public int Index { get; set; } public int Index { get; set; }
@ -2404,7 +2570,7 @@ namespace CodeWalker.GameFiles
public Vector3 Direction { get; set; } public Vector3 Direction { get; set; }
public float Falloff { get; set; } public float Falloff { get; set; }
public float FalloffExponent { get; set; } public float FalloffExponent { get; set; }
public FlagsUint TimeAndStateFlags { get; set; } public uint TimeAndStateFlags { get; set; }
public uint Hash { get; set; } public uint Hash { get; set; }
public byte ConeInnerAngle { get; set; } public byte ConeInnerAngle { get; set; }
public byte ConeOuterAngleOrCapExt { get; set; } public byte ConeOuterAngleOrCapExt { get; set; }
@ -2422,6 +2588,43 @@ namespace CodeWalker.GameFiles
{ {
return (LightType)((TimeAndStateFlags >> 26) & 7); return (LightType)((TimeAndStateFlags >> 26) & 7);
} }
set
{
TimeAndStateFlags = (TimeAndStateFlags & 0xE3FFFFFF) + (((uint)value & 7) << 26);
}
}
public FlagsUint TimeFlags
{
get
{
return (TimeAndStateFlags & 0xFFFFFF);
}
set
{
TimeAndStateFlags = (TimeAndStateFlags & 0xFF000000) + (value & 0xFFFFFF);
}
}
public uint StateFlags1
{
get
{
return (TimeAndStateFlags >> 24) & 3;
}
set
{
TimeAndStateFlags = (TimeAndStateFlags & 0xFCFFFFFF) + ((value & 3) << 24);
}
}
public uint StateFlags2
{
get
{
return (TimeAndStateFlags >> 29) & 7;
}
set
{
TimeAndStateFlags = (TimeAndStateFlags & 0x1FFFFFFF) + ((value & 7) << 29);
}
} }
@ -2445,6 +2648,13 @@ namespace CodeWalker.GameFiles
ConeOuterAngleOrCapExt = l.coneOuterAngleOrCapExt[i]; ConeOuterAngleOrCapExt = l.coneOuterAngleOrCapExt[i];
CoronaIntensity = l.coronaIntensity[i]; CoronaIntensity = l.coronaIntensity[i];
UpdateTangentsAndOrientation();
Scale = Vector3.One;
}
public void UpdateTangentsAndOrientation()
{
switch (Type) switch (Type)
{ {
default: default:
@ -2475,14 +2685,27 @@ namespace CodeWalker.GameFiles
m.Row3 = new Vector4(Direction, 0); m.Row3 = new Vector4(Direction, 0);
Orientation = Quaternion.RotationMatrix(m); Orientation = Quaternion.RotationMatrix(m);
} }
Scale = Vector3.One;
} }
public void SetColour(Color c)
{
Colour = c;
if ((DistLodLights?.colours != null) && (DistLodLights.colours.Length >= Index))
{
DistLodLights.colours[Index] = (uint)(c.ToBgra());
}
}
public void SetPosition(Vector3 pos) public void SetPosition(Vector3 pos)
{ {
Position = pos; Position = pos;
if ((DistLodLights?.positions != null) && (DistLodLights.positions.Length >= Index))
{
DistLodLights.positions[Index] = new MetaVECTOR3(pos);
}
} }
public void SetOrientation(Quaternion ori) public void SetOrientation(Quaternion ori)
{ {
@ -2494,6 +2717,27 @@ namespace CodeWalker.GameFiles
} }
public void CopyFrom(YmapLODLight l)
{
Colour = l.Colour;
Position = l.Position;
Direction = l.Direction;
Falloff = l.Falloff;
FalloffExponent = l.FalloffExponent;
TimeAndStateFlags = l.TimeAndStateFlags;
Hash = l.Hash;
ConeInnerAngle = l.ConeInnerAngle;
ConeOuterAngleOrCapExt = l.ConeOuterAngleOrCapExt;
CoronaIntensity = l.CoronaIntensity;
Orientation = l.Orientation;
Scale = l.Scale;
TangentX = l.TangentX;
TangentY = l.TangentY;
}
public override string ToString() public override string ToString()
{ {
return Index.ToString() + ": " + Position.ToString(); return Index.ToString() + ": " + Position.ToString();

View File

@ -0,0 +1,619 @@

namespace CodeWalker.Project.Panels
{
partial class EditYmapLodLightPanel
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(EditYmapLodLightPanel));
this.GoToButton = new System.Windows.Forms.Button();
this.PositionTextBox = new System.Windows.Forms.TextBox();
this.label31 = new System.Windows.Forms.Label();
this.DeleteButton = new System.Windows.Forms.Button();
this.AddToProjectButton = new System.Windows.Forms.Button();
this.NormalizeDirectionButton = new System.Windows.Forms.Button();
this.label17 = new System.Windows.Forms.Label();
this.DirectionTextBox = new System.Windows.Forms.TextBox();
this.ColourLabel = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.IntensityUpDown = new System.Windows.Forms.NumericUpDown();
this.label3 = new System.Windows.Forms.Label();
this.TypeComboBox = new System.Windows.Forms.ComboBox();
this.label4 = new System.Windows.Forms.Label();
this.FalloffTextBox = new System.Windows.Forms.TextBox();
this.label5 = new System.Windows.Forms.Label();
this.FalloffExponentTextBox = new System.Windows.Forms.TextBox();
this.label6 = new System.Windows.Forms.Label();
this.HashTextBox = new System.Windows.Forms.TextBox();
this.InnerAngleUpDown = new System.Windows.Forms.NumericUpDown();
this.label7 = new System.Windows.Forms.Label();
this.OuterAngleUpDown = new System.Windows.Forms.NumericUpDown();
this.label8 = new System.Windows.Forms.Label();
this.CoronaIntensityUpDown = new System.Windows.Forms.NumericUpDown();
this.label9 = new System.Windows.Forms.Label();
this.TimeFlagsAMCheckedListBox = new System.Windows.Forms.CheckedListBox();
this.TimeFlagsPMCheckedListBox = new System.Windows.Forms.CheckedListBox();
this.label10 = new System.Windows.Forms.Label();
this.TimeStateFlagsTextBox = new System.Windows.Forms.TextBox();
this.label11 = new System.Windows.Forms.Label();
this.StateFlags1CheckedListBox = new System.Windows.Forms.CheckedListBox();
this.label12 = new System.Windows.Forms.Label();
this.StateFlags2CheckedListBox = new System.Windows.Forms.CheckedListBox();
this.ColourRUpDown = new System.Windows.Forms.NumericUpDown();
this.ColourGUpDown = new System.Windows.Forms.NumericUpDown();
this.ColourBUpDown = new System.Windows.Forms.NumericUpDown();
((System.ComponentModel.ISupportInitialize)(this.IntensityUpDown)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.InnerAngleUpDown)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.OuterAngleUpDown)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.CoronaIntensityUpDown)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.ColourRUpDown)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.ColourGUpDown)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.ColourBUpDown)).BeginInit();
this.SuspendLayout();
//
// GoToButton
//
this.GoToButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.GoToButton.Location = new System.Drawing.Point(478, 6);
this.GoToButton.Name = "GoToButton";
this.GoToButton.Size = new System.Drawing.Size(68, 23);
this.GoToButton.TabIndex = 87;
this.GoToButton.Text = "Go to";
this.GoToButton.UseVisualStyleBackColor = true;
this.GoToButton.Click += new System.EventHandler(this.GoToButton_Click);
//
// PositionTextBox
//
this.PositionTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.PositionTextBox.Location = new System.Drawing.Point(82, 8);
this.PositionTextBox.Name = "PositionTextBox";
this.PositionTextBox.Size = new System.Drawing.Size(390, 20);
this.PositionTextBox.TabIndex = 86;
this.PositionTextBox.TextChanged += new System.EventHandler(this.PositionTextBox_TextChanged);
//
// label31
//
this.label31.AutoSize = true;
this.label31.Location = new System.Drawing.Point(4, 11);
this.label31.Name = "label31";
this.label31.Size = new System.Drawing.Size(47, 13);
this.label31.TabIndex = 85;
this.label31.Text = "Position:";
//
// DeleteButton
//
this.DeleteButton.Location = new System.Drawing.Point(129, 314);
this.DeleteButton.Name = "DeleteButton";
this.DeleteButton.Size = new System.Drawing.Size(95, 23);
this.DeleteButton.TabIndex = 107;
this.DeleteButton.Text = "Delete LodLight";
this.DeleteButton.UseVisualStyleBackColor = true;
this.DeleteButton.Click += new System.EventHandler(this.DeleteButton_Click);
//
// AddToProjectButton
//
this.AddToProjectButton.Location = new System.Drawing.Point(28, 314);
this.AddToProjectButton.Name = "AddToProjectButton";
this.AddToProjectButton.Size = new System.Drawing.Size(95, 23);
this.AddToProjectButton.TabIndex = 106;
this.AddToProjectButton.Text = "Add to Project";
this.AddToProjectButton.UseVisualStyleBackColor = true;
this.AddToProjectButton.Click += new System.EventHandler(this.AddToProjectButton_Click);
//
// NormalizeDirectionButton
//
this.NormalizeDirectionButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.NormalizeDirectionButton.Location = new System.Drawing.Point(478, 32);
this.NormalizeDirectionButton.Name = "NormalizeDirectionButton";
this.NormalizeDirectionButton.Size = new System.Drawing.Size(68, 23);
this.NormalizeDirectionButton.TabIndex = 110;
this.NormalizeDirectionButton.Text = "Normalize";
this.NormalizeDirectionButton.UseVisualStyleBackColor = true;
this.NormalizeDirectionButton.Click += new System.EventHandler(this.NormalizeDirectionButton_Click);
//
// label17
//
this.label17.AutoSize = true;
this.label17.Location = new System.Drawing.Point(4, 37);
this.label17.Name = "label17";
this.label17.Size = new System.Drawing.Size(52, 13);
this.label17.TabIndex = 108;
this.label17.Text = "Direction:";
//
// DirectionTextBox
//
this.DirectionTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.DirectionTextBox.Location = new System.Drawing.Point(82, 34);
this.DirectionTextBox.Name = "DirectionTextBox";
this.DirectionTextBox.Size = new System.Drawing.Size(390, 20);
this.DirectionTextBox.TabIndex = 109;
this.DirectionTextBox.TextChanged += new System.EventHandler(this.DirectionTextBox_TextChanged);
//
// ColourLabel
//
this.ColourLabel.BackColor = System.Drawing.Color.White;
this.ColourLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.ColourLabel.Location = new System.Drawing.Point(82, 113);
this.ColourLabel.Name = "ColourLabel";
this.ColourLabel.Size = new System.Drawing.Size(30, 21);
this.ColourLabel.TabIndex = 111;
this.ColourLabel.Click += new System.EventHandler(this.ColourLabel_Click);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(4, 63);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(34, 13);
this.label1.TabIndex = 112;
this.label1.Text = "Type:";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(4, 116);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(72, 13);
this.label2.TabIndex = 114;
this.label2.Text = "Colour (RGB):";
//
// IntensityUpDown
//
this.IntensityUpDown.Location = new System.Drawing.Point(82, 87);
this.IntensityUpDown.Maximum = new decimal(new int[] {
255,
0,
0,
0});
this.IntensityUpDown.Name = "IntensityUpDown";
this.IntensityUpDown.Size = new System.Drawing.Size(154, 20);
this.IntensityUpDown.TabIndex = 116;
this.IntensityUpDown.Value = new decimal(new int[] {
255,
0,
0,
0});
this.IntensityUpDown.ValueChanged += new System.EventHandler(this.IntensityUpDown_ValueChanged);
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(4, 89);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(49, 13);
this.label3.TabIndex = 115;
this.label3.Text = "Intensity:";
//
// TypeComboBox
//
this.TypeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.TypeComboBox.FormattingEnabled = true;
this.TypeComboBox.Items.AddRange(new object[] {
"Point",
"Spot",
"Capsule"});
this.TypeComboBox.Location = new System.Drawing.Point(82, 60);
this.TypeComboBox.Name = "TypeComboBox";
this.TypeComboBox.Size = new System.Drawing.Size(154, 21);
this.TypeComboBox.TabIndex = 118;
this.TypeComboBox.SelectedIndexChanged += new System.EventHandler(this.TypeComboBox_SelectedIndexChanged);
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(4, 144);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(38, 13);
this.label4.TabIndex = 119;
this.label4.Text = "Falloff:";
//
// FalloffTextBox
//
this.FalloffTextBox.Location = new System.Drawing.Point(82, 141);
this.FalloffTextBox.Name = "FalloffTextBox";
this.FalloffTextBox.Size = new System.Drawing.Size(154, 20);
this.FalloffTextBox.TabIndex = 120;
this.FalloffTextBox.TextChanged += new System.EventHandler(this.FalloffTextBox_TextChanged);
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(4, 170);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(58, 13);
this.label5.TabIndex = 121;
this.label5.Text = "Falloff exp:";
//
// FalloffExponentTextBox
//
this.FalloffExponentTextBox.Location = new System.Drawing.Point(82, 167);
this.FalloffExponentTextBox.Name = "FalloffExponentTextBox";
this.FalloffExponentTextBox.Size = new System.Drawing.Size(154, 20);
this.FalloffExponentTextBox.TabIndex = 122;
this.FalloffExponentTextBox.TextChanged += new System.EventHandler(this.FalloffExponentTextBox_TextChanged);
//
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(4, 196);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(35, 13);
this.label6.TabIndex = 123;
this.label6.Text = "Hash:";
//
// HashTextBox
//
this.HashTextBox.Location = new System.Drawing.Point(82, 193);
this.HashTextBox.Name = "HashTextBox";
this.HashTextBox.Size = new System.Drawing.Size(154, 20);
this.HashTextBox.TabIndex = 124;
this.HashTextBox.TextChanged += new System.EventHandler(this.HashTextBox_TextChanged);
//
// InnerAngleUpDown
//
this.InnerAngleUpDown.Location = new System.Drawing.Point(82, 219);
this.InnerAngleUpDown.Maximum = new decimal(new int[] {
255,
0,
0,
0});
this.InnerAngleUpDown.Name = "InnerAngleUpDown";
this.InnerAngleUpDown.Size = new System.Drawing.Size(154, 20);
this.InnerAngleUpDown.TabIndex = 126;
this.InnerAngleUpDown.Value = new decimal(new int[] {
255,
0,
0,
0});
this.InnerAngleUpDown.ValueChanged += new System.EventHandler(this.InnerAngleUpDown_ValueChanged);
//
// label7
//
this.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(4, 221);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(63, 13);
this.label7.TabIndex = 125;
this.label7.Text = "Inner angle:";
//
// OuterAngleUpDown
//
this.OuterAngleUpDown.Location = new System.Drawing.Point(82, 245);
this.OuterAngleUpDown.Maximum = new decimal(new int[] {
255,
0,
0,
0});
this.OuterAngleUpDown.Name = "OuterAngleUpDown";
this.OuterAngleUpDown.Size = new System.Drawing.Size(154, 20);
this.OuterAngleUpDown.TabIndex = 128;
this.OuterAngleUpDown.Value = new decimal(new int[] {
255,
0,
0,
0});
this.OuterAngleUpDown.ValueChanged += new System.EventHandler(this.OuterAngleUpDown_ValueChanged);
//
// label8
//
this.label8.AutoSize = true;
this.label8.Location = new System.Drawing.Point(4, 247);
this.label8.Name = "label8";
this.label8.Size = new System.Drawing.Size(65, 13);
this.label8.TabIndex = 127;
this.label8.Text = "Outer angle:";
//
// CoronaIntensityUpDown
//
this.CoronaIntensityUpDown.Location = new System.Drawing.Point(82, 271);
this.CoronaIntensityUpDown.Maximum = new decimal(new int[] {
255,
0,
0,
0});
this.CoronaIntensityUpDown.Name = "CoronaIntensityUpDown";
this.CoronaIntensityUpDown.Size = new System.Drawing.Size(154, 20);
this.CoronaIntensityUpDown.TabIndex = 130;
this.CoronaIntensityUpDown.Value = new decimal(new int[] {
255,
0,
0,
0});
this.CoronaIntensityUpDown.ValueChanged += new System.EventHandler(this.CoronaIntensityUpDown_ValueChanged);
//
// label9
//
this.label9.AutoSize = true;
this.label9.Location = new System.Drawing.Point(4, 273);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(44, 13);
this.label9.TabIndex = 129;
this.label9.Text = "Corona:";
//
// TimeFlagsAMCheckedListBox
//
this.TimeFlagsAMCheckedListBox.CheckOnClick = true;
this.TimeFlagsAMCheckedListBox.FormattingEnabled = true;
this.TimeFlagsAMCheckedListBox.Items.AddRange(new object[] {
"00:00 - 01:00",
"01:00 - 02:00",
"02:00 - 03:00",
"03:00 - 04:00",
"04:00 - 05:00",
"05:00 - 06:00",
"06:00 - 07:00",
"07:00 - 08:00",
"08:00 - 09:00",
"09:00 - 10:00",
"10:00 - 11:00",
"11:00 - 12:00"});
this.TimeFlagsAMCheckedListBox.Location = new System.Drawing.Point(350, 87);
this.TimeFlagsAMCheckedListBox.Name = "TimeFlagsAMCheckedListBox";
this.TimeFlagsAMCheckedListBox.Size = new System.Drawing.Size(95, 184);
this.TimeFlagsAMCheckedListBox.TabIndex = 131;
this.TimeFlagsAMCheckedListBox.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.TimeFlagsAMCheckedListBox_ItemCheck);
//
// TimeFlagsPMCheckedListBox
//
this.TimeFlagsPMCheckedListBox.CheckOnClick = true;
this.TimeFlagsPMCheckedListBox.FormattingEnabled = true;
this.TimeFlagsPMCheckedListBox.Items.AddRange(new object[] {
"12:00 - 13:00",
"13:00 - 14:00",
"14:00 - 15:00",
"15:00 - 16:00",
"16:00 - 17:00",
"17:00 - 18:00",
"18:00 - 19:00",
"19:00 - 20:00",
"20:00 - 21:00",
"21:00 - 22:00",
"22:00 - 23:00",
"23:00 - 00:00"});
this.TimeFlagsPMCheckedListBox.Location = new System.Drawing.Point(451, 87);
this.TimeFlagsPMCheckedListBox.Name = "TimeFlagsPMCheckedListBox";
this.TimeFlagsPMCheckedListBox.Size = new System.Drawing.Size(95, 184);
this.TimeFlagsPMCheckedListBox.TabIndex = 132;
this.TimeFlagsPMCheckedListBox.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.TimeFlagsPMCheckedListBox_ItemCheck);
//
// label10
//
this.label10.AutoSize = true;
this.label10.Location = new System.Drawing.Point(258, 63);
this.label10.Name = "label10";
this.label10.Size = new System.Drawing.Size(86, 13);
this.label10.TabIndex = 134;
this.label10.Text = "Time/state flags:";
//
// TimeStateFlagsTextBox
//
this.TimeStateFlagsTextBox.Location = new System.Drawing.Point(350, 60);
this.TimeStateFlagsTextBox.Name = "TimeStateFlagsTextBox";
this.TimeStateFlagsTextBox.Size = new System.Drawing.Size(196, 20);
this.TimeStateFlagsTextBox.TabIndex = 135;
this.TimeStateFlagsTextBox.TextChanged += new System.EventHandler(this.TimeStateFlagsTextBox_TextChanged);
//
// label11
//
this.label11.AutoSize = true;
this.label11.Location = new System.Drawing.Point(286, 89);
this.label11.Name = "label11";
this.label11.Size = new System.Drawing.Size(58, 13);
this.label11.TabIndex = 136;
this.label11.Text = "Time flags:";
//
// StateFlags1CheckedListBox
//
this.StateFlags1CheckedListBox.CheckOnClick = true;
this.StateFlags1CheckedListBox.FormattingEnabled = true;
this.StateFlags1CheckedListBox.Items.AddRange(new object[] {
"Street light",
"Unk2"});
this.StateFlags1CheckedListBox.Location = new System.Drawing.Point(350, 277);
this.StateFlags1CheckedListBox.Name = "StateFlags1CheckedListBox";
this.StateFlags1CheckedListBox.Size = new System.Drawing.Size(95, 34);
this.StateFlags1CheckedListBox.TabIndex = 137;
this.StateFlags1CheckedListBox.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.StateFlags1CheckedListBox_ItemCheck);
//
// label12
//
this.label12.AutoSize = true;
this.label12.Location = new System.Drawing.Point(284, 279);
this.label12.Name = "label12";
this.label12.Size = new System.Drawing.Size(60, 13);
this.label12.TabIndex = 138;
this.label12.Text = "State flags:";
//
// StateFlags2CheckedListBox
//
this.StateFlags2CheckedListBox.CheckOnClick = true;
this.StateFlags2CheckedListBox.FormattingEnabled = true;
this.StateFlags2CheckedListBox.Items.AddRange(new object[] {
"Unk3",
"Unk4",
"Unk5"});
this.StateFlags2CheckedListBox.Location = new System.Drawing.Point(451, 277);
this.StateFlags2CheckedListBox.Name = "StateFlags2CheckedListBox";
this.StateFlags2CheckedListBox.Size = new System.Drawing.Size(95, 49);
this.StateFlags2CheckedListBox.TabIndex = 139;
this.StateFlags2CheckedListBox.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.StateFlags2CheckedListBox_ItemCheck);
//
// ColourRUpDown
//
this.ColourRUpDown.Location = new System.Drawing.Point(116, 114);
this.ColourRUpDown.Maximum = new decimal(new int[] {
255,
0,
0,
0});
this.ColourRUpDown.Name = "ColourRUpDown";
this.ColourRUpDown.Size = new System.Drawing.Size(38, 20);
this.ColourRUpDown.TabIndex = 140;
this.ColourRUpDown.Value = new decimal(new int[] {
255,
0,
0,
0});
this.ColourRUpDown.ValueChanged += new System.EventHandler(this.ColourRUpDown_ValueChanged);
//
// ColourGUpDown
//
this.ColourGUpDown.Location = new System.Drawing.Point(157, 114);
this.ColourGUpDown.Maximum = new decimal(new int[] {
255,
0,
0,
0});
this.ColourGUpDown.Name = "ColourGUpDown";
this.ColourGUpDown.Size = new System.Drawing.Size(38, 20);
this.ColourGUpDown.TabIndex = 141;
this.ColourGUpDown.Value = new decimal(new int[] {
255,
0,
0,
0});
this.ColourGUpDown.ValueChanged += new System.EventHandler(this.ColourGUpDown_ValueChanged);
//
// ColourBUpDown
//
this.ColourBUpDown.Location = new System.Drawing.Point(198, 114);
this.ColourBUpDown.Maximum = new decimal(new int[] {
255,
0,
0,
0});
this.ColourBUpDown.Name = "ColourBUpDown";
this.ColourBUpDown.Size = new System.Drawing.Size(38, 20);
this.ColourBUpDown.TabIndex = 142;
this.ColourBUpDown.Value = new decimal(new int[] {
255,
0,
0,
0});
this.ColourBUpDown.ValueChanged += new System.EventHandler(this.ColourBUpDown_ValueChanged);
//
// EditYmapLodLightPanel
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(553, 407);
this.Controls.Add(this.ColourBUpDown);
this.Controls.Add(this.ColourGUpDown);
this.Controls.Add(this.ColourRUpDown);
this.Controls.Add(this.StateFlags2CheckedListBox);
this.Controls.Add(this.label12);
this.Controls.Add(this.StateFlags1CheckedListBox);
this.Controls.Add(this.label11);
this.Controls.Add(this.TimeStateFlagsTextBox);
this.Controls.Add(this.label10);
this.Controls.Add(this.TimeFlagsPMCheckedListBox);
this.Controls.Add(this.TimeFlagsAMCheckedListBox);
this.Controls.Add(this.CoronaIntensityUpDown);
this.Controls.Add(this.label9);
this.Controls.Add(this.OuterAngleUpDown);
this.Controls.Add(this.label8);
this.Controls.Add(this.InnerAngleUpDown);
this.Controls.Add(this.label7);
this.Controls.Add(this.label6);
this.Controls.Add(this.HashTextBox);
this.Controls.Add(this.label5);
this.Controls.Add(this.FalloffExponentTextBox);
this.Controls.Add(this.label4);
this.Controls.Add(this.FalloffTextBox);
this.Controls.Add(this.TypeComboBox);
this.Controls.Add(this.IntensityUpDown);
this.Controls.Add(this.label3);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Controls.Add(this.ColourLabel);
this.Controls.Add(this.NormalizeDirectionButton);
this.Controls.Add(this.label17);
this.Controls.Add(this.DirectionTextBox);
this.Controls.Add(this.DeleteButton);
this.Controls.Add(this.AddToProjectButton);
this.Controls.Add(this.GoToButton);
this.Controls.Add(this.PositionTextBox);
this.Controls.Add(this.label31);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "EditYmapLodLightPanel";
this.Text = "Lod Light";
((System.ComponentModel.ISupportInitialize)(this.IntensityUpDown)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.InnerAngleUpDown)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.OuterAngleUpDown)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.CoronaIntensityUpDown)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.ColourRUpDown)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.ColourGUpDown)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.ColourBUpDown)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button GoToButton;
private System.Windows.Forms.TextBox PositionTextBox;
private System.Windows.Forms.Label label31;
private System.Windows.Forms.Button DeleteButton;
private System.Windows.Forms.Button AddToProjectButton;
private System.Windows.Forms.Button NormalizeDirectionButton;
private System.Windows.Forms.Label label17;
private System.Windows.Forms.TextBox DirectionTextBox;
private System.Windows.Forms.Label ColourLabel;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.NumericUpDown IntensityUpDown;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.ComboBox TypeComboBox;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.TextBox FalloffTextBox;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.TextBox FalloffExponentTextBox;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.TextBox HashTextBox;
private System.Windows.Forms.NumericUpDown InnerAngleUpDown;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.NumericUpDown OuterAngleUpDown;
private System.Windows.Forms.Label label8;
private System.Windows.Forms.NumericUpDown CoronaIntensityUpDown;
private System.Windows.Forms.Label label9;
private System.Windows.Forms.CheckedListBox TimeFlagsAMCheckedListBox;
private System.Windows.Forms.CheckedListBox TimeFlagsPMCheckedListBox;
private System.Windows.Forms.Label label10;
private System.Windows.Forms.TextBox TimeStateFlagsTextBox;
private System.Windows.Forms.Label label11;
private System.Windows.Forms.CheckedListBox StateFlags1CheckedListBox;
private System.Windows.Forms.Label label12;
private System.Windows.Forms.CheckedListBox StateFlags2CheckedListBox;
private System.Windows.Forms.NumericUpDown ColourRUpDown;
private System.Windows.Forms.NumericUpDown ColourGUpDown;
private System.Windows.Forms.NumericUpDown ColourBUpDown;
}
}

View File

@ -0,0 +1,521 @@
using CodeWalker.GameFiles;
using SharpDX;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CodeWalker.Project.Panels
{
public partial class EditYmapLodLightPanel : ProjectPanel
{
public ProjectForm ProjectForm;
public YmapLODLight CurrentLodLight { get; set; }
private bool populatingui = false;
public EditYmapLodLightPanel(ProjectForm owner)
{
ProjectForm = owner;
InitializeComponent();
TypeComboBox.Items.Clear();
TypeComboBox.Items.Add(LightType.Point);
TypeComboBox.Items.Add(LightType.Spot);
TypeComboBox.Items.Add(LightType.Capsule);
}
public void SetLodLight(YmapLODLight lodlight)
{
CurrentLodLight = lodlight;
Tag = lodlight;
LoadLodLight();
UpdateFormTitle();
}
private void UpdateFormTitle()
{
Text = "LodLight: " + (CurrentLodLight?.Index.ToString() ?? "(none)");
}
private void LoadLodLight()
{
if (CurrentLodLight == null)
{
////Panel.Enabled = false;
AddToProjectButton.Enabled = false;
DeleteButton.Enabled = false;
PositionTextBox.Text = string.Empty;
DirectionTextBox.Text = string.Empty;
TypeComboBox.SelectedItem = LightType.Point;
IntensityUpDown.Value = 0;
ColourRUpDown.Value = 0;
ColourGUpDown.Value = 0;
ColourBUpDown.Value = 0;
ColourLabel.BackColor = System.Drawing.Color.White;
FalloffTextBox.Text = "";
FalloffExponentTextBox.Text = "";
HashTextBox.Text = "";
InnerAngleUpDown.Value = 0;
OuterAngleUpDown.Value = 0;
CoronaIntensityUpDown.Value = 0;
TimeStateFlagsTextBox.Text = "";
foreach (int i in TimeFlagsAMCheckedListBox.CheckedIndices)
{
TimeFlagsAMCheckedListBox.SetItemCheckState(i, CheckState.Unchecked);
}
foreach (int i in TimeFlagsPMCheckedListBox.CheckedIndices)
{
TimeFlagsPMCheckedListBox.SetItemCheckState(i, CheckState.Unchecked);
}
foreach (int i in StateFlags1CheckedListBox.CheckedIndices)
{
StateFlags1CheckedListBox.SetItemCheckState(i, CheckState.Unchecked);
}
foreach (int i in StateFlags2CheckedListBox.CheckedIndices)
{
StateFlags2CheckedListBox.SetItemCheckState(i, CheckState.Unchecked);
}
}
else
{
populatingui = true;
var l = CurrentLodLight;
////Panel.Enabled = true;
AddToProjectButton.Enabled = !ProjectForm.YmapExistsInProject(CurrentLodLight.Ymap);
DeleteButton.Enabled = !AddToProjectButton.Enabled;
PositionTextBox.Text = FloatUtil.GetVector3String(l.Position);
DirectionTextBox.Text = FloatUtil.GetVector3String(l.Direction);
TypeComboBox.SelectedItem = l.Type;
IntensityUpDown.Value = l.Colour.A;
ColourRUpDown.Value = l.Colour.R;
ColourGUpDown.Value = l.Colour.G;
ColourBUpDown.Value = l.Colour.B;
ColourLabel.BackColor = System.Drawing.Color.FromArgb(l.Colour.R, l.Colour.G, l.Colour.B);
FalloffTextBox.Text = FloatUtil.ToString(l.Falloff);
FalloffExponentTextBox.Text = FloatUtil.ToString(l.FalloffExponent);
HashTextBox.Text = l.Hash.ToString();
InnerAngleUpDown.Value = l.ConeInnerAngle;
OuterAngleUpDown.Value = l.ConeOuterAngleOrCapExt;
CoronaIntensityUpDown.Value = l.CoronaIntensity;
TimeStateFlagsTextBox.Text = l.TimeAndStateFlags.ToString();
UpdateFlagsCheckBoxes();
populatingui = false;
if (ProjectForm.WorldForm != null)
{
ProjectForm.WorldForm.SelectObject(CurrentLodLight);
}
}
}
private void UpdateFlagsCheckBoxes()
{
var l = CurrentLodLight;
var tfam = (l.TimeFlags >> 0) & 0xFFF;
var tfpm = (l.TimeFlags >> 12) & 0xFFF;
var sf1 = l.StateFlags1;
var sf2 = l.StateFlags2;
for (int i = 0; i < TimeFlagsAMCheckedListBox.Items.Count; i++)
{
TimeFlagsAMCheckedListBox.SetItemCheckState(i, ((tfam & (1u << i)) > 0) ? CheckState.Checked : CheckState.Unchecked);
}
for (int i = 0; i < TimeFlagsPMCheckedListBox.Items.Count; i++)
{
TimeFlagsPMCheckedListBox.SetItemCheckState(i, ((tfpm & (1u << i)) > 0) ? CheckState.Checked : CheckState.Unchecked);
}
for (int i = 0; i < StateFlags1CheckedListBox.Items.Count; i++)
{
StateFlags1CheckedListBox.SetItemCheckState(i, ((sf1 & (1u << i)) > 0) ? CheckState.Checked : CheckState.Unchecked);
}
for (int i = 0; i < StateFlags2CheckedListBox.Items.Count; i++)
{
StateFlags2CheckedListBox.SetItemCheckState(i, ((sf2 & (1u << i)) > 0) ? CheckState.Checked : CheckState.Unchecked);
}
}
private uint GetFlagsFromItemCheck(CheckedListBox clb, ItemCheckEventArgs e)
{
uint flags = 0;
for (int i = 0; i < clb.Items.Count; i++)
{
if ((e != null) && (e.Index == i))
{
if (e.NewValue == CheckState.Checked)
{
flags += (uint)(1 << i);
}
}
else
{
if (clb.GetItemChecked(i))
{
flags += (uint)(1 << i);
}
}
}
return flags;
}
private void ProjectItemChanged()
{
if (CurrentLodLight == null) return;
if (ProjectForm == null) return;
ProjectForm.SetProjectItem(CurrentLodLight);
ProjectForm.SetYmapHasChanged(true);
}
private void UpdateGraphics()
{
if (CurrentLodLight == null) return;
if (ProjectForm?.WorldForm == null) return;
ProjectForm.WorldForm.UpdateLodLightGraphics(CurrentLodLight);
}
private void UpdateColour()
{
if (populatingui) return;
var r = (byte)ColourRUpDown.Value;
var g = (byte)ColourGUpDown.Value;
var b = (byte)ColourBUpDown.Value;
var i = (byte)IntensityUpDown.Value;
ColourLabel.BackColor = System.Drawing.Color.FromArgb(r, g, b);
if (CurrentLodLight != null)
{
CurrentLodLight.SetColour(new SharpDX.Color(r, g, b, i));
UpdateGraphics();
ProjectItemChanged();
}
}
private void AddToProjectButton_Click(object sender, EventArgs e)
{
if (CurrentLodLight == null) return;
if (ProjectForm == null) return;
ProjectForm.SetProjectItem(CurrentLodLight);
ProjectForm.AddLodLightToProject();
}
private void DeleteButton_Click(object sender, EventArgs e)
{
ProjectForm.SetProjectItem(CurrentLodLight);
ProjectForm.DeleteLodLight();
}
private void GoToButton_Click(object sender, EventArgs e)
{
if (CurrentLodLight == null) return;
if (ProjectForm?.WorldForm == null) return;
ProjectForm.WorldForm.GoToPosition(CurrentLodLight.Position, Vector3.One * CurrentLodLight.Falloff * 2.0f);
}
private void NormalizeDirectionButton_Click(object sender, EventArgs e)
{
Vector3 d = Vector3.Normalize(FloatUtil.ParseVector3String(DirectionTextBox.Text));
DirectionTextBox.Text = FloatUtil.GetVector3String(d);
}
private void PositionTextBox_TextChanged(object sender, EventArgs e)
{
if (populatingui) return;
if (CurrentLodLight == null) return;
Vector3 v = FloatUtil.ParseVector3String(PositionTextBox.Text);
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentLodLight.Position != v)
{
CurrentLodLight.SetPosition(v);
ProjectItemChanged();
UpdateGraphics();
var wf = ProjectForm.WorldForm;
if (wf != null)
{
wf.BeginInvoke(new Action(() =>
{
wf.SetWidgetPosition(CurrentLodLight.Position, true);
}));
}
}
}
}
private void DirectionTextBox_TextChanged(object sender, EventArgs e)
{
if (populatingui) return;
if (CurrentLodLight == null) return;
Vector3 v = FloatUtil.ParseVector3String(DirectionTextBox.Text);
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentLodLight.Direction != v)
{
CurrentLodLight.Direction = v;
CurrentLodLight.UpdateTangentsAndOrientation();
ProjectItemChanged();
UpdateGraphics();
var wf = ProjectForm.WorldForm;
if (wf != null)
{
wf.BeginInvoke(new Action(() =>
{
wf.SetWidgetRotation(CurrentLodLight.Orientation, true);
}));
}
}
}
}
private void TypeComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
if (populatingui) return;
if (CurrentLodLight == null) return;
var t = (LightType)TypeComboBox.SelectedItem;
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentLodLight.Type != t)
{
CurrentLodLight.Type = t;
ProjectItemChanged();
UpdateGraphics();
}
}
populatingui = true;
TimeStateFlagsTextBox.Text = CurrentLodLight.TimeAndStateFlags.ToString();
populatingui = false;
}
private void IntensityUpDown_ValueChanged(object sender, EventArgs e)
{
UpdateColour();
}
private void ColourRUpDown_ValueChanged(object sender, EventArgs e)
{
UpdateColour();
}
private void ColourGUpDown_ValueChanged(object sender, EventArgs e)
{
UpdateColour();
}
private void ColourBUpDown_ValueChanged(object sender, EventArgs e)
{
UpdateColour();
}
private void ColourLabel_Click(object sender, EventArgs e)
{
var colDiag = new ColorDialog { Color = ColourLabel.BackColor };
if (colDiag.ShowDialog(this) == DialogResult.OK)
{
var c = colDiag.Color;
populatingui = true;
ColourRUpDown.Value = c.R;
ColourGUpDown.Value = c.G;
ColourBUpDown.Value = c.B;
populatingui = false;
UpdateColour();
}
}
private void FalloffTextBox_TextChanged(object sender, EventArgs e)
{
if (populatingui) return;
if (CurrentLodLight == null) return;
float v = FloatUtil.Parse(FalloffTextBox.Text);
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentLodLight.Falloff != v)
{
CurrentLodLight.Falloff = v;
ProjectItemChanged();
UpdateGraphics();
}
}
}
private void FalloffExponentTextBox_TextChanged(object sender, EventArgs e)
{
if (populatingui) return;
if (CurrentLodLight == null) return;
float v = FloatUtil.Parse(FalloffExponentTextBox.Text);
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentLodLight.FalloffExponent != v)
{
CurrentLodLight.FalloffExponent = v;
ProjectItemChanged();
UpdateGraphics();
}
}
}
private void HashTextBox_TextChanged(object sender, EventArgs e)
{
if (populatingui) return;
if (CurrentLodLight == null) return;
uint.TryParse(HashTextBox.Text, out uint v);
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentLodLight.Hash != v)
{
CurrentLodLight.Hash = v;
ProjectItemChanged();
}
}
}
private void InnerAngleUpDown_ValueChanged(object sender, EventArgs e)
{
if (populatingui) return;
if (CurrentLodLight == null) return;
byte v = (byte)InnerAngleUpDown.Value;
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentLodLight.ConeInnerAngle != v)
{
CurrentLodLight.ConeInnerAngle = v;
ProjectItemChanged();
UpdateGraphics();
}
}
}
private void OuterAngleUpDown_ValueChanged(object sender, EventArgs e)
{
if (populatingui) return;
if (CurrentLodLight == null) return;
byte v = (byte)OuterAngleUpDown.Value;
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentLodLight.ConeOuterAngleOrCapExt != v)
{
CurrentLodLight.ConeOuterAngleOrCapExt = v;
ProjectItemChanged();
UpdateGraphics();
}
}
}
private void CoronaIntensityUpDown_ValueChanged(object sender, EventArgs e)
{
if (populatingui) return;
if (CurrentLodLight == null) return;
byte v = (byte)CoronaIntensityUpDown.Value;
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentLodLight.CoronaIntensity != v)
{
CurrentLodLight.CoronaIntensity = v;
ProjectItemChanged();
}
}
}
private void TimeStateFlagsTextBox_TextChanged(object sender, EventArgs e)
{
if (populatingui) return;
if (CurrentLodLight == null) return;
uint.TryParse(TimeStateFlagsTextBox.Text, out uint v);
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentLodLight.TimeAndStateFlags != v)
{
CurrentLodLight.TimeAndStateFlags = v;
ProjectItemChanged();
}
}
populatingui = true;
UpdateFlagsCheckBoxes();
populatingui = false;
}
private void TimeFlagsAMCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e)
{
if (populatingui) return;
if (CurrentLodLight == null) return;
var tfam = GetFlagsFromItemCheck(TimeFlagsAMCheckedListBox, e);
var tfpm = GetFlagsFromItemCheck(TimeFlagsPMCheckedListBox, null);
var v = tfam + (tfpm << 12);
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentLodLight.TimeFlags != v)
{
CurrentLodLight.TimeFlags = v;
ProjectItemChanged();
}
}
populatingui = true;
TimeStateFlagsTextBox.Text = CurrentLodLight.TimeAndStateFlags.ToString();
populatingui = false;
}
private void TimeFlagsPMCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e)
{
if (populatingui) return;
if (CurrentLodLight == null) return;
var tfam = GetFlagsFromItemCheck(TimeFlagsAMCheckedListBox, null);
var tfpm = GetFlagsFromItemCheck(TimeFlagsPMCheckedListBox, e);
var v = tfam + (tfpm << 12);
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentLodLight.TimeFlags != v)
{
CurrentLodLight.TimeFlags = v;
ProjectItemChanged();
}
}
populatingui = true;
TimeStateFlagsTextBox.Text = CurrentLodLight.TimeAndStateFlags.ToString();
populatingui = false;
}
private void StateFlags1CheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e)
{
if (populatingui) return;
if (CurrentLodLight == null) return;
var v = GetFlagsFromItemCheck(StateFlags1CheckedListBox, e);
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentLodLight.StateFlags1 != v)
{
CurrentLodLight.StateFlags1 = v;
ProjectItemChanged();
}
}
populatingui = true;
TimeStateFlagsTextBox.Text = CurrentLodLight.TimeAndStateFlags.ToString();
populatingui = false;
}
private void StateFlags2CheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e)
{
if (populatingui) return;
if (CurrentLodLight == null) return;
var v = GetFlagsFromItemCheck(StateFlags2CheckedListBox, e);
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentLodLight.StateFlags2 != v)
{
CurrentLodLight.StateFlags2 = v;
ProjectItemChanged();
}
}
populatingui = true;
TimeStateFlagsTextBox.Text = CurrentLodLight.TimeAndStateFlags.ToString();
populatingui = false;
}
}
}

View File

@ -0,0 +1,409 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAMAICAAAAAAGACoDAAANgAAABAQAAAAABgAaAMAAN4MAABAQAAAAAAYACgyAABGEAAAKAAAACAA
AABAAAAAAQAYAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAP//////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////v8/u3v+Pn6//7+////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//7+/vX3/rzA3OHl9fz9////////////////////////////////////////////////////////////
//////////////////////////////////////////////////7//+zv+3Z6qcLI5Pr7////////////
////////////////////////////////////////////////////////////////////////////////
//////////////////7+/+br+15in6+33vf5//////////////////7+//7+////////////////////
//////////////////////////////3+//v8//v8//3+//////////////////////7+/+Ho+1dana20
4/b4//////////z9//P2/+Tp/ezw/vz9//////////////////////////////////////////7///X4
/9Pa+tPa+/H1//z9//////////////////7+/93k+SsscaSr3PX3//////7+//L1/7W98AcWgrvC8Pj6
//////////////////////////////////////////7+/+bs/xohiAEJdrvF9+7y//z9////////////
//7+/9rh+CEkapmh0/T3//////j6/9HZ/AEHcgEEb9LZ+/r7////////////////////////////////
//////////7//+/z/3F+zAAAXwQLcZai3fb4//////////////3+/97l/E9Tmaau4fT3/////+/0/1dd
sAAAV7a/8/H1//7+//////////////////////////////////////////////r8/+jv/46Y3QUUf6Ot
5PX4//////////////3+/9zj+3Z6wLe/7fX4//////D0/212xnaAzerw//z9////////////////////
//////////////////////////////////v8/+/z/+Dm+/D0//z9//////////7+//j6/9Pd+UhLjb/H
9/D0//3+//n7/+nt/+jt//n7////////////////////////////////////////////////////////
//7///7+//7+//7+//////////r8/+7z/83W+ImU2A0UdFNarr/K9env//X4//z9//3+//7/////////
//////////////////////////////////////////////////////////////////7///j6/+Pq/255
xhckjE5XsVVftUlTqwAKeTA9nr3H8+7z//v8////////////////////////////////////////////
//////////////////////////////7+//b4/9Tc+Sc0mRonj8rV/crX/ZSb48rX/brG8wwWgQAEdJei
4efu//n7//7+//z9//z9//z9//z9//3+//////////////////////////////3+//f5/+3y/+nv/+ft
/8vV+io2mImU2M7c/7vG9yIvlQAOfCg4mM3Y/s/c/4aR1AQRfGtzwtni/ebt/9vi/tri/tXd+9Tc+O3x
/vz9//////////////////////////n6/87V+FVftkRPrFlnvSEqjQoUfmJvwWFvvg0TfQQIcxEchwAD
cy89n19rvVVitQwZgwAAaiMrkT9NqTVBoiw3mhQihig1mNLX+fv8//////////////////////////b5
/52l4EFLqoCK03yF0VBctGhyw52o5GVrvQAAaneBzsHM+jA3mhYgiTtIpJOf3ouW2AAAbmh0wbbA8bS+
7qiz5pCb16+56e/z//3+//////////////////////////v8//H1/+vw/+zx/+nv/7/J9YqP3MbP/8LM
+hwqkFZftaCp5EhRrcTQ+9jj/8rW/UJMqn6J0ebt//X3//f5//b4//X3//f5//z9////////////////
//////////7+//z9//3+//////////3+/+7z/6at64iP3aWs7XN8zRIfhyUykp2o5MHM+oKM0xonjY6X
2+jv//v8//////7+//n7//b5//r7//7///////////////////7+//f5/+rw/9Pa9fL0/v7/////////
//v8//H1/+Tr/7i/91liu0NPq0VQrS06m0NNqDdCoYqU1+nv//v8//////////n7/9zi/qSt59ri/fL1
//v8//7///////z9//D0/8rT+h0sjkVQrPD0//////////////////////z9/+7z/8LL9Jqk4aGq6LW/
8c3W9+Xs/vH1//v8//////////////f5/6at5gAAbxIfh6u16+Po/fr7//////b5/6ev5gAIeAAPernC
8fX4//////////3+//v8//z9//////3+//j6//P3//P2//b4//r8//7+//7+//v8//r8//3+//////v8
/+Xr/nuIzwAAbBseg5Sb2fb5//////f5/8DF8pWe3d/n/vT3//39//////v8/+zx/87V9+3x/v3+////
//3+//j6//X4//v8//////////n7/+Dm/snR9fD0//39//z8/fv8/+3y/8LK9aGq4dfd9/n7//////z9
//b5//X4//v8//////////7+/+7z/4aP1gEPet7k/f39//////f5/83U+ZCZ2u3x/v7+//////P3/215
wgAJd7fB8/L1//7+//////3+//j6//f5//r8//7+//////////////////////////////j6/87W/AAA
X2duue3y//7+//////D0/05asBQfidzj/P39//////X4/6Su6AAAXBccgtff/vv8////////////////
//////////////////////////////////////P3/3F8xhYli9Xe/fn6/////////+3y/1pltQAJd9be
/fv8//////z9/+rw/36I0Bknjs/W+vv8////////////////////////////////////////////////
//////f5/8HI7tnf+/X4//7+/////////+/0/3R7xgAAb9ng/Pz9//////////n7/+Ln/dLY+fP2//3+
//////////////////////////////////////////////////////3+//r7//v8//7+////////////
//b4/7/F84eP0e/0//7+//////////7+//z9//v8//3+////////////////////////////////////
//////////////////////////////////////////////////z9//b5//X4//v8////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////w////4
P///+D////g8//D4MH/geCB/4Dggf+A4IH/wOCD/+DAB//hgAf//gAP//wAAB/AAAAPwAAAD8AAAA/AA
AAfjAAEHgYADAQPgBwEDEAEBAghgAQwIIEH8CCB//Bggf/wYMH/8ODD///h/////////////KAAAABAA
AAAgAAAAAQAYAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///+vv/fL1/v///wAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///4+Vx7/F5v///wAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAP///4CHtrS62////////////////////wAAAAAAAAAAAP////H0/vf6/v//
/////////4yTwrrB4f///+zw+7rA6P39/////wAAAAAAAAAAAP///56l2BkcguXr/P///////42Uw8jO
6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f//
/wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA
AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc
skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU
0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq
+ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz
/eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR
p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm
+P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB
AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA
AAAAAAAA////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////v7//f7//P3//P3//P3/
/f7//v7/////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////v7//P3/
+fv/+fv/+Pr/+fv/+vv//P3//v//////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////+vv/8vb/2+P9X2OmREGLnqPd
4+v/8vb/+/z/////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////+vv/8fb/
1N35bXK1JSRtbHGz5O7/8fX/+/z/////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////+vv/8fb/2OL+NjZ7AAArX2Ok
4uz/8fX/+/z/////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////+vv/8fb/
2eP/LjJ1DAxKfYTE4Or/8fX/+/z//////////////////////////////v7//v7//f7//f7//v7//v//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////+vv/8PX/3OX/gILIR0eVeoHC3eb/8fX/+/z//////////////////////v7//P3/+fv/+Pr/
+Pr/+Pr/+vv//P3//v7/////////////////////////////////////////////////////////////
/////////////////////////////v7//f7//P3/+vv/+vv/+/z//f3//v7/////////////////////
////////////////////////+vv/8PX/2eP9ZWeqHx1obnOz4Or/8fX/+/z//////////////////v7/
+/z/9fj/8vb/8PX/7vT/8fb/9fj/+fr//f7/////////////////////////////////////////////
/////////////////////////////////////////v///P3/+Pr/9fj/9fj/9Pj/9Pf/9vn/+/z//v7/
////////////////////////////////////////+vv/8fb/2eP9ODp9AAA5jZDQ5O7/8PX/+/z/////
/////////v7/+/z/9Pf/7fP/5u//wsz6j5XfuMDx7fL/9vn//P3/////////////////////////////
/////////////////////////////////////////////////////////f7/+Pr/8/b/5+3/2eH/2uP/
5u3/7fP/8/b/+vv//f7/////////////////////////////////////+vv/8PX/3ef/U1ebBgVKio/O
4uz/8fX/+/z//////////v///P3/9fj/7fP/4uv/hIzZHSWPAABmU1i14ub/9/r/+/z/////////////
/////////////////////////////////////////////////////////////////////////P3/9Pf/
7/X/09z/TlSzNzWYj5bh5O7/6/L/8vb/+fv//f7/////////////////////////////////+vv/8fX/
2eP/QUWIEhBZbnSz3uj/8fb/+/z//////////f7/+Pr/7/T/6PH/iI7cAABvAABqAABncXjK6O//9fj/
+/z/////////////////////////////////////////////////////////////////////////////
////////+/z/8/f/2uD/Z27EAABnAABiBgl4jJTd5vD/6O//8vX/+fv//f7/////////////////////
////////+vv/8fb/2OP/Mjd6AQE6ZGup4er/8fX/+/z/////////+vz/8fX/6/T/xM/8ExyJAABwAABu
GySRxc387fT/9ff//P3/////////////////////////////////////////////////////////////
////////////////////////+vz/8/f/1Nr/MzqhAABhAxOBAARyBgp5jpLg5Oz/7PP/9Pf/+vz//v7/
////////////////////////+vv/8fb/2eP/KCtvBwZOjJHS4Or/8fX/+/z//////f7/9/n/7fP/3+j/
UFq3AABtAAZ3BAh6mZ/n5vD/7vP/+Pr//v7/////////////////////////////////////////////
////////////////////////////////////////+/z/9Pj/6e//sbb1KzWcAABwBhaBAAFyAgp6fITR
1d777/T/+Pr//f7/////////////////////////+vv/8PX/3+j/WF2hBglTnaTj5O3/8PX/+/z/////
/P3/9Pf/6vL/k5riAAByAAR0AABrY2vE4ur/6vH/9ff//P3/////////////////////////////////
/////////////////////////////////////////////////////////f3/9/n/7fL/5O3/ytX/RU6w
AABpAA5+AABuAABnhord6e7/+fv//f7/////////////////////////+vv/7/T/3+j/k5jbT1KdgYjJ
3uf+8fX/+/z/////+/z/9fn/4ef/NDqhAABnAABrJjCU0Nn/5/D/8fX/+vv//v7/////////////////
/////////////////////////////////////////////////////////////////////////v7/+/z/
9vn/7vP/6vP/ztb/O0CmAABpAABrQkuoxMn57PH/+Pr//f7/////////////////////////+vv/8PX/
2+X/en/CUFGak5nY3+j/8fX//P3//////P3/9fj/4en/i5DbNT2hIyuTpqzv4uz/7vP/9/n//f7/////
////////////////////////////////////////////////////////////////////////////////
/////////////v7//P3/9vn/7/P/6vL/ytH/X2i9XWi7wsf/6e//8/f/+Pr//v7/////////////////
////////+vv/8PX/3OX/WF2hW1ylvMD+3uf/8PX/+/z//////f7/9vn/7fP/4uj/j5Pgf4LV3+X/6fD/
9Pf//P3/////////////////////////////////////////////////////////////////////////
/////////////////////////////////v///P3/+Pr/8vX/7fP/5+//5u7/6vD/8PT/9vn//P3//v7/
/////////////////////f7/9/n/7fP/0tz9LDJzNjh/nqTk2uT/7fL/9/n//f7//f7/+fv/8/b/7PL/
3eX/zM//5ev/9fj/+fv//v7/////////////////////////////////////////////////////////
/////////////////////////////////////////////////////v///f3/+vv/9/n/9vn/9fj/9vn/
+fr//P3//v7//////////////v///f7/+vv/9vn/7/T/5vD/2Ob/VFubERNdoajk4u//5O7/7vP/9vj/
+fr/+vv/+Pr/9fj/9Pj/9fj/9fj/+Pr//P3/////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////v///v7/
/f7//P3//P3//f3//v7//v///////////////f7/+vz/9vn/8fX/7vT/5O3/3eb/z9n/cHjICxN5d37L
z9n/2eP/5O3/6/L/8PT/9Pf/9/n/+vv/+vv/+/z//P3//f3//v7/////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////P3/+Pr/8/b/7vT/6vL/z9r+jZjeQUeq
IiuQCBN3AAFrBRB8Nj2iUViym6XlydH/4+z/6/L/8PT/9/n/+/z//f7//v//////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////f3/9/n/8fX/6/L/3uf/
mKTkLzibAABoAAB0Fx+HDBh7FSGDAg16AABYAABlCBB/Ji2UhYza1+D/6PL/7fL/9Pf/+vv//f7/////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////v7//P3/9/n/
8PT/7PT/z9j/XmO+AABtAABcMDSXoajsu8X7VV+5hYzblZ/fTVSxFSKMAABkAABnAAN2Qkmpsbrz5e3/
6vH/8fX/+Pr//P3//v//////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////P3/9/n/8PX/7PT/vcn3LTOZAABaAgR1ZWzD0Nf/5vL/1OP/l53lzs3/6fP/4+7/sLzwZ23CBxSD
AABnAABlHiaSmqHo3+j/5+//7/T/9vn//P3//v7/////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////v7/
/v7//v7//v7//f7/+/z/9vj/7vP/7PX/tcLzEBeGAABkPEWlqLPt2eX/4e7/3On/uMX1gofVe3vPhYzY
z93+5/X/4e3/lJ3gHiOPAABtAABqChiEbHLIytD/5/D/7PL/8/f/+Pr/+fr/+Pr/+Pr/+Pr/+Pr/+Pr/
+Pr/+fv/+vv/+/z//f7//v7/////////////////////////////////////////////////////////
/v7//f7/+/z/+fv/9/n/9vj/9fj/9Pf/8fX/7PL/4uv/l6HgDhF7AAN4iZDe0d7/3uz/4vD/w83/VVm3
ICiSAAFyAABlAABwaHTD1N//2un/3er/w838ZW3BEyOJJzKVAQ16NDmfwsn75fD/5u7/7PL/7vP/7fP/
7fP/7fL/7fP/7vP/7/T/8fb/9Pj/9vn/+fr//f3//v//////////////////////////////////////
/////////////v7//P3/+Pr/9Pf/8fX/7vT/7PL/6/L/6fH/5u7/6vX/tsD0CQx4AAFwkZvi7ff/4vD/
4fD/z9j/OkGlAABiAABwBxWAAAt7BBN+P0uofYLUztb/4O7/6fb/6fP/qa7xQkyoBg56AABqMjugx8/+
5fH/4Ov/4On/3uj/3eb/3+j/3uj/1+L/0d3/1d7/3+f/7fL/9vj/+vz//v7/////////////////////
/////////////////////////////f7/+fr/8/f/6/L/2d//v8j6vcf5ucP1wMv8wM3+vMj6PkqoAABo
UF25usP7tsPyvsr6sLrwQ0utAABqAAV1OUameIDRKDWZAAd2GyeOLDecmaHntsL0pbLom6riq7LzUlu0
AANzBhR/AAZ0NT+ja3bBY2i/XGG6UViyWl65XGG7XGC6TVWvQU6pPkalODygqK7p8vb/+vz//v7/////
/////////////////////////////////////////////P3/9/n/7/T/wcj2R0ysExeFERmGDxuIFB6K
FBqICxSEAABsAAByDBiDCRSBBRCADhaFCRODAAh4AxF/AAl4CxeDHSaPAAp6AAN0AA19AAd3CBOBEBqH
BhGBAAh5AABwAAByAAh5BhSCAxWCAABsAABvAABlAABnAABxAABjAABmAABhAABdAABYAABhCAt/q7Lr
8/f/+vv//v7//////////////////////////////////////////////////P3/+fv/3uT/SE2vAABn
CBB/GiCMLzmfLTWcGByJFRyKGCOOMj2gHymRDxiGGyOPLDCXBRF/AAh3BhaCEyKMICqTKC2WNDqfIzCV
Awx6Eh+JHiaPAAR3AAZ5CxSDICWQX2q7Q1CqAA1+AAFxDxuHiZTbVGC4dHnQnabrTVqzY23EUV62Slau
LjaZXWm9sLjz5ez/9vn/+fv//v7//////////////////////////////////////////////////P3/
+Pv/4+n+e4LPfoPVpqv2vsf/zNX/zdb/xtH/v8v8pK7spKfysLb3vcr4ws784ej/hI/YAAZ1AAJzVF25
yM//3Of/5+//i5LcAABpMzyfp6vxoKznlqHhqbbtx9H/8fz/kpvfAABiAABph4zc5PD/2OP/193/3un/
1+D/2OH/1+D/0Nr/zNL/3+j/6/L/7/T/9vn//P3//v//////////////////////////////////////
/////////////f7/+Pr/9Pf/6vD/5u3/3+b/4uv/6PD/5+//5O3/5/P/sL3sXmS7mZzoz9f/3+z/4e//
mKLiEiKKCBF/KTWZr7T06/f/3ev/VF2zChSBipPcz9v+4u7/3ur/3ev/5/X/qrPrISmSDRJ2Xmq/3ur/
4uv/6vH/7fP/7fL/7/T/7vP/7fP/7fP/8PX/8fX/9Pf/+Pr/+/z//v7/////////////////////////
/////////////////////////////v7//P3/+Pr/9vn/9Pf/8vb/8vb/8/b/9Pf/7/T/6/L/tL/ubXLH
en/Ti43gqavy0t3/nafjMj6fJzaaAAV1GyeOYmW7Nz6fAABgNj6i1N//3uz/2uX/3Oj/5PH/wcj7FR2J
AAN0gong0tr/6fH/7/P/9vj/+Pr/+fv/+fv/+Pr/+Pr/+Pr/+fv/+vv//P3//f7//v//////////////
/////////////////////////////////////////////////v7//f7//P3/+/z/+/z/+/z//f3//f7/
+fv/8fX/5Oz/jpbfc3jObnXLcXfOk5rks7b4iY3dR1KvDhuEAABoAABlEBV9U12ytcD13Or/3en/3ej/
1eL/q7fvGR+MKDKZbnnNxc/76PD/8fX/+fr//f7//v///////v7//f7//f3//P3//f3//f7//v//////
/////////////////////////////////////////////////////v7//f7//P3//P3//f7//v7/////
/////////////////f7/9vn/7/T/yNH5lJrleoDVmZ3pmpzpc3nPfoTWf4bYVFy3HSaLZ3PGsrb8v8r8
y9n9q7jre4LRf4fUgIvXAwZ1AABrhYjb0NX/6PH/8PX/+Pr//f7//////////v///f3/+vv/+Pr/9/r/
9/n/+Pr/+/z//f7//v7//////////////////////////////////////v///f7/+/z/+fr/9vj/9/n/
+vz/+vv/+/z//v7//////////////////v7/+vz/8/f/7PL/2uT/t8H1srP6vcH+nKTnSlOxV2C7TVaz
WGS8QUqmSlSuSFOtR1GtbXTKVl23ARB5AAh2AABnd33P3eP/4ur/7/T/9/n//P3//////////////P3/
9/n/8vb/7PH/6fD/7PL/7vP/8vb/9vn/+/z//f7//////////////////////////////v7/+/z/+Pr/
8/b/7/T/8Pb/6vH/3eP97vL++fr//P3//////////////////////f7/+vv/9fj/7/T/5+//z9f+t7v4
uLn9Z2zFLzucFCGIMz6gGCCMAAd4AAl2Dx2EER+GXWK8c3XLKzKXd4LP4er/6/L/8PX/9/n//P3//v//
/////////v7/+fv/8/b/7PP/y9H/i4/erLbt4er/5e3/7fP/8/b/+fv//f3//v7/////////////////
/v7/+/z/9vj/8PT/6/L/3+n/x9H9aHTAZGvG3+b9+Pr/+/z//////////////////////////v7/+/z/
+Pr/8vb/6/H/3OX+wMn4maDmdHrPWGG6T1a1eoHWcHfOTlayUlq1SlKubHjAxMj/0dn/4+v/7PL/8vb/
+Pr//P3//v7//////////////f7/+fr/7vP/xsv5YGXAHymRKjKYYWS9rbLz4u3/6/P/8vb/+fr//f7/
/////////////v//+/z/9vj/7fL/5e3/xs7/Y23BIiiSAABeLTab3+b/9/r/+/z/////////////////
/////////////////f7/+vz/9vj/8PX/6vH/3eb/ydL8xM/6uMPyt733w8j/zNb/1Nz/3OT/4uz/5u7/
7fP/8vb/9vj/+vz//f7//////////////////////f7/+fv/7vP/jpHiAAJ1CxaBER6GAABoFRmGbXbH
0Nf/7PL/9fj//P3//////////////v7/+fv/8/f/4Of/hYvbKDGZAABuAABdAAZyi5La5+7/9vn/+/z/
/////////////////////////////////////v7//P3/+fv/9ff/8vb/7/X/7fP/6/L/5u3/5ez/6fD/
7PP/7/T/8fX/9Pf/9/n/+vv//P3//v7//v///////////////////////v7/+fv/8fb/2eH9fIbQExqH
AABrAAp6AAFyAABwS0+uztX39vn/+vz//////////////f7/+Pr/8ff/qbLpAABrAABhAABwDBWAfobX
5e3/8PX/9vn//f3//////////v///f7/+/z/+vv/+vv/+vz//P3//v7//v///v7//P3/+vz/+Pr/9/n/
9vj/9vj/9vj/9vj/9/n/+fr/+/z//P3//f7//v7//f7//P3/+/z/+vz/+/z//P3//v7//////v7/+/z/
9fj/7/T/5/H/uML1U1e1AAh5AABuAABvMjmdv8bz9vr/+vv//////////////f7/+fv/7/T/iY7aDxSA
GiONa3XHsr7w4Oj/6/H/9Pf/+vz//v7//////v///P3/+Pr/9Pf/8/f/9fj/9fj/9vn/+/z//v7/////
/////////v7//f7//P3/+/z/+/z//P3//f7//v///////////////v7/+/z/9/n/9vn/9vn/9Pj/9vn/
+/z//v7//////f7/+vz/9fj/7/T/6vL/3ef/i5PbGRqJBQl5jJbZ6vH/9Pj/+/z//////////////f7/
+fv/8fT/1Nn9t7/0wcr54er/7fT/8fX/9fj/+vv//f7//////////f3/+Pr/8PT/6/L/3uX/ztb/5Or/
8/f/+Pr//f7//////////////f7/+vz/+Pr/+fv/+fv/+vv//f3//v///////////////P3/9/n/7vL/
193/ztf/5u3/7vP/9Pf/+/z//v7//////v7//P3/+Pr/8fX/7PP/5/D/sLfxoKnk4+r/8vf/9/n//f3/
/////////////v7/+/z/9vn/9Pf/8vb/8fb/8fX/9Pf/+Pr//P3//v7//////////v7/+vv/8vb/5+7/
y9H/WWO9KSmSkZXj6vD/+Pv//P3//////////f7/+Pr/9fj/8vb/6O7/7vP/9fj/+Pr//f7/////////
/v//+vv/8vb/7PP/hYraKiqKlp7i6PD/7fP/9ff/+/z//v7//////////f7/+vv/9ff/8fX/8PX/8vb/
8/f/9vn/+/z//v7//////////////////f7/+/z/+vv/+fr/+fr/+vv//P3//v7/////////////////
/P3/9fj/7PL/1d7/RUysAABhAABlg4ja6/D/+Pr//P3/////////+/z/9fj/6e7/2eD/h4/bnaXg7PH/
9fj/+/z//////////v7/+Pr/8PX/y9X1JDGVAABaERWDoKnp6PH/7vP/9/n//P3//////////////v7/
/P3/+vv/+fv/+fv/+vv//P3//v7//////////////////////////v7//v7//v7//v7//v//////////
/////////////v7/+fv/8PX/7PX/ipPdAABsAABlQ1Cp3Ob/7vP/9/n//f7/////////+fv/9Pj/yNH5
Ule2DBJ8Ljie0df+8fb/+fv//v7//////v7/+Pr/7/X/hY3YAABxAAl7AABuEBaEs7nz6fH/8fX/+vv/
/v7//////////////////v///v7//v7//v7/////////////////////////////////////////////
/////////////////////////////f3/9vn/7PL/0tn/LzidAQFsAAB0iZHb6vP/8PT/+fv//v//////
/v7/+Pr/8vf/r7rqAAV4AABdPUen1N//7PL/9vn//f7//////v7/+fr/7/T/yc75S1G0AABrARKAAABp
Qker0df/7fP/9/n//f7/////////////////////////////////////////////////////////////
/////////////////////////////////////////////P3/9/n/5+7/cXXNAAd2AABuMDebzdT97PL/
9vj//P3//////////v7/9/n/7/X/tL/uFCCLAABqHSqRvcf46fD/9Pf//f3/////////+vv/8vX/6vH/
yM3+JC2XAABtAAV2Agx9q7Ly7vT/9vn//f7/////////////////////////////////////////////
/////////////////////////////////////////////////////////////P3/9/r/4uj/WWO1AAVx
KTaYu8T07fT/8vb/+vv//v7//////////v7/9/n/7vX/vsn1Iy2SAABrAQ99mp/o6PD/9Pf//P3/////
/////P3/9/n/7vP/6fL/s7z2DBB/AABeQ0uttrr56e7/+Pr//f7/////////////////////////////
/////////////////////////////////////////////////////////////////////////////P3/
+fv/4ef6g4zNbXfFw8v27fT/8vb/+Pr//f3//////////////v7/9/n/7vT/yNL7MjucAABtBxF/nKLo
6fH/9Pf//P3//////////v7/+/z/9fj/7fL/6/T/jZXbLzScrrP14en/7fL/+fv//v7/////////////
////////////////////////////////////////////////////////////////////////////////
/////////////f7/+vz/8PP91dr34+f/8vb/8/f/9/r//P3//v///////////////v7/+Pr/8PX/1N3/
QUqmAQRxBQ98m6Dm7PL/9fj//P3//////////////v7/+/z/9ff/8PX/5ez/ytH94ej/8vb/9vj/+/z/
/v7/////////////////////////////////////////////////////////////////////////////
/////////////////////////////v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//////////////////
/v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7//////////////////v7/+/z/9/n/9fj/9vn/
9fj/9vj/+vz//f7/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////v7//f7//f3//f3//f3//v7//v//////
////////////////////+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/////////////////////
/v7//f7/+/z/+/z/+/z//P3//v7/////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////v7//P3/+fv/+fv/+vv/+Pr/+vv/
/P3//v7/////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////v7//f7/
/f3//P3//f7//v7//v//////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB///////
//AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA
H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A
A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA
////+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A
AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf
AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4
AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A//
///////gD/////////Af//////////////8=
</value>
</data>
</root>

View File

@ -255,6 +255,19 @@ namespace CodeWalker.Project.Panels
ccgnode.Tag = cargen; ccgnode.Tag = cargen;
} }
} }
if ((ymap.LODLights?.LodLights != null) && (ymap.LODLights.LodLights.Length > 0))
{
var lodlightsnode = node.Nodes.Add("LOD Lights (" + ymap.LODLights.LodLights.Length.ToString() + ")");
lodlightsnode.Name = "LodLights";
lodlightsnode.Tag = ymap;
var lodlights = ymap.LODLights.LodLights;
for (int i = 0; i < lodlights.Length; i++)
{
var lodlight = lodlights[i];
var llnode = lodlightsnode.Nodes.Add(lodlight.ToString());
llnode.Tag = lodlight;
}
}
if ((ymap.GrassInstanceBatches != null) && (ymap.GrassInstanceBatches.Length > 0)) if ((ymap.GrassInstanceBatches != null) && (ymap.GrassInstanceBatches.Length > 0))
{ {
var grassbatchesnodes = node.Nodes.Add("Grass Batches (" + ymap.GrassInstanceBatches.Length.ToString() + ")"); var grassbatchesnodes = node.Nodes.Add("Grass Batches (" + ymap.GrassInstanceBatches.Length.ToString() + ")");
@ -1013,6 +1026,20 @@ namespace CodeWalker.Project.Panels
} }
return null; return null;
} }
public TreeNode FindLodLightTreeNode(YmapLODLight lodlight)
{
if (lodlight == null) return null;
TreeNode ymapnode = FindYmapTreeNode(lodlight.Ymap);
if (ymapnode == null) return null;
var lodlightsnode = GetChildTreeNode(ymapnode, "LodLights");
if (lodlightsnode == null) return null;
for (int i = 0; i < lodlightsnode.Nodes.Count; i++)
{
TreeNode lodlightnode = lodlightsnode.Nodes[i];
if (lodlightnode.Tag == lodlight) return lodlightnode;
}
return null;
}
public TreeNode FindGrassTreeNode(YmapGrassInstanceBatch batch) public TreeNode FindGrassTreeNode(YmapGrassInstanceBatch batch)
{ {
if (batch == null) return null; if (batch == null) return null;
@ -1432,6 +1459,21 @@ namespace CodeWalker.Project.Panels
{ {
ProjectTreeView.SelectedNode = null; ProjectTreeView.SelectedNode = null;
} }
public void TrySelectYmapTreeNode(YmapFile ymap)
{
TreeNode ymapnode = FindYmapTreeNode(ymap);
if (ymapnode != null)
{
if (ProjectTreeView.SelectedNode == ymapnode)
{
OnItemSelected?.Invoke(ymap);
}
else
{
ProjectTreeView.SelectedNode = ymapnode;
}
}
}
public void TrySelectEntityTreeNode(YmapEntityDef ent) public void TrySelectEntityTreeNode(YmapEntityDef ent)
{ {
TreeNode entnode = FindEntityTreeNode(ent); TreeNode entnode = FindEntityTreeNode(ent);
@ -1462,6 +1504,21 @@ namespace CodeWalker.Project.Panels
} }
} }
} }
public void TrySelectLodLightTreeNode(YmapLODLight lodlight)
{
TreeNode lodlightnode = FindLodLightTreeNode(lodlight);
if (lodlightnode != null)
{
if (ProjectTreeView.SelectedNode == lodlightnode)
{
OnItemSelected?.Invoke(lodlight);
}
else
{
ProjectTreeView.SelectedNode = lodlightnode;
}
}
}
public void TrySelectGrassBatchTreeNode(YmapGrassInstanceBatch grassBatch) public void TrySelectGrassBatchTreeNode(YmapGrassInstanceBatch grassBatch)
{ {
TreeNode grassNode = FindGrassTreeNode(grassBatch); TreeNode grassNode = FindGrassTreeNode(grassBatch);
@ -1959,6 +2016,14 @@ namespace CodeWalker.Project.Panels
tn.Text = cargen.ToString(); tn.Text = cargen.ToString();
} }
} }
public void UpdateLodLightTreeNode(YmapLODLight lodlight)
{
var tn = FindLodLightTreeNode(lodlight);
if (tn != null)
{
tn.Text = lodlight.ToString();
}
}
public void UpdatePathNodeTreeNode(YndNode node) public void UpdatePathNodeTreeNode(YndNode node)
{ {
var tn = FindPathNodeTreeNode(node); var tn = FindPathNodeTreeNode(node);
@ -2059,6 +2124,25 @@ namespace CodeWalker.Project.Panels
tn.Parent.Nodes.Remove(tn); tn.Parent.Nodes.Remove(tn);
} }
} }
public void RemoveLodLightTreeNode(YmapLODLight lodlight)
{
var lodlights = lodlight?.LodLights?.LodLights;
var tn = FindLodLightTreeNode(lodlight);
if ((tn != null) && (tn.Parent != null) && (lodlights != null))
{
var pn = tn.Parent;
var yn = pn.Parent;
yn.Nodes.Remove(pn);
pn = yn.Nodes.Add("LOD Lights (" + (lodlights?.Length.ToString() ?? "0") + ")");
pn.Name = "LodLights";
pn.Tag = lodlight.LodLights.Ymap;
foreach (var ll in lodlights)
{
var ntn = pn.Nodes.Add(ll.ToString());
ntn.Tag = ll;
}
}
}
public void RemoveGrassBatchTreeNode(YmapGrassInstanceBatch batch) public void RemoveGrassBatchTreeNode(YmapGrassInstanceBatch batch)
{ {
var tn = FindGrassTreeNode(batch); var tn = FindGrassTreeNode(batch);

View File

@ -42,6 +42,7 @@ namespace CodeWalker.Project
private YmapFile CurrentYmapFile; private YmapFile CurrentYmapFile;
private YmapEntityDef CurrentEntity; private YmapEntityDef CurrentEntity;
private YmapCarGen CurrentCarGen; private YmapCarGen CurrentCarGen;
private YmapLODLight CurrentLodLight;
private YmapGrassInstanceBatch CurrentGrassBatch; private YmapGrassInstanceBatch CurrentGrassBatch;
private YtypFile CurrentYtypFile; private YtypFile CurrentYtypFile;
@ -387,6 +388,13 @@ namespace CodeWalker.Project
(panel) => { panel.SetCarGen(CurrentCarGen); }, //updateFunc (panel) => { panel.SetCarGen(CurrentCarGen); }, //updateFunc
(panel) => { return panel.CurrentCarGen == CurrentCarGen; }); //findFunc (panel) => { return panel.CurrentCarGen == CurrentCarGen; }); //findFunc
} }
public void ShowEditYmapLodLightPanel(bool promote)
{
ShowPanel(promote,
() => { return new EditYmapLodLightPanel(this); }, //createFunc
(panel) => { panel.SetLodLight(CurrentLodLight); }, //updateFunc
(panel) => { return panel.CurrentLodLight == CurrentLodLight; }); //findFunc
}
public void ShowEditYmapGrassBatchPanel(bool promote) public void ShowEditYmapGrassBatchPanel(bool promote)
{ {
ShowPanel(promote, ShowPanel(promote,
@ -630,6 +638,10 @@ namespace CodeWalker.Project
{ {
ShowEditYmapCarGenPanel(promote); ShowEditYmapCarGenPanel(promote);
} }
else if (CurrentLodLight != null)
{
ShowEditYmapLodLightPanel(promote);
}
else if (CurrentGrassBatch != null) else if (CurrentGrassBatch != null)
{ {
ShowEditYmapGrassBatchPanel(promote); ShowEditYmapGrassBatchPanel(promote);
@ -756,6 +768,7 @@ namespace CodeWalker.Project
CurrentMloEntity = item as MCEntityDef; CurrentMloEntity = item as MCEntityDef;
CurrentEntity = item as YmapEntityDef; CurrentEntity = item as YmapEntityDef;
CurrentCarGen = item as YmapCarGen; CurrentCarGen = item as YmapCarGen;
CurrentLodLight = item as YmapLODLight;
CurrentGrassBatch = item as YmapGrassInstanceBatch; CurrentGrassBatch = item as YmapGrassInstanceBatch;
CurrentYtypFile = item as YtypFile; CurrentYtypFile = item as YtypFile;
CurrentArchetype = item as Archetype; CurrentArchetype = item as Archetype;
@ -824,6 +837,10 @@ namespace CodeWalker.Project
{ {
CurrentYmapFile = CurrentCarGen.Ymap; CurrentYmapFile = CurrentCarGen.Ymap;
} }
else if (CurrentLodLight != null)
{
CurrentYmapFile = CurrentLodLight.Ymap;
}
else if (CurrentGrassBatch != null) else if (CurrentGrassBatch != null)
{ {
CurrentYmapFile = CurrentGrassBatch.Ymap; CurrentYmapFile = CurrentGrassBatch.Ymap;
@ -1773,6 +1790,10 @@ namespace CodeWalker.Project
{ {
ProjectExplorer?.TrySelectCarGenTreeNode(CurrentCarGen); ProjectExplorer?.TrySelectCarGenTreeNode(CurrentCarGen);
} }
else if (CurrentLodLight != null)
{
ProjectExplorer?.TrySelectLodLightTreeNode(CurrentLodLight);
}
else if (CurrentGrassBatch != null) else if (CurrentGrassBatch != null)
{ {
ProjectExplorer?.TrySelectGrassBatchTreeNode(CurrentGrassBatch); ProjectExplorer?.TrySelectGrassBatchTreeNode(CurrentGrassBatch);
@ -2284,6 +2305,140 @@ namespace CodeWalker.Project
return CurrentCarGen == cargen; return CurrentCarGen == cargen;
} }
public YmapLODLight NewLodLight(YmapLODLight copy = null, bool copyPosition = false, bool selectNew = true)
{
if (CurrentYmapFile == null) return null;
Vector3 pos = GetSpawnPos(10.0f);
YmapLODLight yll = new YmapLODLight();
if (copy != null)
{
yll.CopyFrom(copy);
}
else
{
yll.TimeAndStateFlags = 0x00FFFFFF;
yll.Type = LightType.Point;
yll.Colour = new SharpDX.Color(255, 255, 255, 127);
yll.Direction = Vector3.ForwardRH;
yll.Falloff = 10.0f;
//...
}
if (!copyPosition || (copy == null))
{
yll.Position = pos;
}
if (WorldForm != null)
{
lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering...
{
CurrentYmapFile.AddLodLight(yll);
}
WorldForm.UpdateLodLightGraphics(yll);
}
else
{
CurrentYmapFile.AddLodLight(yll);
}
if (selectNew)
{
LoadProjectTree();
ProjectExplorer?.TrySelectLodLightTreeNode(yll);
CurrentLodLight = yll;
ShowEditYmapLodLightPanel(false);
}
return yll;
}
public void AddLodLightToProject()
{
if (CurrentLodLight == null) return;
if (!YmapExistsInProject(CurrentLodLight.Ymap))
{
var lodlight = CurrentLodLight;
if (lodlight.DistLodLights?.Ymap != null)
{
AddYmapToProject(lodlight.DistLodLights.Ymap);
CurrentYmapFile.HasChanged = true;
}
CurrentYmapFile = lodlight.Ymap;
CurrentYmapFile.HasChanged = true;
AddYmapToProject(CurrentYmapFile);
CurrentLodLight = lodlight; //bug fix for some reason the treeview selects the project node here.
CurrentYmapFile = lodlight.Ymap;
ProjectExplorer?.TrySelectLodLightTreeNode(lodlight);
}
}
public bool DeleteLodLight()
{
if (CurrentYmapFile == null) return false;
if (CurrentLodLight == null) return false;
if (CurrentLodLight.Ymap != CurrentYmapFile) return false;
//if (CurrentYmapFile.LODLights == null) return false; //nothing to delete..
//if (MessageBox.Show("Are you sure you want to delete this LOD light?\n" + CurrentLodLight.ToString() + "\n\nThis operation cannot be undone. Continue?", "Confirm delete", MessageBoxButtons.YesNo) != DialogResult.Yes)
//{
// return true;
//}
var delyll = CurrentLodLight;
var lodlights = delyll.LodLights;
bool res = false;
if (WorldForm != null)
{
lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering...
{
res = CurrentYmapFile.RemoveLodLight(CurrentLodLight);
//WorldForm.SelectItem(null, null, null);
}
}
else
{
res = CurrentYmapFile.RemoveLodLight(CurrentLodLight);
}
if (!res)
{
MessageBox.Show("Unable to delete the LOD light. This shouldn't happen!");
}
ProjectExplorer?.RemoveLodLightTreeNode(CurrentLodLight);
ProjectExplorer?.SetYmapHasChanged(CurrentYmapFile, true);
ClosePanel((EditYmapLodLightPanel p) => { return p.Tag == delyll; });
CurrentLodLight = null;
CurrentYmapFile = null;
if (WorldForm != null)
{
if ((lodlights?.LodLights != null) && (lodlights.LodLights.Length > 0))
{
WorldForm.UpdateLodLightGraphics(lodlights.LodLights[0]);
}
WorldForm.SelectItem(null);
}
return true;
}
public bool IsCurrentLodLight(YmapLODLight lodlight)
{
return CurrentLodLight == lodlight;
}
private void ImportMenyooXml() private void ImportMenyooXml()
{ {
if (CurrentProjectFile == null) if (CurrentProjectFile == null)
@ -6887,6 +7042,7 @@ namespace CodeWalker.Project
var room = sel.MloRoomDef; var room = sel.MloRoomDef;
var ent = sel.EntityDef; var ent = sel.EntityDef;
var cargen = sel.CarGenerator; var cargen = sel.CarGenerator;
var lodlight = sel.LodLight;
var grassbatch = sel.GrassBatch; var grassbatch = sel.GrassBatch;
var collvert = sel.CollisionVertex; var collvert = sel.CollisionVertex;
var collpoly = sel.CollisionPoly; var collpoly = sel.CollisionPoly;
@ -6902,7 +7058,7 @@ namespace CodeWalker.Project
var audiopl = sel.Audio; var audiopl = sel.Audio;
Archetype arch = mlo?.Archetype ?? ent?.MloParent?.Archetype ?? ent?.Archetype; Archetype arch = mlo?.Archetype ?? ent?.MloParent?.Archetype ?? ent?.Archetype;
YtypFile ytyp = mlo?.Archetype?.Ytyp ?? ent?.MloParent?.Archetype?.Ytyp ?? ent?.Archetype?.Ytyp ?? room?.OwnerMlo?.Ytyp; YtypFile ytyp = mlo?.Archetype?.Ytyp ?? ent?.MloParent?.Archetype?.Ytyp ?? ent?.Archetype?.Ytyp ?? room?.OwnerMlo?.Ytyp;
YmapFile ymap = ent?.Ymap ?? cargen?.Ymap ?? grassbatch?.Ymap ?? mlo?.Ymap; YmapFile ymap = ent?.Ymap ?? cargen?.Ymap ?? lodlight?.Ymap ?? grassbatch?.Ymap ?? mlo?.Ymap;
YbnFile ybn = collbound?.GetRootYbn(); YbnFile ybn = collbound?.GetRootYbn();
YndFile ynd = pathnode?.Ynd; YndFile ynd = pathnode?.Ynd;
YnvFile ynv = navpoly?.Ynv ?? navpoint?.Ynv ?? navportal?.Ynv; YnvFile ynv = navpoly?.Ynv ?? navpoint?.Ynv ?? navportal?.Ynv;
@ -6921,6 +7077,10 @@ namespace CodeWalker.Project
{ {
ProjectExplorer?.TrySelectCarGenTreeNode(cargen); ProjectExplorer?.TrySelectCarGenTreeNode(cargen);
} }
if (wasmult || (lodlight != CurrentLodLight))
{
ProjectExplorer?.TrySelectLodLightTreeNode(lodlight);
}
if (wasmult || (grassbatch != CurrentGrassBatch)) if (wasmult || (grassbatch != CurrentGrassBatch))
{ {
ProjectExplorer?.TrySelectGrassBatchTreeNode(grassbatch); ProjectExplorer?.TrySelectGrassBatchTreeNode(grassbatch);
@ -7024,6 +7184,7 @@ namespace CodeWalker.Project
CurrentArchetype = arch; CurrentArchetype = arch;
CurrentEntity = ent ?? mlo; CurrentEntity = ent ?? mlo;
CurrentCarGen = cargen; CurrentCarGen = cargen;
CurrentLodLight = lodlight;
CurrentGrassBatch = grassbatch; CurrentGrassBatch = grassbatch;
CurrentYbnFile = ybn; CurrentYbnFile = ybn;
CurrentCollisionVertex = collvert; CurrentCollisionVertex = collvert;
@ -7091,6 +7252,10 @@ namespace CodeWalker.Project
{ {
OnWorldCarGenModified(sel.CarGenerator); OnWorldCarGenModified(sel.CarGenerator);
} }
else if (sel.LodLight != null)
{
OnWorldLodLightModified(sel.LodLight);
}
else if (sel.PathNode != null) else if (sel.PathNode != null)
{ {
OnWorldPathNodeModified(sel.PathNode, sel.PathLink); OnWorldPathNodeModified(sel.PathNode, sel.PathLink);
@ -7237,6 +7402,41 @@ namespace CodeWalker.Project
} }
} }
}
private void OnWorldLodLightModified(YmapLODLight lodlight)
{
if (lodlight?.Ymap == null) return;
if (CurrentProjectFile == null)
{
NewProject();
}
if (!YmapExistsInProject(lodlight.Ymap))
{
lodlight.Ymap.HasChanged = true;
AddYmapToProject(lodlight.Ymap);
ProjectExplorer?.TrySelectLodLightTreeNode(lodlight);
}
if (lodlight != CurrentLodLight)
{
CurrentLodLight = lodlight;
ProjectExplorer?.TrySelectLodLightTreeNode(lodlight);
}
if (lodlight == CurrentLodLight)
{
ShowEditYmapLodLightPanel(false);
ProjectExplorer?.UpdateLodLightTreeNode(lodlight);
if (lodlight.Ymap != null)
{
SetYmapHasChanged(true);
}
}
} }
private void OnWorldCollisionVertexModified(BoundVertex vert) private void OnWorldCollisionVertexModified(BoundVertex vert)
{ {

View File

@ -470,6 +470,135 @@ namespace CodeWalker.Project
public abstract class LodLightUndoStep : UndoStep
{
public YmapLODLight LodLight { get; set; }
protected void UpdateGraphics(WorldForm wf)
{
if (LodLight != null)
{
wf.UpdateLodLightGraphics(LodLight);
}
}
}
public class LodLightPositionUndoStep : LodLightUndoStep
{
public Vector3 StartPosition { get; set; }
public Vector3 EndPosition { get; set; }
public LodLightPositionUndoStep(YmapLODLight lodlight, Vector3 startpos)
{
LodLight = lodlight;
StartPosition = startpos;
EndPosition = lodlight?.Position ?? Vector3.Zero;
}
private void Update(WorldForm wf, ref MapSelection sel, Vector3 p)
{
LodLight?.SetPosition(p);
if (LodLight != sel.LodLight) wf.SelectObject(LodLight);
wf.SetWidgetPosition(p);
UpdateGraphics(wf);
}
public override void Undo(WorldForm wf, ref MapSelection sel)
{
Update(wf, ref sel, StartPosition);
}
public override void Redo(WorldForm wf, ref MapSelection sel)
{
Update(wf, ref sel, EndPosition);
}
public override string ToString()
{
return "LodLight " + (LodLight?.Index.ToString() ?? "") + ": Position";
}
}
public class LodLightRotationUndoStep : LodLightUndoStep
{
public Quaternion StartRotation { get; set; }
public Quaternion EndRotation { get; set; }
public LodLightRotationUndoStep(YmapLODLight lodlight, Quaternion startrot)
{
LodLight = lodlight;
StartRotation = startrot;
EndRotation = lodlight?.Orientation ?? Quaternion.Identity;
}
private void Update(WorldForm wf, ref MapSelection sel, Quaternion q)
{
LodLight?.SetOrientation(q);
if (LodLight != sel.LodLight) wf.SelectObject(LodLight);
wf.SetWidgetRotation(q);
UpdateGraphics(wf);
}
public override void Undo(WorldForm wf, ref MapSelection sel)
{
Update(wf, ref sel, StartRotation);
}
public override void Redo(WorldForm wf, ref MapSelection sel)
{
Update(wf, ref sel, EndRotation);
}
public override string ToString()
{
return "LodLight " + (LodLight?.Index.ToString() ?? "") + ": Rotation";
}
}
public class LodLightScaleUndoStep : LodLightUndoStep
{
public Vector3 StartScale { get; set; }
public Vector3 EndScale { get; set; }
public LodLightScaleUndoStep(YmapLODLight lodlight, Vector3 startscale)
{
LodLight = lodlight;
StartScale = startscale;
EndScale = lodlight?.Scale ?? new Vector3(1.0f);
}
private void Update(WorldForm wf, ref MapSelection sel, Vector3 s)
{
LodLight?.SetScale(s);
if (LodLight != sel.LodLight) wf.SelectObject(LodLight);
wf.SetWidgetScale(s);
UpdateGraphics(wf);
}
public override void Undo(WorldForm wf, ref MapSelection sel)
{
Update(wf, ref sel, StartScale);
}
public override void Redo(WorldForm wf, ref MapSelection sel)
{
Update(wf, ref sel, EndScale);
}
public override string ToString()
{
return "LodLight " + (LodLight?.Index.ToString() ?? "") + ": Scale";
}
}
public class CollisionPositionUndoStep : UndoStep public class CollisionPositionUndoStep : UndoStep
{ {
public Bounds Bounds { get; set; } public Bounds Bounds { get; set; }

View File

@ -1483,15 +1483,15 @@ namespace CodeWalker.Rendering
if (ll == null) return; if (ll == null) return;
if (dll == null) return; if (dll == null) return;
if (ll.Lights == null) if (ll.LodLights == null)
{ {
ll.Init(dll); ll.Init(dll);
} }
if (ll.Lights == null) if (ll.LodLights == null)
{ return; } { return; }
var n = ll.Lights.Length; var n = ll.LodLights.Length;
if (n <= 0) if (n <= 0)
{ return; } { return; }
@ -1503,7 +1503,7 @@ namespace CodeWalker.Rendering
for (int i = 0; i < n; i++) for (int i = 0; i < n; i++)
{ {
var l = ll.Lights[i]; var l = ll.LodLights[i];
var light = new LODLight(); var light = new LODLight();
light.Position = l.Position; light.Position = l.Position;
light.Colour = (uint)l.Colour.ToBgra(); light.Colour = (uint)l.Colour.ToBgra();

View File

@ -243,7 +243,11 @@ namespace CodeWalker.Rendering
{ {
instbatches.Invalidate(batch); instbatches.Invalidate(batch);
} }
public void Invalidate(YmapLODLight lodlight)
{
lodlights.Invalidate(lodlight.LodLights?.Ymap);
distlodlights.Invalidate(lodlight.DistLodLights);
}
} }

View File

@ -408,6 +408,10 @@ namespace CodeWalker.Rendering
{ {
renderableCache.Invalidate(batch); renderableCache.Invalidate(batch);
} }
public void Invalidate(YmapLODLight lodlight)
{
renderableCache.Invalidate(lodlight);
}
public void UpdateSelectionDrawFlags(DrawableModel model, DrawableGeometry geom, bool rem) public void UpdateSelectionDrawFlags(DrawableModel model, DrawableGeometry geom, bool rem)

View File

@ -263,7 +263,7 @@ namespace CodeWalker
} }
else if (LodLight != null) else if (LodLight != null)
{ {
name = (LodLight.LodLights?.Ymap?.Name ?? "") + ": " + LodLight.Index.ToString(); name = (LodLight.Ymap?.Name ?? "") + ": " + LodLight.Index.ToString();
} }
else if (BoxOccluder != null) else if (BoxOccluder != null)
{ {
@ -336,6 +336,7 @@ namespace CodeWalker
if (MultipleSelectionItems != null) return true; if (MultipleSelectionItems != null) return true;
if (EntityDef != null) return true; if (EntityDef != null) return true;
if (CarGenerator != null) return true; if (CarGenerator != null) return true;
if (LodLight != null) return true;
if (CollisionBounds != null) return true; if (CollisionBounds != null) return true;
if (CollisionPoly != null) return true; if (CollisionPoly != null) return true;
if (CollisionVertex != null) return true; if (CollisionVertex != null) return true;
@ -413,6 +414,15 @@ namespace CodeWalker
case WidgetMode.Scale: return new CarGenScaleUndoStep(CarGenerator, startScale); case WidgetMode.Scale: return new CarGenScaleUndoStep(CarGenerator, startScale);
} }
} }
else if (LodLight != null)
{
switch (mode)
{
case WidgetMode.Position: return new LodLightPositionUndoStep(LodLight, startPos);
case WidgetMode.Rotation: return new LodLightRotationUndoStep(LodLight, startRot);
case WidgetMode.Scale: return new LodLightScaleUndoStep(LodLight, startScale);
}
}
else if (PathNode != null) else if (PathNode != null)
{ {
switch (mode) switch (mode)
@ -1200,6 +1210,7 @@ namespace CodeWalker
Dictionary<TrainTrack, int> trainTracks = new Dictionary<TrainTrack, int>(); Dictionary<TrainTrack, int> trainTracks = new Dictionary<TrainTrack, int>();
Dictionary<YmtFile, int> scenarioYmts = new Dictionary<YmtFile, int>(); Dictionary<YmtFile, int> scenarioYmts = new Dictionary<YmtFile, int>();
Dictionary<Bounds, int> bounds = new Dictionary<Bounds, int>(); Dictionary<Bounds, int> bounds = new Dictionary<Bounds, int>();
Dictionary<YmapLODLights, int> lodlights = new Dictionary<YmapLODLights, int>();
foreach (var item in MultipleSelectionItems) foreach (var item in MultipleSelectionItems)
{ {
@ -1239,6 +1250,10 @@ namespace CodeWalker
{ {
bounds[item.CollisionVertex.Owner] = 1; bounds[item.CollisionVertex.Owner] = 1;
} }
if (item.LodLight?.LodLights != null)
{
lodlights[item.LodLight.LodLights] = 1;
}
} }
foreach (var kvp in bounds) foreach (var kvp in bounds)
{ {
@ -1260,6 +1275,13 @@ namespace CodeWalker
{ {
wf.UpdateScenarioGraphics(kvp.Key, false); wf.UpdateScenarioGraphics(kvp.Key, false);
} }
foreach (var kvp in lodlights)
{
if ((kvp.Key.LodLights != null) && (kvp.Key.LodLights.Length > 0))
{
wf.UpdateLodLightGraphics(kvp.Key.LodLights[0]);
}
}
} }
else else
{ {
@ -1299,6 +1321,10 @@ namespace CodeWalker
{ {
wf.UpdateCollisionBoundsGraphics(CollisionBounds); wf.UpdateCollisionBoundsGraphics(CollisionBounds);
} }
else if (LodLight != null)
{
wf.UpdateLodLightGraphics(LodLight);
}
} }
} }

View File

@ -1951,6 +1951,16 @@ namespace CodeWalker
} }
} }
public void UpdateLodLightGraphics(YmapLODLight lodlight)
{
lodlight.LodLights?.BuildBVH();
//lock (Renderer.RenderSyncRoot)
{
Renderer.Invalidate(lodlight);
}
}
public void UpdateGrassBatchGraphics(YmapGrassInstanceBatch grassBatch) public void UpdateGrassBatchGraphics(YmapGrassInstanceBatch grassBatch)
{ {
//lock (Renderer.RenderSyncRoot) //lock (Renderer.RenderSyncRoot)
@ -3650,6 +3660,10 @@ namespace CodeWalker
{ {
SelectionEntityTabPage.Text = "LodLight"; SelectionEntityTabPage.Text = "LodLight";
SelEntityPropertyGrid.SelectedObject = item.LodLight; SelEntityPropertyGrid.SelectedObject = item.LodLight;
ymap = item.LodLight.Ymap;
ToolbarCopyButton.Enabled = true;
ToolbarDeleteItemButton.Enabled = true;
ToolbarDeleteItemButton.Text = "Delete LOD light";
} }
else if (item.GrassBatch != null) else if (item.GrassBatch != null)
{ {