From 98582e13949a6a5d359b912f859ee0cd3761d192 Mon Sep 17 00:00:00 2001 From: codeimp Date: Wed, 1 Sep 2010 20:08:07 +0000 Subject: [PATCH] Started GZDoom Editing plugin project --- Builder.sln | 12 ++ Resources/Icons/VisualModeZ.png | Bin 0 -> 905 bytes .../GZDoomEditing/GZDoomEditing.csproj | 73 ++++++++ .../GZDoomEditing/General/BuilderPlug.cs | 171 ++++++++++++++++++ .../GZDoomEditing/Properties/AssemblyInfo.cs | 36 ++++ .../Properties/Resources.Designer.cs | 70 +++++++ .../GZDoomEditing/Properties/Resources.resx | 124 +++++++++++++ .../GZDoomEditing/Resources/VisualModeZ.png | Bin 0 -> 905 bytes Tests/UDMF/udmfexample.wad | Bin 9165 -> 12243 bytes 9 files changed, 486 insertions(+) create mode 100644 Resources/Icons/VisualModeZ.png create mode 100644 Source/Plugins/GZDoomEditing/GZDoomEditing.csproj create mode 100644 Source/Plugins/GZDoomEditing/General/BuilderPlug.cs create mode 100644 Source/Plugins/GZDoomEditing/Properties/AssemblyInfo.cs create mode 100644 Source/Plugins/GZDoomEditing/Properties/Resources.Designer.cs create mode 100644 Source/Plugins/GZDoomEditing/Properties/Resources.resx create mode 100644 Source/Plugins/GZDoomEditing/Resources/VisualModeZ.png diff --git a/Builder.sln b/Builder.sln index 4f719e97..4aa67ef0 100644 --- a/Builder.sln +++ b/Builder.sln @@ -19,6 +19,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "USDF", "Source\Plugins\USDF EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TagRange", "Source\Plugins\TagRange\TagRange.csproj", "{F49EFF6D-51CB-4E49-8223-AAE653C5B62F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GZDoomEditing", "Source\Plugins\GZDoomEditing\GZDoomEditing.csproj", "{760A9BC7-CB73-4C36-858B-994C14996FCD}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -116,6 +118,16 @@ Global {F49EFF6D-51CB-4E49-8223-AAE653C5B62F}.Release|Mixed Platforms.Build.0 = Release|x86 {F49EFF6D-51CB-4E49-8223-AAE653C5B62F}.Release|x86.ActiveCfg = Release|x86 {F49EFF6D-51CB-4E49-8223-AAE653C5B62F}.Release|x86.Build.0 = Release|x86 + {760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|Any CPU.ActiveCfg = Debug|x86 + {760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|x86.ActiveCfg = Debug|x86 + {760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|x86.Build.0 = Debug|x86 + {760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|Any CPU.ActiveCfg = Release|x86 + {760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|Mixed Platforms.Build.0 = Release|x86 + {760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|x86.ActiveCfg = Release|x86 + {760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Resources/Icons/VisualModeZ.png b/Resources/Icons/VisualModeZ.png new file mode 100644 index 0000000000000000000000000000000000000000..110541d8b3274e0f3d18c15a4d852f4a49e69a01 GIT binary patch literal 905 zcmV;419tq0P)#Y$?vwQ0^kAqP#goz&j|er>kP~8yD2IXL zlR(Lk)fNz|2X&H|bZBJR7CVQbxbGz)GW{epw}B>#Fll)a*{Hn-AJrZB(}Jl^PTwZC$aMn8b8XiF8n}&0g&`qv2Wn*-n82D&fI2V`$I%)CLw9Nh2D3-QPT@_ zP5~>0Q7K%4hrAO$r4v}ScLXlUT^PMM1ht0;D)ZzP?o3*WY)w;=RYFmu7Zu}25l-<} z@4w;j=enTvrcGq2adsUOR$!dBiaT6f;g#cu1k?a}{fsL1FsVQ)HUkM)!CN zb7zH_!5pc~FvBl0eTZYpnf*W^y+S2dfXb^twV8r;thx*wpz%@~Q=7jcR-uh#)3Mz- zn#w^zq0G!gb#^wY)6>yXuU_;(P;s3Srx959 z0Ba82hIjD|>~1um;;;rsTD#DD=@QO#orYE*KslXLEOk3SK7R30C{1%>?_ERiJ8% + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {760A9BC7-CB73-4C36-858B-994C14996FCD} + Library + Properties + CodeImp.DoomBuilder.GZDoomEditing + GZDoomEditing + v3.5 + 512 + + + true + ..\..\..\Build\Plugins\ + DEBUG;TRACE + full + x86 + prompt + + + ..\..\..\Build\Plugins\ + + + true + pdbonly + x86 + prompt + + + + + 3.5 + + + + + + + + + True + True + Resources.resx + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + {818B3D10-F791-4C3F-9AF5-BB2D0079B63C} + Builder + + + + + + + + \ No newline at end of file diff --git a/Source/Plugins/GZDoomEditing/General/BuilderPlug.cs b/Source/Plugins/GZDoomEditing/General/BuilderPlug.cs new file mode 100644 index 00000000..ae77bdda --- /dev/null +++ b/Source/Plugins/GZDoomEditing/General/BuilderPlug.cs @@ -0,0 +1,171 @@ + +#region ================== Copyright (c) 2010 Pascal vd Heiden + +/* + * Copyright (c) 2010 Pascal vd Heiden + * This program is released under GNU General Public License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#endregion + +#region ================== Namespaces + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Globalization; +using System.Text; +using System.Windows.Forms; +using System.IO; +using System.Reflection; +using CodeImp.DoomBuilder.Controls; +using CodeImp.DoomBuilder.Windows; +using CodeImp.DoomBuilder.IO; +using CodeImp.DoomBuilder.Map; +using CodeImp.DoomBuilder.Rendering; +using CodeImp.DoomBuilder.Geometry; +using System.Drawing; +using CodeImp.DoomBuilder.Editing; +using CodeImp.DoomBuilder.Plugins; +using CodeImp.DoomBuilder.Actions; +using CodeImp.DoomBuilder.Types; +using CodeImp.DoomBuilder.Config; +using CodeImp.DoomBuilder.Data; + +#endregion + +namespace CodeImp.DoomBuilder.GZDoomEditing +{ + public class BuilderPlug : Plug + { + #region ================== Variables + + // Static instance + private static BuilderPlug me; + + #endregion + + #region ================== Properties + + // Static property to access the BuilderPlug + public static BuilderPlug Me { get { return me; } } + + #endregion + + #region ================== Initialize / Dispose + + // This event is called when the plugin is initialized + public override void OnInitialize() + { + base.OnInitialize(); + + // Keep a static reference + me = this; + } + + // This is called when the plugin is terminated + public override void Dispose() + { + base.Dispose(); + } + + #endregion + + #region ================== Classic Mode Surfaces + + // This is called when the vertices are created for the classic mode surfaces + public override void OnSectorFloorSurfaceUpdate(Sector s, ref FlatVertex[] vertices) + { + ImageData img = General.Map.Data.GetFlatImage(s.LongFloorTexture); + if((img != null) && img.IsImageLoaded) + { + float xpan, ypan, xscale, yscale, rotate; + int color, light; + bool absolute; + + try + { + // Fetch ZDoom fields + xpan = s.Fields.ContainsKey("xpanningfloor") ? (float)s.Fields["xpanningfloor"].Value : 0.0f; + ypan = s.Fields.ContainsKey("ypanningfloor") ? (float)s.Fields["ypanningfloor"].Value : 0.0f; + xscale = s.Fields.ContainsKey("xscalefloor") ? (float)s.Fields["xscalefloor"].Value : 1.0f; + yscale = s.Fields.ContainsKey("yscalefloor") ? (float)s.Fields["yscalefloor"].Value : 1.0f; + rotate = s.Fields.ContainsKey("rotationfloor") ? (float)s.Fields["rotationfloor"].Value : 0.0f; + color = s.Fields.ContainsKey("lightcolor") ? (int)s.Fields["lightcolor"].Value : -1; + light = s.Fields.ContainsKey("lightfloor") ? (int)s.Fields["lightfloor"].Value : 0; + absolute = s.Fields.ContainsKey("lightfloorabsolute") ? (bool)s.Fields["lightfloorabsolute"].Value : false; + } + catch(Exception) { return; } + + // Setup the vertices with the given settings + SetupSurfaceVertices(vertices, s, img, xpan, ypan, xscale, yscale, rotate, color, light, absolute); + } + } + + // This is called when the vertices are created for the classic mode surfaces + public override void OnSectorCeilingSurfaceUpdate(Sector s, ref FlatVertex[] vertices) + { + ImageData img = General.Map.Data.GetFlatImage(s.LongFloorTexture); + if((img != null) && img.IsImageLoaded) + { + float xpan, ypan, xscale, yscale, rotate; + int color, light; + bool absolute; + + try + { + // Fetch ZDoom fields + xpan = s.Fields.ContainsKey("xpanningceiling") ? (float)s.Fields["xpanningceiling"].Value : 0.0f; + ypan = s.Fields.ContainsKey("ypanningceiling") ? (float)s.Fields["ypanningceiling"].Value : 0.0f; + xscale = s.Fields.ContainsKey("xscaleceiling") ? (float)s.Fields["xscaleceiling"].Value : 1.0f; + yscale = s.Fields.ContainsKey("yscaleceiling") ? (float)s.Fields["yscaleceiling"].Value : 1.0f; + rotate = s.Fields.ContainsKey("rotationceiling") ? (float)s.Fields["rotationceiling"].Value : 0.0f; + color = s.Fields.ContainsKey("lightcolor") ? (int)s.Fields["lightcolor"].Value : -1; + light = s.Fields.ContainsKey("lightceiling") ? (int)s.Fields["lightceiling"].Value : 0; + absolute = s.Fields.ContainsKey("lightceilingabsolute") ? (bool)s.Fields["lightceilingabsolute"].Value : false; + } + catch(Exception) { return; } + + // Setup the vertices with the given settings + SetupSurfaceVertices(vertices, s, img, xpan, ypan, xscale, yscale, rotate, color, light, absolute); + } + } + + // This applies the given values on the vertices + private void SetupSurfaceVertices(FlatVertex[] vertices, Sector s, ImageData img, float xpan, float ypan, + float xscale, float yscale, float rotate, int color, int light, bool absolute) + { + // Prepare for math! + rotate = Angle2D.DegToRad(rotate); + Vector2D scale = new Vector2D(xscale, yscale); + Vector2D texscale = new Vector2D(1.0f / img.ScaledWidth, 1.0f / img.ScaledHeight); + Vector2D offset = new Vector2D(xpan, ypan); + if(!absolute) light = s.Brightness + light; + PixelColor lightcolor = PixelColor.FromInt(color); + PixelColor brightness = PixelColor.FromInt(General.Map.Renderer2D.CalculateBrightness(light)); + PixelColor finalcolor = PixelColor.Modulate(lightcolor, brightness); + color = finalcolor.WithAlpha(255).ToInt(); + + // Do the math for all vertices + for(int i = 0; i < vertices.Length; i++) + { + Vector2D pos = new Vector2D(vertices[i].x, vertices[i].y); + pos = pos.GetRotated(rotate); + pos.y = -pos.y; + pos = (pos + offset) * scale * texscale; + vertices[i].u = pos.x; + vertices[i].v = pos.y; + vertices[i].c = color; + } + } + + #endregion + } +} diff --git a/Source/Plugins/GZDoomEditing/Properties/AssemblyInfo.cs b/Source/Plugins/GZDoomEditing/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..7d87e92f --- /dev/null +++ b/Source/Plugins/GZDoomEditing/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("GZDoomEditing")] +[assembly: AssemblyDescription("(G)ZDoom Editing Plugin")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Doom Builder")] +[assembly: AssemblyCopyright("Copyright © 2010")] +[assembly: AssemblyTrademark("CodeImp")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("954411b0-01e9-416f-9254-432cc1a02e3c")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Source/Plugins/GZDoomEditing/Properties/Resources.Designer.cs b/Source/Plugins/GZDoomEditing/Properties/Resources.Designer.cs new file mode 100644 index 00000000..289169a5 --- /dev/null +++ b/Source/Plugins/GZDoomEditing/Properties/Resources.Designer.cs @@ -0,0 +1,70 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.3615 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace CodeImp.DoomBuilder.GZDoomEditing.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CodeImp.DoomBuilder.GZDoomEditing.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + internal static System.Drawing.Bitmap VisualModeZ { + get { + object obj = ResourceManager.GetObject("VisualModeZ", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/Source/Plugins/GZDoomEditing/Properties/Resources.resx b/Source/Plugins/GZDoomEditing/Properties/Resources.resx new file mode 100644 index 00000000..e80940d6 --- /dev/null +++ b/Source/Plugins/GZDoomEditing/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\VisualModeZ.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/Source/Plugins/GZDoomEditing/Resources/VisualModeZ.png b/Source/Plugins/GZDoomEditing/Resources/VisualModeZ.png new file mode 100644 index 0000000000000000000000000000000000000000..110541d8b3274e0f3d18c15a4d852f4a49e69a01 GIT binary patch literal 905 zcmV;419tq0P)#Y$?vwQ0^kAqP#goz&j|er>kP~8yD2IXL zlR(Lk)fNz|2X&H|bZBJR7CVQbxbGz)GW{epw}B>#Fll)a*{Hn-AJrZB(}Jl^PTwZC$aMn8b8XiF8n}&0g&`qv2Wn*-n82D&fI2V`$I%)CLw9Nh2D3-QPT@_ zP5~>0Q7K%4hrAO$r4v}ScLXlUT^PMM1ht0;D)ZzP?o3*WY)w;=RYFmu7Zu}25l-<} z@4w;j=enTvrcGq2adsUOR$!dBiaT6f;g#cu1k?a}{fsL1FsVQ)HUkM)!CN zb7zH_!5pc~FvBl0eTZYpnf*W^y+S2dfXb^twV8r;thx*wpz%@~Q=7jcR-uh#)3Mz- zn#w^zq0G!gb#^wY)6>yXuU_;(P;s3Srx959 z0Ba82hIjD|>~1um;;;rsTD#DD=@QO#orYE*KslXLEOk3SK7R30C{1%>?_ERiJ8%V_WN3@GE3R?83z!OKn?tG@}@e zy*97t|G=HlWiOmKarSvnzAR@SA!7f6X869W?&{8dxMc@nOn}1e?yAbn%F6G{teT#= z@?QVkXN)m_I%Ujgup8~~4Ys28&)SQ>-5!s37f&xtZ|{t5wNIUDcNTuPa33Q}fq$~o z>6~78fQH}g*~VaWYe+rc??UIn9-qC_3;TC=hC>g})5+Z^Y5KYu=w_&!-K+^eWD09) zYdqe|#yCw+H(tVH#cw406VQ;v`wwJzU4ZXJlWBBc718BR5>!@Egv>@FXW;C3GKwbc@y+)1 zcGTV->{+ZbQ?7&rD^;ct|4i29hmv*0Tgf^SDA~k8CFx-8risSIR7rMI0;pwIN%krw zy);^C{^eBGEkp%V$*v@_`OV9PT}iH1NLG33xeZZGUn%OaQle?OSJQhLR^41JbBbEn zf#t^4uB?R}UJBW2FC1cl^1@H3rVTsL{FU5p=3LUk8EQ(n+HwlpQV=AyT-H}DoFccR z+*nN%l^4DPFG#6H!_~45Jr#?}xcSxSRol(L%SWQxZiZdnU%xUCegYK2IP`iw@8rtziam_h2s`-H3TuQN ze##BMldM4b95?_~0rb;qsD&MZ-FywoTORI=qV4Erx=-BW4u*5~JswVZSlPkgWGovv zx^E1}TX%RiPY>6aE@y$O77Nf63*1q27SP>bfuRr!L1F=WeBJ^KHdtVM!~#AOhz~t& z0frkaFlb_7Ik5n!^FF|(1`Esuu>ei+fyd}v9N=1m1!jm?fTqO)(a)Q}sv1l%Z^VS> z@GJm|^)=XFI*AR$-MUdg6bo!H!5p)0q>y?AHEP}3gE7~-T}LyfqO}Pu z#IJ%|=@h9=3^&=#xSRTk@Z=-zH8V%{QSBI%l#yogc#grIi#iCStTYqIb1e2i6^mWb zmu3!mj>%q{3^b>FX=ah<*zBcA=@oK{?FJ%w8KKjp@C!-dVW7!MM(MOjdBqw7t4&rM ztNj!szrbp?8?4BIz|tl4#V=q)^G#M9bE#~RPEsnZ+#G1K;wmqpusKzXOBHvwu{Z2R zw{DE5)A4RizWR>Q1gzS2!tf+veUfZ1+S(ZmVH5k+>4m}M7WXF750Cu(j761_dT%&* z5KZpx^Hos#&L;Z+Iv#IFqc&bLP3#Ao+}7p0e93$)WSw8d^dqf5%OV%sqU|If()AO- z=evHFqds7^EGiVhpgAvmm!o_oXORYW`Far?AuqBV1=`k1(U&9SMV6ybwpNlTr+E=D z+gzBv9u^30bx50B(Lv4EtJNfDq-}ADaevHEouz23Ybof0F#txUoh%&nZcHo z7g9M$!kN%5zzUjdx*SgFQDAV;Tzi8o$J}BI>#CkKvnTi&gxE+g|igm zN@V18{zSc6{&`12wbI!lswHP@CzZ3e^S3TSl~nSJY$(lIS5M?kotyON!IcB_6ZPuX zsp;H(nSDBsYM9dK zk>W|oBRR@BkE&p)4X>QvoN677s<<1dqJd*T37E4R{mpkTl}nkt0(5gem8K%YQ)#MA z0w)TMX`mp-`D1+Z=6*EgSNGj=xK;7T9#^oXKt|ciYg`zUfWi{Q)@_-2N=>0hYEKruQ04Oi?X&tu&k|MDr+m4%GwH;63C$fri5Flkbrg$ z3HhqFSa|9J*j1acf|MtD9j~s6c49kY!(3t!X#eNlibBNam_8e(D zwxS)pN8l^*JWofdE?PVa^}96JwJ)? z;$mWd9WxnE2h*MLD4inxO8fraU^Id!X}{M=z8Ac|zcm;}uKQ$Heo0f5?k3U?lyt{R zGw3cD4EeJKL)P25=G6qFzgda|zP(qGI5Qc4;3A>CBGNB}S1CRj&O!RqhIGhb;a7y0 z6`*k;V0uEQ)RrYvcx|OJxZF%GU#SkS3L^_l~abx!ntkxWVKeR^p2*b415`h+F zzmMxJ(KIjPv2C>}ixK+4$4}W_sNI<7ZNi?e+b7kVi`HOOMo<|nwYHZF5PMi^p&CGJO1obvuxz z`D)Vp6-xjLfJ|H$A2CV?*Kk4oTS+hAq1uu(Wto(Pvw%+2-~jBIpIZSNnfV+>F}DaH z+@vhM!)h2Eh6RsQqcMIkTDR9A08fS{n-3%zLp#R5O$!;q>4X*{vYS* zcsx4}Ie0mPK1l)lv49=JN6v5U#54G2VBb8RJ;wiSWak>5&HS;sZXV4Z&p?A1p^XiB z4=mT{@Z8Ehf*gR0SrGmz`myL8%-Fh)zDF~l8UxYzU}m8CcuxEA>_Em3Fb))B((}>m zI{wGnA@yk17C&N)lf{@HIvjb(^(X$buPp_IOdxyscd>t^LonI?^V`O3uD`#DKJynm Z{}aLZ^`*<_*00*1?o)pK(m4*Be*sG(S|k7f delta 1595 zcmaJ?&u<%55Pr|iu6Ng2+ld?7A)+{mg$i~Yd;KFe4pP!OM4;BBb)lgMH9feY5_Q@% zs#-`C-?)HOG$$^|C)99iYl#ymIUsSUs4O@jamocQfao7U*L<_tkQOY)vT{dpVUX58+ZqK>YSpJ}nKnaPp+t(a; z|2@B?(~57gR$pDNUuvw~h+S#K=2z?WMr?Iu_pdaTW0R9H%lOE+g%%UJ zV)}n3^cWC1WB}PmqR;9r6`qxwDfVa=J*3@O`+T2Y9th62zxTW*WubjbR%Ldor~Lm8 zw5ECtJXHTh&2zT69c3CW}t;IA|pYt$V{% z_UiPGZqmD2gf7E}l@|T!P0+TRNg?wGa8-+={S7TC3)Iq*w5o;acYTPy(0t_4N9mzv zIGtY6!!k{0^n}dNhMu4W-Jl2hIIZhC-PKIg_~;YgFM6(Q+_Z3#X{kfdD}x_`r4m@|Es?O71sh$ zIuV$VIl68}=;J`j$h&o!9Bl`tjqJW#ASF00r|54~TnHw8nbLm7qR)cU1`fngn<>%H z!7^UpqhOSh0}~k93PtGpK*}h%6w9Kmfiu3$zHs=;;M;U{F!NL_OIw3y4@$D6gg^;d zhP6K^Pg|h_fmWLS3cX16=y$XcO}5_}{!*c@#!f2pXJ>0QlJO`#dMQlFc#yt5Zqn;< zv%NDO@$^n_;)7b8KUIz5d*#cErMip1;iobCaV!O^iwi!d86w1$3=z^?h>#A*Bwa|K z8--=a-E^_(Fu3lh5JN5lb^tKoxUT7T;rd+yEEBj4b`WqBD!Tn3?cj7FzgW*BFz$c20~0`h^-keG=;z|UT|Ci`3@l@1a1dH7x!g(s9`R5 z2nvB)jAIQ8aT21P@Q83)@Hs#+GnkD1@RqnXA|!X>C`erPJl3#~Ds@sL3O3aA(BqV| zqb4$@vkSrmZld-=_07s$ PjsFgy;hL*fI4%AGF50Y#