From 5cdde7a34f68b391787ac7d53a88e1f71c56271b Mon Sep 17 00:00:00 2001 From: dexy Date: Mon, 26 Apr 2021 04:41:02 +1000 Subject: [PATCH] LodLights editing basics --- .../GameFiles/FileTypes/YmapFile.cs | 286 +++++++- .../Panels/EditYmapLodLightPanel.Designer.cs | 619 ++++++++++++++++++ .../Project/Panels/EditYmapLodLightPanel.cs | 521 +++++++++++++++ .../Project/Panels/EditYmapLodLightPanel.resx | 409 ++++++++++++ .../Project/Panels/ProjectExplorerPanel.cs | 84 +++ CodeWalker/Project/ProjectForm.cs | 202 +++++- CodeWalker/Project/UndoStep.cs | 129 ++++ CodeWalker/Rendering/Renderable.cs | 8 +- CodeWalker/Rendering/RenderableCache.cs | 6 +- CodeWalker/Rendering/Renderer.cs | 4 + CodeWalker/World/MapSelection.cs | 28 +- CodeWalker/WorldForm.cs | 14 + 12 files changed, 2282 insertions(+), 28 deletions(-) create mode 100644 CodeWalker/Project/Panels/EditYmapLodLightPanel.Designer.cs create mode 100644 CodeWalker/Project/Panels/EditYmapLodLightPanel.cs create mode 100644 CodeWalker/Project/Panels/EditYmapLodLightPanel.resx diff --git a/CodeWalker.Core/GameFiles/FileTypes/YmapFile.cs b/CodeWalker.Core/GameFiles/FileTypes/YmapFile.cs index 8507876..368bb16 100644 --- a/CodeWalker.Core/GameFiles/FileTypes/YmapFile.cs +++ b/CodeWalker.Core/GameFiles/FileTypes/YmapFile.cs @@ -554,7 +554,6 @@ namespace CodeWalker.GameFiles CCarGens[i] = CarGenerators[i].CCarGen; } } - public void BuildInstances() { if (GrassInstanceBatches == null) @@ -580,6 +579,16 @@ namespace CodeWalker.GameFiles 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() { @@ -590,10 +599,10 @@ namespace CodeWalker.GameFiles BuildCEntityDefs(); //technically this isn't required anymore since the CEntityDefs is no longer used for saving. BuildCCarGens(); BuildInstances(); + BuildLodLights(); + BuildDistantLodLights(); //TODO: - //BuildLodLights(); - //BuildDistantLodLights(); //BuildTimecycleModifiers(); //already being saved - update them.. //BuildBoxOccluders(); //BuildOccludeModels(); @@ -654,8 +663,6 @@ namespace CodeWalker.GameFiles if (mapdata.occludeModels.Count1 != 0) LogSaveWarning("occludeModels 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.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.occludeModels = 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 lodlights = new List(); + 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 newlodlights = new List(); + + 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) { List batches = new List(); @@ -1118,6 +1189,14 @@ namespace CodeWalker.GameFiles { 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; @@ -1203,7 +1282,6 @@ namespace CodeWalker.GameFiles emin = Vector3.Min(emin, bbmin); emax = Vector3.Max(emax, bbmax); - smin = Vector3.Min(smin, sbmin); smax = Vector3.Max(smax, sbmax); } @@ -1216,7 +1294,6 @@ namespace CodeWalker.GameFiles { emin = Vector3.Min(emin, batch.AABBMin); emax = Vector3.Max(emax, batch.AABBMax); - smin = Vector3.Min(smin, (batch.AABBMin - 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) { - emin = Vector3.Min(emin, cargen.BBMin); - emax = Vector3.Max(emax, cargen.BBMax); - - smin = Vector3.Min(smin, cargen.BBMin - cargen._CCarGen.perpendicularLength); //just a random guess, maybe should be more? - smax = Vector3.Max(smax, cargen.BBMax + cargen._CCarGen.perpendicularLength); + var len = cargen._CCarGen.perpendicularLength; + emin = Vector3.Min(emin, cargen.Position - len); + emax = Vector3.Max(emax, cargen.Position + len); + smin = Vector3.Min(smin, cargen.Position - len*2.0f); //just a random guess, maybe should be more? + 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; if (_CMapData.entitiesExtentsMin != emin) @@ -2292,7 +2386,35 @@ 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() { if (Ymap != null) @@ -2320,7 +2442,7 @@ namespace CodeWalker.GameFiles public Vector3 BBMax { get; set; } public YmapFile Ymap { get; set; } - public YmapLODLight[] Lights { get; set; } + public YmapLODLight[] LodLights { get; set; } public PathBVH BVH { get; set; } @@ -2340,20 +2462,21 @@ namespace CodeWalker.GameFiles n = Math.Min(n, coronaIntensity?.Length ?? 0); if (n == 0) return; - Lights = new YmapLODLight[n]; + LodLights = new YmapLODLight[n]; for (int i = 0; i < n; i++) { var l = new YmapLODLight(); l.Init(this, parent, i); - Lights[i] = l; + LodLights[i] = l; } + CalcBB(); 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() { if (Ymap != null) @@ -2396,6 +2561,7 @@ namespace CodeWalker.GameFiles [TypeConverter(typeof(ExpandableObjectConverter))] public class YmapLODLight : BasePathNode { + public YmapFile Ymap { get { return LodLights?.Ymap ?? DistLodLights?.Ymap; } } public YmapLODLights LodLights { get; set; } public YmapDistantLODLights DistLodLights { get; set; } public int Index { get; set; } @@ -2404,7 +2570,7 @@ namespace CodeWalker.GameFiles public Vector3 Direction { get; set; } public float Falloff { get; set; } public float FalloffExponent { get; set; } - public FlagsUint TimeAndStateFlags { get; set; } + public uint TimeAndStateFlags { get; set; } public uint Hash { get; set; } public byte ConeInnerAngle { get; set; } public byte ConeOuterAngleOrCapExt { get; set; } @@ -2422,6 +2588,43 @@ namespace CodeWalker.GameFiles { 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]; CoronaIntensity = l.coronaIntensity[i]; + UpdateTangentsAndOrientation(); + + Scale = Vector3.One; + } + + public void UpdateTangentsAndOrientation() + { switch (Type) { default: @@ -2475,14 +2685,27 @@ namespace CodeWalker.GameFiles m.Row3 = new Vector4(Direction, 0); 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) { Position = pos; + + if ((DistLodLights?.positions != null) && (DistLodLights.positions.Length >= Index)) + { + DistLodLights.positions[Index] = new MetaVECTOR3(pos); + } + } 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() { return Index.ToString() + ": " + Position.ToString(); diff --git a/CodeWalker/Project/Panels/EditYmapLodLightPanel.Designer.cs b/CodeWalker/Project/Panels/EditYmapLodLightPanel.Designer.cs new file mode 100644 index 0000000..22ffb9c --- /dev/null +++ b/CodeWalker/Project/Panels/EditYmapLodLightPanel.Designer.cs @@ -0,0 +1,619 @@ + +namespace CodeWalker.Project.Panels +{ + partial class EditYmapLodLightPanel + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + 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; + } +} \ No newline at end of file diff --git a/CodeWalker/Project/Panels/EditYmapLodLightPanel.cs b/CodeWalker/Project/Panels/EditYmapLodLightPanel.cs new file mode 100644 index 0000000..ee35f0e --- /dev/null +++ b/CodeWalker/Project/Panels/EditYmapLodLightPanel.cs @@ -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; + } + } +} diff --git a/CodeWalker/Project/Panels/EditYmapLodLightPanel.resx b/CodeWalker/Project/Panels/EditYmapLodLightPanel.resx new file mode 100644 index 0000000..0960cbe --- /dev/null +++ b/CodeWalker/Project/Panels/EditYmapLodLightPanel.resx @@ -0,0 +1,409 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + 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= + + + \ No newline at end of file diff --git a/CodeWalker/Project/Panels/ProjectExplorerPanel.cs b/CodeWalker/Project/Panels/ProjectExplorerPanel.cs index 5797d38..f0108ba 100644 --- a/CodeWalker/Project/Panels/ProjectExplorerPanel.cs +++ b/CodeWalker/Project/Panels/ProjectExplorerPanel.cs @@ -255,6 +255,19 @@ namespace CodeWalker.Project.Panels 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)) { var grassbatchesnodes = node.Nodes.Add("Grass Batches (" + ymap.GrassInstanceBatches.Length.ToString() + ")"); @@ -1013,6 +1026,20 @@ namespace CodeWalker.Project.Panels } 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) { if (batch == null) return null; @@ -1432,6 +1459,21 @@ namespace CodeWalker.Project.Panels { 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) { 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) { TreeNode grassNode = FindGrassTreeNode(grassBatch); @@ -1959,6 +2016,14 @@ namespace CodeWalker.Project.Panels 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) { var tn = FindPathNodeTreeNode(node); @@ -2059,6 +2124,25 @@ namespace CodeWalker.Project.Panels 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) { var tn = FindGrassTreeNode(batch); diff --git a/CodeWalker/Project/ProjectForm.cs b/CodeWalker/Project/ProjectForm.cs index 62c4618..dcac3bd 100644 --- a/CodeWalker/Project/ProjectForm.cs +++ b/CodeWalker/Project/ProjectForm.cs @@ -42,6 +42,7 @@ namespace CodeWalker.Project private YmapFile CurrentYmapFile; private YmapEntityDef CurrentEntity; private YmapCarGen CurrentCarGen; + private YmapLODLight CurrentLodLight; private YmapGrassInstanceBatch CurrentGrassBatch; private YtypFile CurrentYtypFile; @@ -387,6 +388,13 @@ namespace CodeWalker.Project (panel) => { panel.SetCarGen(CurrentCarGen); }, //updateFunc (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) { ShowPanel(promote, @@ -630,6 +638,10 @@ namespace CodeWalker.Project { ShowEditYmapCarGenPanel(promote); } + else if (CurrentLodLight != null) + { + ShowEditYmapLodLightPanel(promote); + } else if (CurrentGrassBatch != null) { ShowEditYmapGrassBatchPanel(promote); @@ -756,6 +768,7 @@ namespace CodeWalker.Project CurrentMloEntity = item as MCEntityDef; CurrentEntity = item as YmapEntityDef; CurrentCarGen = item as YmapCarGen; + CurrentLodLight = item as YmapLODLight; CurrentGrassBatch = item as YmapGrassInstanceBatch; CurrentYtypFile = item as YtypFile; CurrentArchetype = item as Archetype; @@ -824,6 +837,10 @@ namespace CodeWalker.Project { CurrentYmapFile = CurrentCarGen.Ymap; } + else if (CurrentLodLight != null) + { + CurrentYmapFile = CurrentLodLight.Ymap; + } else if (CurrentGrassBatch != null) { CurrentYmapFile = CurrentGrassBatch.Ymap; @@ -1773,6 +1790,10 @@ namespace CodeWalker.Project { ProjectExplorer?.TrySelectCarGenTreeNode(CurrentCarGen); } + else if (CurrentLodLight != null) + { + ProjectExplorer?.TrySelectLodLightTreeNode(CurrentLodLight); + } else if (CurrentGrassBatch != null) { ProjectExplorer?.TrySelectGrassBatchTreeNode(CurrentGrassBatch); @@ -2284,6 +2305,140 @@ namespace CodeWalker.Project 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() { if (CurrentProjectFile == null) @@ -6887,6 +7042,7 @@ namespace CodeWalker.Project var room = sel.MloRoomDef; var ent = sel.EntityDef; var cargen = sel.CarGenerator; + var lodlight = sel.LodLight; var grassbatch = sel.GrassBatch; var collvert = sel.CollisionVertex; var collpoly = sel.CollisionPoly; @@ -6902,7 +7058,7 @@ namespace CodeWalker.Project var audiopl = sel.Audio; Archetype arch = mlo?.Archetype ?? ent?.MloParent?.Archetype ?? ent?.Archetype; 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(); YndFile ynd = pathnode?.Ynd; YnvFile ynv = navpoly?.Ynv ?? navpoint?.Ynv ?? navportal?.Ynv; @@ -6921,6 +7077,10 @@ namespace CodeWalker.Project { ProjectExplorer?.TrySelectCarGenTreeNode(cargen); } + if (wasmult || (lodlight != CurrentLodLight)) + { + ProjectExplorer?.TrySelectLodLightTreeNode(lodlight); + } if (wasmult || (grassbatch != CurrentGrassBatch)) { ProjectExplorer?.TrySelectGrassBatchTreeNode(grassbatch); @@ -7024,6 +7184,7 @@ namespace CodeWalker.Project CurrentArchetype = arch; CurrentEntity = ent ?? mlo; CurrentCarGen = cargen; + CurrentLodLight = lodlight; CurrentGrassBatch = grassbatch; CurrentYbnFile = ybn; CurrentCollisionVertex = collvert; @@ -7091,6 +7252,10 @@ namespace CodeWalker.Project { OnWorldCarGenModified(sel.CarGenerator); } + else if (sel.LodLight != null) + { + OnWorldLodLightModified(sel.LodLight); + } else if (sel.PathNode != null) { 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) { diff --git a/CodeWalker/Project/UndoStep.cs b/CodeWalker/Project/UndoStep.cs index 862a261..a2edf8f 100644 --- a/CodeWalker/Project/UndoStep.cs +++ b/CodeWalker/Project/UndoStep.cs @@ -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 Bounds Bounds { get; set; } diff --git a/CodeWalker/Rendering/Renderable.cs b/CodeWalker/Rendering/Renderable.cs index 7ef9d94..567d581 100644 --- a/CodeWalker/Rendering/Renderable.cs +++ b/CodeWalker/Rendering/Renderable.cs @@ -1483,15 +1483,15 @@ namespace CodeWalker.Rendering if (ll == null) return; if (dll == null) return; - if (ll.Lights == null) + if (ll.LodLights == null) { ll.Init(dll); } - if (ll.Lights == null) + if (ll.LodLights == null) { return; } - var n = ll.Lights.Length; + var n = ll.LodLights.Length; if (n <= 0) { return; } @@ -1503,7 +1503,7 @@ namespace CodeWalker.Rendering for (int i = 0; i < n; i++) { - var l = ll.Lights[i]; + var l = ll.LodLights[i]; var light = new LODLight(); light.Position = l.Position; light.Colour = (uint)l.Colour.ToBgra(); diff --git a/CodeWalker/Rendering/RenderableCache.cs b/CodeWalker/Rendering/RenderableCache.cs index 46a62e6..815027f 100644 --- a/CodeWalker/Rendering/RenderableCache.cs +++ b/CodeWalker/Rendering/RenderableCache.cs @@ -243,7 +243,11 @@ namespace CodeWalker.Rendering { instbatches.Invalidate(batch); } - + public void Invalidate(YmapLODLight lodlight) + { + lodlights.Invalidate(lodlight.LodLights?.Ymap); + distlodlights.Invalidate(lodlight.DistLodLights); + } } diff --git a/CodeWalker/Rendering/Renderer.cs b/CodeWalker/Rendering/Renderer.cs index b0f2d40..140536c 100644 --- a/CodeWalker/Rendering/Renderer.cs +++ b/CodeWalker/Rendering/Renderer.cs @@ -408,6 +408,10 @@ namespace CodeWalker.Rendering { renderableCache.Invalidate(batch); } + public void Invalidate(YmapLODLight lodlight) + { + renderableCache.Invalidate(lodlight); + } public void UpdateSelectionDrawFlags(DrawableModel model, DrawableGeometry geom, bool rem) diff --git a/CodeWalker/World/MapSelection.cs b/CodeWalker/World/MapSelection.cs index 4f880ae..b1afb75 100644 --- a/CodeWalker/World/MapSelection.cs +++ b/CodeWalker/World/MapSelection.cs @@ -263,7 +263,7 @@ namespace CodeWalker } else if (LodLight != null) { - name = (LodLight.LodLights?.Ymap?.Name ?? "") + ": " + LodLight.Index.ToString(); + name = (LodLight.Ymap?.Name ?? "") + ": " + LodLight.Index.ToString(); } else if (BoxOccluder != null) { @@ -336,6 +336,7 @@ namespace CodeWalker if (MultipleSelectionItems != null) return true; if (EntityDef != null) return true; if (CarGenerator != null) return true; + if (LodLight != null) return true; if (CollisionBounds != null) return true; if (CollisionPoly != null) return true; if (CollisionVertex != null) return true; @@ -413,6 +414,15 @@ namespace CodeWalker 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) { switch (mode) @@ -1200,6 +1210,7 @@ namespace CodeWalker Dictionary trainTracks = new Dictionary(); Dictionary scenarioYmts = new Dictionary(); Dictionary bounds = new Dictionary(); + Dictionary lodlights = new Dictionary(); foreach (var item in MultipleSelectionItems) { @@ -1239,6 +1250,10 @@ namespace CodeWalker { bounds[item.CollisionVertex.Owner] = 1; } + if (item.LodLight?.LodLights != null) + { + lodlights[item.LodLight.LodLights] = 1; + } } foreach (var kvp in bounds) { @@ -1260,6 +1275,13 @@ namespace CodeWalker { 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 { @@ -1299,6 +1321,10 @@ namespace CodeWalker { wf.UpdateCollisionBoundsGraphics(CollisionBounds); } + else if (LodLight != null) + { + wf.UpdateLodLightGraphics(LodLight); + } } } diff --git a/CodeWalker/WorldForm.cs b/CodeWalker/WorldForm.cs index 5824df5..823acde 100644 --- a/CodeWalker/WorldForm.cs +++ b/CodeWalker/WorldForm.cs @@ -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) { //lock (Renderer.RenderSyncRoot) @@ -3650,6 +3660,10 @@ namespace CodeWalker { SelectionEntityTabPage.Text = "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) {