From 5ebda6f0bb571ff326ab89baf2460964876ca35e Mon Sep 17 00:00:00 2001 From: dexy Date: Mon, 3 May 2021 22:59:31 +1000 Subject: [PATCH] HD lights rendering in exterior and lodlights switching, lights falloff fix --- .../GameFiles/FileTypes/YmapFile.cs | 13 ++- CodeWalker.Shaders/LightPS.hlsli | 20 ++-- CodeWalker/Rendering/Renderable.cs | 35 ++++--- CodeWalker/Rendering/RenderableCache.cs | 17 +++- CodeWalker/Rendering/Renderer.cs | 93 +++++++++++++++--- CodeWalker/WorldForm.Designer.cs | 60 ++++++----- CodeWalker/WorldForm.cs | 5 + CodeWalker/WorldForm.resx | 48 ++++----- Shaders/LightPS.cso | Bin 6032 -> 5968 bytes Shaders/LightPS_MS.cso | Bin 33440 -> 32948 bytes Shaders/LodLightsPS.cso | Bin 6020 -> 5984 bytes Shaders/LodLightsPS_MS.cso | Bin 34404 -> 34116 bytes 12 files changed, 206 insertions(+), 85 deletions(-) diff --git a/CodeWalker.Core/GameFiles/FileTypes/YmapFile.cs b/CodeWalker.Core/GameFiles/FileTypes/YmapFile.cs index 1b249d6..677c4be 100644 --- a/CodeWalker.Core/GameFiles/FileTypes/YmapFile.cs +++ b/CodeWalker.Core/GameFiles/FileTypes/YmapFile.cs @@ -968,6 +968,15 @@ namespace CodeWalker.GameFiles } } } + if (LODLights != null) + { + if (Parent?.DistantLODLights != null) + { + LODLights.Init(Parent.DistantLODLights); + } + else + { } + } } @@ -2116,6 +2125,7 @@ namespace CodeWalker.GameFiles ints[4] = (uint)(bb.Maximum.Y * 10.0f); ints[5] = (uint)(bb.Maximum.Z * 10.0f); + var bones = skel?.BonesMap; var exts = (Archetype.Extensions?.Length ?? 0);// + (Extensions?.Length ?? 0);//seems entity extensions aren't included in this //todo: create extension light instances @@ -2126,7 +2136,7 @@ namespace CodeWalker.GameFiles var la = lightAttrs[i]; var xform = Matrix.Identity; - if ((skel != null) && (skel.BonesMap.TryGetValue(la.BoneId, out Bone bone))) + if ((bones != null) && (bones.TryGetValue(la.BoneId, out Bone bone))) { xform = bone.AbsTransform; } @@ -2995,6 +3005,7 @@ namespace CodeWalker.GameFiles } } + public bool Enabled { get; set; } = true; public void Init(YmapLODLights l, YmapDistantLODLights p, int i) { diff --git a/CodeWalker.Shaders/LightPS.hlsli b/CodeWalker.Shaders/LightPS.hlsli index acafeec..bbb80cf 100644 --- a/CodeWalker.Shaders/LightPS.hlsli +++ b/CodeWalker.Shaders/LightPS.hlsli @@ -92,6 +92,12 @@ float4 GetLineSegmentNearestPoint(float3 v, float3 a, float3 b) } } +float GetAttenuation(float ldist, float falloff, float falloffExponent) +{ + float d = ldist / falloff; + return saturate((1 - d) / (1 + d*d*falloffExponent)); +} + float3 DeferredDirectionalLight(float3 camRel, float3 norm, float4 diffuse, float4 specular, float4 irradiance) { @@ -123,14 +129,14 @@ float4 DeferredLODLight(float3 camRel, float3 norm, float4 diffuse, float4 specu if (ldist <= 0) return 0; float4 rgbi = Unpack4x8UNF(lodlight.Colour).gbar; - float3 lcol = rgbi.rgb * rgbi.a * 5.0f; + float3 lcol = rgbi.rgb * rgbi.a * 100.0f; float3 ldir = srpos / ldist; float pclit = saturate(dot(ldir, norm)); float lamt = 1; if (LightType == 1)//point (sphere) { - lamt *= pow(saturate(1 - (ldist / lodlight.Falloff)), lodlight.FalloffExponent); + lamt *= GetAttenuation(ldist, lodlight.Falloff, lodlight.FalloffExponent); } else if (LightType == 2)//spot (cone) { @@ -139,11 +145,11 @@ float4 DeferredLODLight(float3 camRel, float3 norm, float4 diffuse, float4 specu float oang = lodlight.OuterAngleOrCapExt; if (ang > oang) return 0; lamt *= saturate(1 - ((ang - iang) / (oang - iang))); - lamt *= pow(saturate(1 - (ldist / lodlight.Falloff)), lodlight.FalloffExponent); + lamt *= GetAttenuation(ldist, lodlight.Falloff, lodlight.FalloffExponent); } else if (LightType == 4)//capsule { - lamt *= pow(saturate(1 - (ldist / lodlight.Falloff)), lodlight.FalloffExponent); //TODO! proper capsule lighting... (use point-line dist!) + lamt *= GetAttenuation(ldist, lodlight.Falloff, lodlight.FalloffExponent); //TODO! proper capsule lighting... (use point-line dist!) } pclit *= lamt; @@ -185,7 +191,7 @@ float4 DeferredLight(float3 camRel, float3 norm, float4 diffuse, float4 specular if (InstType == 1)//point (sphere) { - lamt *= pow(saturate(1 - (ldist / InstFalloff)), InstFalloffExponent); + lamt *= GetAttenuation(ldist, InstFalloff, InstFalloffExponent); } else if (InstType == 2)//spot (cone) { @@ -194,11 +200,11 @@ float4 DeferredLight(float3 camRel, float3 norm, float4 diffuse, float4 specular float oang = InstConeOuterAngle; if (ang > oang) return 0; lamt *= saturate(1 - ((ang - iang) / (oang - iang))); - lamt *= pow(saturate(1 - (ldist / InstFalloff)), InstFalloffExponent); + lamt *= GetAttenuation(ldist, InstFalloff, InstFalloffExponent); } else if (InstType == 4)//capsule { - lamt *= pow(saturate(1 - (ldist / InstFalloff)), InstFalloffExponent); + lamt *= GetAttenuation(ldist, InstFalloff, InstFalloffExponent); } pclit *= lamt; diff --git a/CodeWalker/Rendering/Renderable.cs b/CodeWalker/Rendering/Renderable.cs index 2b1c54b..8a38126 100644 --- a/CodeWalker/Rendering/Renderable.cs +++ b/CodeWalker/Rendering/Renderable.cs @@ -1373,17 +1373,28 @@ namespace CodeWalker.Rendering public void Init(ref LightAttributes_s l) { - Position = l.Position; - Colour = new Vector3(l.ColorR, l.ColorG, l.ColorB) * ((l.Intensity * 5.0f) / 255.0f); - Direction = l.Direction; - TangentX = l.Tangent; - TangentY = Vector3.Cross(l.Direction, l.Tangent); + var pos = l.Position; + var dir = l.Direction; + var tan = l.Tangent; + var bones = Owner?.Skeleton?.BonesMap; + if ((bones != null) && (bones.TryGetValue(l.BoneId, out Bone bone))) + { + var xform = bone.AbsTransform; + pos = xform.Multiply(pos); + dir = xform.MultiplyRot(dir); + tan = xform.MultiplyRot(tan); + } + Position = pos; + Colour = new Vector3(l.ColorR, l.ColorG, l.ColorB) * (2.0f * l.Intensity / 255.0f); + Direction = dir; + TangentX = tan; + TangentY = Vector3.Normalize(Vector3.Cross(l.Direction, TangentX)); Type = l.Type; Intensity = l.Intensity; Falloff = l.Falloff; - FalloffExponent = Math.Max(l.FalloffExponent * 0.25f, 0.5f);//is this right? - ConeInnerAngle = l.ConeInnerAngle * 0.01745329f; //is this right?? - ConeOuterAngle = l.ConeOuterAngle * 0.01745329f; //pi/180 + FalloffExponent = l.FalloffExponent; + ConeInnerAngle = Math.Min(l.ConeInnerAngle, l.ConeOuterAngle) * 0.01745329f; //is this right?? + ConeOuterAngle = Math.Max(l.ConeInnerAngle, l.ConeOuterAngle) * 0.01745329f; //pi/180 CapsuleExtent = l.Extent; CullingPlaneNormal = l.CullingPlaneNormal; CullingPlaneOffset = l.CullingPlaneOffset; @@ -1483,11 +1494,6 @@ namespace CodeWalker.Rendering if (ll == null) return; if (dll == null) return; - if (ll.LodLights == null) - { - ll.Init(dll); - } - if (ll.LodLights == null) { return; } @@ -1504,6 +1510,7 @@ namespace CodeWalker.Rendering for (int i = 0; i < n; i++) { var l = ll.LodLights[i]; + if (l.Enabled == false) continue; var light = new LODLight(); light.Position = l.Position; light.Colour = (uint)l.Colour.ToBgra(); @@ -1512,7 +1519,7 @@ namespace CodeWalker.Rendering light.TangentX = new Vector4(l.TangentX, 0.0f); light.TangentY = new Vector4(l.TangentY, 0.0f); light.Falloff = l.Falloff; - light.FalloffExponent = Math.Max(l.FalloffExponent*0.01f, 0.5f);//is this right? + light.FalloffExponent = l.FalloffExponent; light.InnerAngle = l.ConeInnerAngle * 0.012319971f; //pi/255 light.OuterAngleOrCapExt = l.ConeOuterAngleOrCapExt * 0.012319971f; //pi/255 var type = l.Type; diff --git a/CodeWalker/Rendering/RenderableCache.cs b/CodeWalker/Rendering/RenderableCache.cs index 0113585..9f487aa 100644 --- a/CodeWalker/Rendering/RenderableCache.cs +++ b/CodeWalker/Rendering/RenderableCache.cs @@ -248,6 +248,10 @@ namespace CodeWalker.Rendering lodlights.Invalidate(lodlight.LodLights?.Ymap); distlodlights.Invalidate(lodlight.DistLodLights); } + public void InvalidateImmediate(YmapLODLights lodlightsonly) + { + lodlights.UpdateImmediate(lodlightsonly?.Ymap, currentDevice); + } } @@ -432,7 +436,18 @@ namespace CodeWalker.Rendering keysToInvalidate.Enqueue(key); } - + public void UpdateImmediate(TKey key, Device device) + { + TVal item; + if (cacheitems.TryGetValue(key, out item)) + { + Interlocked.Add(ref CacheUse, -item.DataSize); + item.Unload(); + item.Init(key); + item.Load(device); + Interlocked.Add(ref CacheUse, item.DataSize); + } + } } } diff --git a/CodeWalker/Rendering/Renderer.cs b/CodeWalker/Rendering/Renderer.cs index 7622b8d..71b9f0a 100644 --- a/CodeWalker/Rendering/Renderer.cs +++ b/CodeWalker/Rendering/Renderer.cs @@ -550,7 +550,7 @@ namespace CodeWalker.Rendering lightartificialdowncolour = (Color4)weather.CurrentValues.lightArtificialExtDown; float lamult = weather.CurrentValues.lightDirAmbIntensityMult; float abounce = weather.CurrentValues.lightDirAmbBounce; - float minmult = hdr ? 0.1f : 0.5f; + float minmult = hdr ? 0.0f : 0.5f; lightdircolour *= Math.Max(lightdircolour.Alpha, minmult); lightdirambcolour *= lightdirambcolour.Alpha * lamult; // 0.1f * lamult; @@ -1831,11 +1831,17 @@ namespace CodeWalker.Rendering LodManager.MapViewEnabled = MapViewEnabled; LodManager.MapViewDist = camera.OrthographicSize / MapViewDetail; LodManager.ShowScriptedYmaps = ShowScriptedYmaps; + LodManager.LODLightsEnabled = renderlodlights; + LodManager.HDLightsEnabled = renderlights; LodManager.Update(renderworldVisibleYmapDict, camera, currentElapsedTime); + foreach (var updatelodlights in LodManager.UpdateLodLights) + { + renderableCache.InvalidateImmediate(updatelodlights); + } - var ents = LodManager.GetVisibleLeaves(); + var ents = LodManager.VisibleLeaves; for (int i = 0; i < ents.Count; i++) { @@ -3267,16 +3273,13 @@ namespace CodeWalker.Rendering { entity?.EnsureLights(rndbl.Key); - if (interiorent)//only interior ents making lights! todo: fix LOD lights + var linst = new RenderableLightInst(); + for (int i = 0; i < rndbl.Lights.Length; i++) { - var linst = new RenderableLightInst(); - for (int i = 0; i < rndbl.Lights.Length; i++) - { - linst.EntityPosition = position; - linst.EntityRotation = orientation; - linst.Light = rndbl.Lights[i]; - shaders.Enqueue(ref linst); - } + linst.EntityPosition = position; + linst.EntityRotation = orientation; + linst.Light = rndbl.Lights[i]; + shaders.Enqueue(ref linst); } } @@ -3956,6 +3959,8 @@ namespace CodeWalker.Rendering public bool MapViewEnabled = false; public float MapViewDist = 1.0f; public bool ShowScriptedYmaps = true; + public bool HDLightsEnabled = true; + public bool LODLightsEnabled = true; public Camera Camera = null; public Vector3 Position = Vector3.Zero; @@ -3965,6 +3970,11 @@ namespace CodeWalker.Rendering public Dictionary RootEntities = new Dictionary(); public List VisibleLeaves = new List(); + public Dictionary LodLightsDict = new Dictionary(); + public HashSet VisibleLights = new HashSet(); + public HashSet VisibleLightsPrev = new HashSet(); + public HashSet UpdateLodLights = new HashSet(); + public void Update(Dictionary ymaps, Camera camera, float elapsed) { Camera = camera; @@ -4014,6 +4024,14 @@ namespace CodeWalker.Rendering } } } + var remLodLights = ymap.LODLights?.LodLights; + if (remLodLights != null) + { + for (int i = 0; i < remLodLights.Length; i++) + { + LodLightsDict.Remove(remLodLights[i].Hash); + } + } ymap.LodManagerUpdate = false; ymap.LodManagerOldEntities = null; } @@ -4042,15 +4060,21 @@ namespace CodeWalker.Rendering } } } + var addLodLights = ymap.LODLights?.LodLights; + if (addLodLights != null) + { + for (int i = 0; i < addLodLights.Length; i++) + { + var light = addLodLights[i]; + LodLightsDict[light.Hash] = light; + } + } } } - } - - public List GetVisibleLeaves() - { VisibleLeaves.Clear(); + VisibleLights.Clear(); foreach (var kvp in RootEntities) { var ent = kvp.Key; @@ -4063,8 +4087,37 @@ namespace CodeWalker.Rendering } } } - return VisibleLeaves; + + UpdateLodLights.Clear(); + foreach (var light in VisibleLights) + { + if (VisibleLightsPrev.Contains(light) == false) + { + if (LodLightsDict.TryGetValue(light.Hash, out var lodlight)) + { + lodlight.Enabled = false; + UpdateLodLights.Add(lodlight.LodLights); + } + } + } + foreach (var light in VisibleLightsPrev) + { + if (VisibleLights.Contains(light) == false) + { + if (LodLightsDict.TryGetValue(light.Hash, out var lodlight)) + { + lodlight.Enabled = true; + UpdateLodLights.Add(lodlight.LodLights); + } + } + } + + + var vl = VisibleLights; + VisibleLights = VisibleLightsPrev; + VisibleLightsPrev = vl; } + private void RecurseAddVisibleLeaves(YmapEntityDef ent) { var clist = GetEntityChildren(ent); @@ -4082,6 +4135,14 @@ namespace CodeWalker.Rendering if (EntityVisible(ent)) { VisibleLeaves.Add(ent); + + if (HDLightsEnabled && (ent.Lights != null)) + { + for (int i = 0; i < ent.Lights.Length; i++) + { + VisibleLights.Add(ent.Lights[i]); + } + } } } } diff --git a/CodeWalker/WorldForm.Designer.cs b/CodeWalker/WorldForm.Designer.cs index e0e812e..fa5679d 100644 --- a/CodeWalker/WorldForm.Designer.cs +++ b/CodeWalker/WorldForm.Designer.cs @@ -312,6 +312,7 @@ namespace CodeWalker this.ToolbarPanel = new System.Windows.Forms.Panel(); this.SubtitleLabel = new System.Windows.Forms.Label(); this.SubtitleTimer = new System.Windows.Forms.Timer(this.components); + this.HDLightsCheckBox = new System.Windows.Forms.CheckBox(); this.StatusStrip.SuspendLayout(); this.ToolsPanel.SuspendLayout(); this.ToolsTabControl.SuspendLayout(); @@ -2249,6 +2250,7 @@ namespace CodeWalker // // OptionsLightingTabPage // + this.OptionsLightingTabPage.Controls.Add(this.HDLightsCheckBox); this.OptionsLightingTabPage.Controls.Add(this.DeferredShadingCheckBox); this.OptionsLightingTabPage.Controls.Add(this.WeatherRegionComboBox); this.OptionsLightingTabPage.Controls.Add(this.label29); @@ -2304,7 +2306,7 @@ namespace CodeWalker this.WeatherRegionComboBox.Location = new System.Drawing.Point(61, 355); this.WeatherRegionComboBox.Name = "WeatherRegionComboBox"; this.WeatherRegionComboBox.Size = new System.Drawing.Size(133, 21); - this.WeatherRegionComboBox.TabIndex = 43; + this.WeatherRegionComboBox.TabIndex = 50; this.WeatherRegionComboBox.SelectedIndexChanged += new System.EventHandler(this.WeatherRegionComboBox_SelectedIndexChanged); this.WeatherRegionComboBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.WeatherRegionComboBox_KeyPress); // @@ -2314,7 +2316,7 @@ namespace CodeWalker this.label29.Location = new System.Drawing.Point(4, 358); this.label29.Name = "label29"; this.label29.Size = new System.Drawing.Size(44, 13); - this.label29.TabIndex = 64; + this.label29.TabIndex = 49; this.label29.Text = "Region:"; // // CloudParamTrackBar @@ -2327,7 +2329,7 @@ namespace CodeWalker this.CloudParamTrackBar.Maximum = 200; this.CloudParamTrackBar.Name = "CloudParamTrackBar"; this.CloudParamTrackBar.Size = new System.Drawing.Size(188, 45); - this.CloudParamTrackBar.TabIndex = 63; + this.CloudParamTrackBar.TabIndex = 55; this.CloudParamTrackBar.TickFrequency = 10; this.CloudParamTrackBar.Value = 100; this.CloudParamTrackBar.Scroll += new System.EventHandler(this.CloudParamTrackBar_Scroll); @@ -2341,7 +2343,7 @@ namespace CodeWalker this.CloudParamComboBox.Location = new System.Drawing.Point(78, 409); this.CloudParamComboBox.Name = "CloudParamComboBox"; this.CloudParamComboBox.Size = new System.Drawing.Size(116, 21); - this.CloudParamComboBox.TabIndex = 62; + this.CloudParamComboBox.TabIndex = 54; this.CloudParamComboBox.SelectedIndexChanged += new System.EventHandler(this.CloudParamComboBox_SelectedIndexChanged); this.CloudParamComboBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.CloudParamComboBox_KeyPress); // @@ -2351,7 +2353,7 @@ namespace CodeWalker this.label23.Location = new System.Drawing.Point(4, 412); this.label23.Name = "label23"; this.label23.Size = new System.Drawing.Size(69, 13); - this.label23.TabIndex = 61; + this.label23.TabIndex = 53; this.label23.Text = "Cloud param:"; // // CloudsComboBox @@ -2363,7 +2365,7 @@ namespace CodeWalker this.CloudsComboBox.Location = new System.Drawing.Point(61, 382); this.CloudsComboBox.Name = "CloudsComboBox"; this.CloudsComboBox.Size = new System.Drawing.Size(133, 21); - this.CloudsComboBox.TabIndex = 60; + this.CloudsComboBox.TabIndex = 52; this.CloudsComboBox.SelectedIndexChanged += new System.EventHandler(this.CloudsComboBox_SelectedIndexChanged); this.CloudsComboBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.CloudsComboBox_KeyPress); // @@ -2373,7 +2375,7 @@ namespace CodeWalker this.label21.Location = new System.Drawing.Point(4, 385); this.label21.Name = "label21"; this.label21.Size = new System.Drawing.Size(42, 13); - this.label21.TabIndex = 59; + this.label21.TabIndex = 51; this.label21.Text = "Clouds:"; // // TimeSpeedLabel @@ -2382,7 +2384,7 @@ namespace CodeWalker this.TimeSpeedLabel.Location = new System.Drawing.Point(78, 263); this.TimeSpeedLabel.Name = "TimeSpeedLabel"; this.TimeSpeedLabel.Size = new System.Drawing.Size(63, 13); - this.TimeSpeedLabel.TabIndex = 58; + this.TimeSpeedLabel.TabIndex = 44; this.TimeSpeedLabel.Text = "0.5 min/sec"; // // label20 @@ -2391,7 +2393,7 @@ namespace CodeWalker this.label20.Location = new System.Drawing.Point(3, 263); this.label20.Name = "label20"; this.label20.Size = new System.Drawing.Size(65, 13); - this.label20.TabIndex = 57; + this.label20.TabIndex = 43; this.label20.Text = "Time speed:"; // // TimeSpeedTrackBar @@ -2404,7 +2406,7 @@ namespace CodeWalker this.TimeSpeedTrackBar.Minimum = 40; this.TimeSpeedTrackBar.Name = "TimeSpeedTrackBar"; this.TimeSpeedTrackBar.Size = new System.Drawing.Size(133, 45); - this.TimeSpeedTrackBar.TabIndex = 41; + this.TimeSpeedTrackBar.TabIndex = 46; this.TimeSpeedTrackBar.TickFrequency = 5; this.TimeSpeedTrackBar.Value = 50; this.TimeSpeedTrackBar.Scroll += new System.EventHandler(this.TimeSpeedTrackBar_Scroll); @@ -2414,7 +2416,7 @@ namespace CodeWalker this.TimeStartStopButton.Location = new System.Drawing.Point(10, 279); this.TimeStartStopButton.Name = "TimeStartStopButton"; this.TimeStartStopButton.Size = new System.Drawing.Size(45, 23); - this.TimeStartStopButton.TabIndex = 40; + this.TimeStartStopButton.TabIndex = 45; this.TimeStartStopButton.Text = "Start"; this.TimeStartStopButton.UseVisualStyleBackColor = true; this.TimeStartStopButton.Click += new System.EventHandler(this.TimeStartStopButton_Click); @@ -2427,7 +2429,7 @@ namespace CodeWalker this.ArtificialAmbientLightCheckBox.Location = new System.Drawing.Point(10, 137); this.ArtificialAmbientLightCheckBox.Name = "ArtificialAmbientLightCheckBox"; this.ArtificialAmbientLightCheckBox.Size = new System.Drawing.Size(124, 17); - this.ArtificialAmbientLightCheckBox.TabIndex = 36; + this.ArtificialAmbientLightCheckBox.TabIndex = 37; this.ArtificialAmbientLightCheckBox.Text = "Artificial ambient light"; this.ArtificialAmbientLightCheckBox.UseVisualStyleBackColor = true; this.ArtificialAmbientLightCheckBox.CheckedChanged += new System.EventHandler(this.ArtificialAmbientLightCheckBox_CheckedChanged); @@ -2440,7 +2442,7 @@ namespace CodeWalker this.NaturalAmbientLightCheckBox.Location = new System.Drawing.Point(10, 115); this.NaturalAmbientLightCheckBox.Name = "NaturalAmbientLightCheckBox"; this.NaturalAmbientLightCheckBox.Size = new System.Drawing.Size(122, 17); - this.NaturalAmbientLightCheckBox.TabIndex = 35; + this.NaturalAmbientLightCheckBox.TabIndex = 36; this.NaturalAmbientLightCheckBox.Text = "Natural ambient light"; this.NaturalAmbientLightCheckBox.UseVisualStyleBackColor = true; this.NaturalAmbientLightCheckBox.CheckedChanged += new System.EventHandler(this.NaturalAmbientLightCheckBox_CheckedChanged); @@ -2450,10 +2452,10 @@ namespace CodeWalker this.LODLightsCheckBox.AutoSize = true; this.LODLightsCheckBox.Checked = true; this.LODLightsCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; - this.LODLightsCheckBox.Location = new System.Drawing.Point(10, 93); + this.LODLightsCheckBox.Location = new System.Drawing.Point(89, 93); this.LODLightsCheckBox.Name = "LODLightsCheckBox"; this.LODLightsCheckBox.Size = new System.Drawing.Size(75, 17); - this.LODLightsCheckBox.TabIndex = 34; + this.LODLightsCheckBox.TabIndex = 35; this.LODLightsCheckBox.Text = "LOD lights"; this.LODLightsCheckBox.UseVisualStyleBackColor = true; this.LODLightsCheckBox.CheckedChanged += new System.EventHandler(this.LODLightsCheckBox_CheckedChanged); @@ -2479,7 +2481,7 @@ namespace CodeWalker this.ControlTimeOfDayCheckBox.Location = new System.Drawing.Point(10, 181); this.ControlTimeOfDayCheckBox.Name = "ControlTimeOfDayCheckBox"; this.ControlTimeOfDayCheckBox.Size = new System.Drawing.Size(166, 17); - this.ControlTimeOfDayCheckBox.TabIndex = 38; + this.ControlTimeOfDayCheckBox.TabIndex = 39; this.ControlTimeOfDayCheckBox.Text = "Control time of day (right-drag)"; this.ControlTimeOfDayCheckBox.UseVisualStyleBackColor = true; this.ControlTimeOfDayCheckBox.CheckedChanged += new System.EventHandler(this.ControlTimeOfDayCheckBox_CheckedChanged); @@ -2490,7 +2492,7 @@ namespace CodeWalker this.TimeOfDayLabel.Location = new System.Drawing.Point(75, 208); this.TimeOfDayLabel.Name = "TimeOfDayLabel"; this.TimeOfDayLabel.Size = new System.Drawing.Size(34, 13); - this.TimeOfDayLabel.TabIndex = 54; + this.TimeOfDayLabel.TabIndex = 41; this.TimeOfDayLabel.Text = "12:00"; // // label19 @@ -2499,7 +2501,7 @@ namespace CodeWalker this.label19.Location = new System.Drawing.Point(4, 208); this.label19.Name = "label19"; this.label19.Size = new System.Drawing.Size(65, 13); - this.label19.TabIndex = 53; + this.label19.TabIndex = 40; this.label19.Text = "Time of day:"; // // TimeOfDayTrackBar @@ -2512,7 +2514,7 @@ namespace CodeWalker this.TimeOfDayTrackBar.Maximum = 1440; this.TimeOfDayTrackBar.Name = "TimeOfDayTrackBar"; this.TimeOfDayTrackBar.Size = new System.Drawing.Size(188, 45); - this.TimeOfDayTrackBar.TabIndex = 39; + this.TimeOfDayTrackBar.TabIndex = 42; this.TimeOfDayTrackBar.TickFrequency = 60; this.TimeOfDayTrackBar.Value = 720; this.TimeOfDayTrackBar.Scroll += new System.EventHandler(this.TimeOfDayTrackBar_Scroll); @@ -2526,7 +2528,7 @@ namespace CodeWalker this.WeatherComboBox.Location = new System.Drawing.Point(61, 328); this.WeatherComboBox.Name = "WeatherComboBox"; this.WeatherComboBox.Size = new System.Drawing.Size(133, 21); - this.WeatherComboBox.TabIndex = 42; + this.WeatherComboBox.TabIndex = 48; this.WeatherComboBox.SelectedIndexChanged += new System.EventHandler(this.WeatherComboBox_SelectedIndexChanged); this.WeatherComboBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.WeatherComboBox_KeyPress); // @@ -2536,7 +2538,7 @@ namespace CodeWalker this.label17.Location = new System.Drawing.Point(4, 331); this.label17.Name = "label17"; this.label17.Size = new System.Drawing.Size(51, 13); - this.label17.TabIndex = 39; + this.label17.TabIndex = 47; this.label17.Text = "Weather:"; // // ControlLightDirectionCheckBox @@ -2545,7 +2547,7 @@ namespace CodeWalker this.ControlLightDirectionCheckBox.Location = new System.Drawing.Point(10, 159); this.ControlLightDirectionCheckBox.Name = "ControlLightDirectionCheckBox"; this.ControlLightDirectionCheckBox.Size = new System.Drawing.Size(177, 17); - this.ControlLightDirectionCheckBox.TabIndex = 37; + this.ControlLightDirectionCheckBox.TabIndex = 38; this.ControlLightDirectionCheckBox.Text = "Control light direction (right-drag)"; this.ControlLightDirectionCheckBox.UseVisualStyleBackColor = true; this.ControlLightDirectionCheckBox.CheckedChanged += new System.EventHandler(this.ControlLightDirectionCheckBox_CheckedChanged); @@ -3590,6 +3592,19 @@ namespace CodeWalker // this.SubtitleTimer.Tick += new System.EventHandler(this.SubtitleTimer_Tick); // + // HDLightsCheckBox + // + this.HDLightsCheckBox.AutoSize = true; + this.HDLightsCheckBox.Checked = true; + this.HDLightsCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.HDLightsCheckBox.Location = new System.Drawing.Point(10, 93); + this.HDLightsCheckBox.Name = "HDLightsCheckBox"; + this.HDLightsCheckBox.Size = new System.Drawing.Size(69, 17); + this.HDLightsCheckBox.TabIndex = 34; + this.HDLightsCheckBox.Text = "HD lights"; + this.HDLightsCheckBox.UseVisualStyleBackColor = true; + this.HDLightsCheckBox.CheckedChanged += new System.EventHandler(this.HDLightsCheckBox_CheckedChanged); + // // WorldForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -3962,5 +3977,6 @@ namespace CodeWalker private System.Windows.Forms.ToolStripMenuItem ToolbarRotationSnapping45Button; private System.Windows.Forms.ToolStripMenuItem ToolbarRotationSnapping90Button; private System.Windows.Forms.ToolStripMenuItem ToolbarSnapGridSizeButton; + private System.Windows.Forms.CheckBox HDLightsCheckBox; } } \ No newline at end of file diff --git a/CodeWalker/WorldForm.cs b/CodeWalker/WorldForm.cs index dd35c56..acbb530 100644 --- a/CodeWalker/WorldForm.cs +++ b/CodeWalker/WorldForm.cs @@ -7013,6 +7013,11 @@ namespace CodeWalker //Monitor.Exit(rendersyncroot); } + private void HDLightsCheckBox_CheckedChanged(object sender, EventArgs e) + { + Renderer.renderlights = HDLightsCheckBox.Checked; + } + private void LODLightsCheckBox_CheckedChanged(object sender, EventArgs e) { Renderer.renderdistlodlights = LODLightsCheckBox.Checked; diff --git a/CodeWalker/WorldForm.resx b/CodeWalker/WorldForm.resx index 70dd9c9..1ea334c 100644 --- a/CodeWalker/WorldForm.resx +++ b/CodeWalker/WorldForm.resx @@ -240,6 +240,14 @@ ufo YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAB4SURBVDhP3ZC7DcAgDEQZKTMwHOvSIFriS7BlEB+HMic9 QJbvFThLUkpXzjkSpaeuzMPlEELx3jdsBauyCHBY6UWYPQI93KEljQD3jL6EGzN6x0bASyNYwkKU8Udm gd6TMnIikDJyIqjVNz8T7FgKrAwFX6lVinM3aJ05lWDPRRcAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAB0SURBVDhP7ZNBCoAgEEXnSJ3BqxmetNpaMLhVv5DNRJS2 + CxIeuvA9XSjtg5mHEILPxB6U7JyLxphmSkDK1o5x9dst87SUfTXwRsYsA+paT0BGDGsVOJ92hdz3Bz4f + wGPC48uu7w5IGd+gBlpRMgYCnRwyESUj3CsQkYNFDwAAAABJRU5ErkJggg== @@ -261,12 +269,13 @@ ufo WBXYx9R1nV75RuyHKrrnzCcGjE1u9ZyD4BugoZigQ9xrngAAAABJRU5ErkJggg== - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAB0SURBVDhP7ZNBCoAgEEXnSJ3BqxmetNpaMLhVv5DNRJS2 - CxIeuvA9XSjtg5mHEILPxB6U7JyLxphmSkDK1o5x9dst87SUfTXwRsYsA+paT0BGDGsVOJ92hdz3Bz4f - wGPC48uu7w5IGd+gBlpRMgYCnRwyESUj3CsQkYNFDwAAAABJRU5ErkJggg== + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACtSURBVDhPrZBBEsIgEAR5Gy/wFV55T/wHr+KgHuCKNsVY + ZI2JiU7VVIVlp7OL+1mllIr7cb8Ie++PQwQYITnnM24NWxoBgsQYm/l+gk699bMsRA4h1JTSPsg0Xert + em/mGwh3vW1Z7MvIABSWqXG3+iZHAEw1m4wD49oVANgVOL/VeSgeDAiX1mpWeKy9BIQiI+OxWQF77tG5 + 2Fc729BmeElf/3lNhORe+oecewDObEqX49RqCgAAAABJRU5ErkJggg== @@ -295,15 +304,6 @@ ufo EcMw2DzPDMEke9AsYBrHs10vN4I1QqImwwDcFyMjQGaBHr5Bo8nEoYCnCQTGzVeI4oj6fIi+KHgoPBhC 4knCjTww9vxfbIUQNDEyiGIZ8t6tW/k0vC/AOpuiueNOLwVkUeylvju9FJCg8E1vM/2PlTv5UoervVTJ uQAAAABJRU5ErkJggg== - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACtSURBVDhPrZBBEsIgEAR5Gy/wFV55T/wHr+KgHuCKNsVY - ZI2JiU7VVIVlp7OL+1mllIr7cb8Ie++PQwQYITnnM24NWxoBgsQYm/l+gk699bMsRA4h1JTSPsg0Xert - em/mGwh3vW1Z7MvIABSWqXG3+iZHAEw1m4wD49oVANgVOL/VeSgeDAiX1mpWeKy9BIQiI+OxWQF77tG5 - 2Fc729BmeElf/3lNhORe+oecewDObEqX49RqCgAAAABJRU5ErkJggg== @@ -389,6 +389,17 @@ ufo 4BJN+IjGo5O8ZJndGVhKxpjWWts551aih0fre+0BLaVchRAezPB2NXSSV/gVwXGYPJiVUt6ns1ghCDjn UQG86w3FToVgDcWCWS9Fvi/Ao0RVAcwUjwpyhzmf4n8BFApS5HZRwRuONGMbrIJ1JIN8O2QAAAAASUVO RK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEvSURBVDhP3dK/K0dRGMfxKxRJopCSEkLya/guUhQRmQwG + WfwIkYySgYUSKUKJlOK/MBoMFMofYLUIsfJ+f3NuF3+A8tRree5zP/fcc070f6oHT/jAPTqQj6WvXvCM + TZQgG3H58gFGcYVLtGIN15jBNDbwiGNUIg4pQx8GsQuHhrCDW8yjHyns4Q0DcCXpykM5bFzgHGPYxw1G + UIVMtMHfWUUj4nIg/KurGIYrSAZYOXDGlbhXcZlegUO8Yxzb+BlQAwNW0G0jVAYK0AwHtnCEOyQDZvGC + ObTbKIIvLMA9WIYDizhFMsDjfsAZptCA9JcdfoVBvryOSbgCe4HPTuCz+BQMKEUvJmCy96ET1ehCuAf2 + 5ZF+uwdZKEYtmuBGFSIXhtejBe5PHX7dxL+qKPoEppRHcXOtiDsAAAAASUVORK5CYII= @@ -424,17 +435,6 @@ ufo rp3fhGJScIRLzKMLFTC9cMIu3nCDVUyjB6WkYA93mEWbAyH9cMImPuA+rWMA31YwBU82kF6BS32Er/aO M8zAh+OEghpcwQ2bg3uwBW8ewFd7xQkm0IA4oaAS7bh2KHjBIZbhV/D6GJkFphrdcIP8lFrAGPwPOjCO QdQiTqrAWNICd7gPnUj+xBKaU9dxfhTkjwV/FxU+AbsiGnc46OYIAAAAAElFTkSuQmCC - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEvSURBVDhP3dK/K0dRGMfxKxRJopCSEkLya/guUhQRmQwG - WfwIkYySgYUSKUKJlOK/MBoMFMofYLUIsfJ+f3NuF3+A8tRree5zP/fcc070f6oHT/jAPTqQj6WvXvCM - TZQgG3H58gFGcYVLtGIN15jBNDbwiGNUIg4pQx8GsQuHhrCDW8yjHyns4Q0DcCXpykM5bFzgHGPYxw1G - UIVMtMHfWUUj4nIg/KurGIYrSAZYOXDGlbhXcZlegUO8Yxzb+BlQAwNW0G0jVAYK0AwHtnCEOyQDZvGC - ObTbKIIvLMA9WIYDizhFMsDjfsAZptCA9JcdfoVBvryOSbgCe4HPTuCz+BQMKEUvJmCy96ET1ehCuAf2 - 5ZF+uwdZKEYtmuBGFSIXhtejBe5PHX7dxL+qKPoEppRHcXOtiDsAAAAASUVORK5CYII= diff --git a/Shaders/LightPS.cso b/Shaders/LightPS.cso index 2447c69f66e0c0f7b94b91882a1d89e93a8ecfee..0f0d80f9ab65c75d15dc66216416ef4e862f8ac4 100644 GIT binary patch delta 792 zcmZWnJxjx25Wd*fG=(-vLw%(m^ux_TF$ii@`k|uTEL3su2e>#0j)H9wT$P(Uhzc$u zQgPPNK`7$puW%3@y-V|^wFZvMeLc^UyPQpTr|i|8%1XU{YrlTm%{}qBaCvwAsQ|#H z00@zvCHonrSOqvCdmp>Ew^eOJ2PjeLt#htEs6l{m0jqi{HxHo3!2rrYWXRi;!XrJM zP*8ZB7zn^$E}1X zU6buD4VF!-oFNeTkxnBABYhATW09^=7!pY>K9YlNGZk{B;)Q8p*EAHD(_~J_4M@bA zZfP-3w1WBgc$k9TXw(w!30a^*bM!rbynDhWE4?;&LfI@AB!_shT=SOU193dZ+Hu(w zTN2654AAigB+_7y{JWSj9N@-;L1ju$h&m+8=ARdSm?g%5q JT`KO2iC-_0R5<_u delta 906 zcmZWoJxc>Y5S=rLmjpC-7iFV|#1BLX#9;i6h#Ex^5wsBtEi43EA*Emp7B)&`|AH2l z68!-d7GmRXu&}qY^i8sJ9Pwap_vX!e^JbR&oTwLy>j&kv+IVH7d+PW3`{n%XH4_0+eMLTNTPt``b$J_H!AmBuh|*k- z?dSB7lXc~b9krr2j@tPbh5jWtqJQ7@z6|g7uwjY5sGv?luzvmH_(NsmfSs-yC7fG| zP%7)av^rs)WQvw(OZEV|uNkJyihT*bh`zZt$ApVxpqtZ=u5Wqz%^e$+TEdl@gj)+R z?Ru(tb1|JyWi9}P#?x$u2Pb2fYv!29$u);#Vm-KKSPtVn-oS!shxKMSX%79ciExk7 zgBbDPsoTuTV&`!{_Sqh5_t}mIR&-a|&&-B~-!ekf3nPuw jbR{x$iy8?mej-@MX6G}0B#P-t3n+V*X)>)UTsz|GFL2y8#A_p!Y!l^20 zV_SuLG)IIKq#ik7oI_8D9DCr<1NT;3;ZVV$91zU+yr0?He_<^>kKeqRZ|2SW^z_C@ zU(Fr&=UQ*S-@UwiwfFU(fB$;B@$fJ5nH{jM@5?3 zo_rL}pQGk2Ek84+wT77>SvxrleffNUUXD8}@^k3QZr5F9ToY&wnWY|zFS}l)qlN9p zi7A9lJ*&7ZDGC55=nx_)?YTYh);^^%&W*;5N+$xbE(F5-&BQ*qH@lxiBDBfMQ?I;) z8R^uJ=yk6Eyo@GWmv4*y=(IeAVg463WJs zVW(`#^w*8E85^w#TN8|FG`4wE^X0f+(TSx|L28koY0J~QRoRKwu1qrn2{f3LO3cX& z3mEHg`k32Omv=jUkx1mhyhQ8eSI7g{0+$$+z(=v_QVjjk@#NS!r1>fy)e=XWA?((7wFL!A36tG z8@%w*QtM;a_Fc-LnZ64;Jcg4JeHVO_I==An%I8y=?HKLiSk_N=Z?|n%U6=1(^Ch^H zub>&x#vYA}?X2;eP}*7F@m3j_R(-Wtki+Z#1*8KlQhjbU#<;if!B0u=iJjd1(ob}9 zPjrTk5Dk$dwHy9HJ%Jb@o(|2>O5K=~ShqUssWxbexW;Jc5R(3Ak-D*t1w_X{d~K0l z%nf1#I_vrbxFmb~zJ$y9j3bXa>um-k0FyDn`2P@=h8tmd<%fDrTNc}|>9&(C)B$aH znn;ki*cj$$p%|Mw=71K7Yup3Zh|M-i3u>_;V;uP=Dr~Xo;(D@($OU>Gw)rQ^V1qTt t(e~ZP+1j?Is{ahxPgcKwQ?dpsU)Hg%Bb5H2ET0VA+-03zkUN9*{{TStB>4aU delta 5065 zcmeHLO=ufO6rR=ZN=?H`D`#!XVzo}(rVgopaBJ1AD@zHO;Fu^ml;lu|PQ5gcKn`~5 zP)T(TIrQK@3O(9TdMmAQ&jsIl>7md|Zw~Yj2rW4Tl0ZZ9zS((VYYc%9-`21@v-AGG zH}h#cZ+__}Ht!^+&t7hxS?xXe)_?ZfACEsfdF|h)kAJe1Qky-c(%jDQ^CY8GE34Ex zKPP(I)1PE>-`!HG!J;2_HnNj;wW{o*aumx|UO62|(6<)&r8@Nq+HD-O>~EYAYlyop zEjYD;uTsfzW8^4hH|e(HS9)fIC7oS1j=EW*scDz4wo*9+vspS$e>pxqI_;F8-;L<6 z&s_PH9-b~)<1|(9(xWgS>$v;ov{E_!#md8Utxyh{k&uF1fLV;7Nx!>Z8g@-;yWXS z(F-Jfculf`L}#>GyGY%o^56u=7ftb1W6b3EBbSE`7H0c_3}7*wW#F>Jl8huO%Ut9Y zr_Ew8!+?7N&CmfbMGwFta-Bkrwu%LUY>7S z=SvNLvClh9ZOFSD@A^4J3>nov?`am|3z?$j#m^)A9QVg*d)_a|7v?7%y*KY2Fxsek zW1~h#yorra5%$B>o(QR^QJ7gXeT^Zc;_j43Bg;1394*ab{-Gg6L|>>NM8ud7QOk{u zqISWh`^zOJ-^Cy#ALQawFbes!jJlJarc{o)9}QM9^CmS`*S~tC(qCrUn0Es(E~2F; zOF-)77A;M^gCOX|r|!qD1F3k|WcxV?Y(usbZPmR2p%&7|bfc}&c2K5=^;AWu6_pCL zY-%r*spT7LZC+SO?tK2%xopg@m|xf&4ufB<_hNqW4>aDt4vAkgXJdZF{0a|auYLd8 zjgMaO)}_z+uboAj;2ybbz8rqOY#2Hp&|Cj)jyM+C6w#mvARK$^Ff@-kGfUwlV zv{f6(bn35AX$}cH_E(xcvex{;_apNal1(Xnp>cI>FByErMn{l0|0Vg!^Q+1&o>TnP QsNFf0UgF*qZFG*m0F_}S!vFvP diff --git a/Shaders/LodLightsPS.cso b/Shaders/LodLightsPS.cso index 2f0441f4f287bafa754c849f31ef4c7cd35cd6cf..257f251f3f8b5874a80dc90abbfe8efd5df1bb23 100644 GIT binary patch delta 509 zcmZ8eyGjF55S`1qPt<)}$i|K0CU!~;D#jp!$;K{)78W)U?fn6}5VR1)!f8aXu(A*f zN$UqFY++#|B8u4h34$~0-a;1+^FDKC??LT-w!XHNv>&h5qwSZEo44!YMzD9%6#%dk z0vKc)gmH4t2r1#I0PtD3t)CkaZF@nz17k9Z?l14ZW~v;R8-LROLm0_Od^V~>UTth`+i4Hm=quU1)<}& zU-NaULkw1sFLUtHm8WtdCRv>0Itl5u$nv>rcLRl#i!70|ERAKeuX0g7ttOOOfvpi) z=0nv^HQ~?%AHGCv0lo&4HhUQ_9?4QuMcl)^e4Cn49Hb!of&3)XIiKns+{sO?d`y*L Z0)NcZC1?bCh%DA{E}YRhGI2MY`T-tsK~Vqz delta 565 zcmZuuJxc>Y5S`0?P z_LBc#C0Hrg`7QW`QF{VV84IoV89LZ^#ydY_kyx#!W+t|&$3P%su0P>_> zt$z*gXtBKlX-J8Yl+uuLOjgtdV@o{_x-^QDYja5ApwaGn3?qj&4FDhf$(ihbN?S(O)$SM(Bai+r@ z9!&h8pVZr@_*sT7WQcU?V#kM|^JUcYnfrw0C1h}W zD>3Mfx7}I?mB(E&c&G#rR5@AMzYi(|zjPzx?eItOU$ktaLSg=u@g7NdyV$nrwG%>kgXC5SuiwTb+Eko3 zJjUzyF{-!vS)CXb-s@He4|K!i8HwAqs5ED8E1eOK^^5C`koAZ%7^M||IGOJQ+$jLu UAjy!NLw)mtdX;9EF~2$a8|F!)h5!Hn delta 3497 zcmeHKL2DCH5S~r4$-WJ=o88qWjUlNO1q&vjl2)m>*%TD2(i8-b7U~Zucu+8HDn^PZ z7)C+FgP`8L#Ck2X(2Gz|@u1#v@Zi;}AULzTFAdS+(Hs(ZJCirxdoypoedNo|z0kM& zq0;OXw=y$vGAkzII}abdyYcz)Qd0qdrMm!8vePsUk@JMcE{!h@fbWe~>1k9%RsqTs z-ro2ceWmHo9RPpe`fwwc1MM~#pb_9S7IT^3f#rI8=VaZfeehf<W!h~hba6Bm1YhjqMvW4t-T1W|beGvC78kUWYrOk6Sy}?dGe?y1_wtLf3 zuugOm0UV&58-{%}-p#R-ZD;|<0+%n1oZ^0QMqbGrvX%U@&wUEs1}`Qn6u6zQbU2Qq zQecih7JQE5v{J`4hdC}6eU5c(7ANs#(ZH+aoZwdZESFsix3cPNKr#m;$?S(5dhA0o z$C)3t9?7^pW}V@3C9S;(rnP%cvL>4>aM4Xim{lxPGqP0?Y#ko4Wve6sY_VOo(Qvhl z>`QlWZ_~s=8l9XS@i=L_=ffMuu{W^+F?-bY4KdG317f=GRDTfjQy*NGKD;b%FApwD z|6LaPd2y}{i0MmWcCYsma|B=CTAT_*nL?UEsz&yERbvnbwyb#YLM_7Ig