Textures Browser form: empty texture sets are no longer shown when mixed textures & flats is disabled in the current game configuration.

Textures Browser form: PK3/Directory TEXTURES images are now shown in a separate folder in the resources tree.
Fixed, Textures Browser form: fixed a logic error when trying to select initial flat when mix textures & flats was disabled in the current game configuration (this resulted in the blank textures list after opening the form).
Fixed, Textures Browser form: resources tree showed textures count even when browsing flats.
Fixed, Textures Browser form: PK3/Directory textures took precedence even when browsing flats (this means when there were a flat and a texture with the same name, a texture was displayed when browsing flats).
Fixed, Classic modes: actor's scale set in DECORATE was ignored when rendering models.
Fixed, MODELDEF parser: in some cases, several model definitions were skipped when trying to skip the current one.
Fixed, resource management: flat and sprite TEXTURES definitions were loaded only from TEXTURES files named "TEXTURES".
Fixed/added, PK3/folder resource management: patch locations for sprites defined in TEXTURES are now checked the same way as in ZDoom (previously only the "sprites" folder was checked).
Fixed/added, PK3/folder resource management: patch locations for textures defined in TEXTURES are now checked the same way as in ZDoom (previously only the "textures" folder was checked).
Fixed, PK3/folder resource management: flats defined in TEXTURES were not added to the global Flats image list.
Fixed, PK3/folder resource management: in some cases, the image search algorithm could find flats, textures, patches or sprites in incorrect folders (for example, it could find a flat in "flats_backup" folder).
This commit is contained in:
MaxED 2014-10-07 00:23:02 +00:00
parent 6bc4325b36
commit 88e5e790e7
14 changed files with 190 additions and 146 deletions

View file

@ -695,6 +695,7 @@ constants
DMSS_AFFECTARMOR;
DMSS_FOILINVUL;
DMSS_KILL;
DMSS_NOFACTOR;
FPF_AIMATANGLE;
FPF_TRANSFERTRANSLATION;
JLOSF_PROJECTILE;

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -81,8 +81,9 @@ namespace CodeImp.DoomBuilder.Data
try
{
//mxd. Find in directories ZDoom expects them to be
foreach(string location in PatchLocations){
string path = Path.Combine(location, Path.GetDirectoryName(pname));
foreach(string loc in PatchLocations)
{
string path = Path.Combine(loc, Path.GetDirectoryName(pname));
string filename = FindFirstFile(path, Path.GetFileName(pname), true);
if(!string.IsNullOrEmpty(filename) && FileExists(filename))
@ -114,12 +115,13 @@ namespace CodeImp.DoomBuilder.Data
try
{
// Find in patches directory
string path = Path.Combine(TEXTURES_DIR, Path.GetDirectoryName(pname));
string filename = FindFirstFile(path, Path.GetFileName(pname), true);
if((filename != null) && FileExists(filename))
//mxd. Find in directories ZDoom expects them to be
foreach(string loc in TextureLocations)
{
return LoadFile(filename);
string path = Path.Combine(loc, Path.GetDirectoryName(pname));
string filename = FindFirstFile(path, Path.GetFileName(pname), true);
if(!string.IsNullOrEmpty(filename) && FileExists(filename))
return LoadFile(filename);
}
}
catch(Exception e)

View file

@ -33,7 +33,6 @@ namespace CodeImp.DoomBuilder.Data
#region ================== Variables
private List<TexturePatch> patches; //mxd
private bool gotFullName;//mxd
private string type;
#endregion
@ -52,6 +51,7 @@ namespace CodeImp.DoomBuilder.Data
this.patches = new List<TexturePatch>(1);
this.type = type;
SetName(name);
this.fullName = "[TEXTURES]\\" + type + "s\\" + name; //mxd
// We have no destructor
GC.SuppressFinalize(this);
@ -66,13 +66,6 @@ namespace CodeImp.DoomBuilder.Data
{
// Add it
patches.Add(patch);
//mxd. Get full name from first patch
if (!gotFullName) {
fullName = General.Map.Data.GetPatchLocation(patch.lumpname);
gotFullName = true;
}
if (patch.lumpname == Name) hasPatchWithSameName = true; //mxd
}
@ -116,14 +109,7 @@ namespace CodeImp.DoomBuilder.Data
foreach(TexturePatch p in patches)
{
// Get the patch data stream
Stream patchdata;
//mxd
if (type == "sprite") {
patchdata = General.Map.Data.GetSpriteData(p.lumpname);
} else {
patchdata = General.Map.Data.GetPatchData(p.lumpname);
}
Stream patchdata = General.Map.Data.GetPatchData(p.lumpname);
if(patchdata != null)
{

View file

@ -123,8 +123,9 @@ namespace CodeImp.DoomBuilder.Data
}
//mxd. Find in directories ZDoom expects them to be
foreach(string location in PatchLocations) {
string filename = FindFirstFile(location, pname, true);
foreach(string loc in PatchLocations)
{
string filename = FindFirstFile(loc, pname, true);
if((filename != null) && FileExists(filename))
return LoadFile(filename);
}
@ -147,11 +148,12 @@ namespace CodeImp.DoomBuilder.Data
if(data != null) return data;
}
// Find in patches directory
string filename = FindFirstFile(TEXTURES_DIR, pname, true);
if((filename != null) && FileExists(filename))
//mxd. Find in directories ZDoom expects them to be
foreach(string loc in TextureLocations)
{
return LoadFile(filename);
string filename = FindFirstFile(loc, pname, true);
if(!string.IsNullOrEmpty(filename) && FileExists(filename))
return LoadFile(filename);
}
// Nothing found

View file

@ -54,7 +54,8 @@ namespace CodeImp.DoomBuilder.Data
#region ================== Properties
protected string[] PatchLocations = { PATCHES_DIR, TEXTURES_DIR, FLATS_DIR, GRAPHICS_DIR }; //mxd. Because ZDoom looks for patches in these folders ///TODO: check the order of these
protected readonly string[] PatchLocations = { PATCHES_DIR, TEXTURES_DIR, FLATS_DIR, SPRITES_DIR, GRAPHICS_DIR }; //mxd. Because ZDoom looks for patches and sprites in this order
protected readonly string[] TextureLocations = { TEXTURES_DIR, PATCHES_DIR, FLATS_DIR, SPRITES_DIR, GRAPHICS_DIR }; //mxd. Because ZDoom looks for textures in this order
#endregion
@ -210,7 +211,6 @@ namespace CodeImp.DoomBuilder.Data
// Load TEXTURES lump files
imgset.Clear();
//string[] alltexturefiles = GetAllFilesWithTitle("", "TEXTURES", false);
string[] alltexturefiles = GetAllFilesWhichTitleStartsWith("", "TEXTURES"); //mxd
foreach(string texturesfile in alltexturefiles)
{
@ -268,12 +268,14 @@ namespace CodeImp.DoomBuilder.Data
// Error when suspended
if (issuspended) throw new Exception("Data reader is suspended");
//no need to search in wads...
// Find in patches directory
//string filename = FindFirstFile(PATCHES_DIR, pname, true);
string filename = FindFirstFile("", pname, true); //mxd. ZDoom can load them from anywhere, so shall we
if ((filename != null) && FileExists(filename))
return filename;
// Find in directories ZDoom expects them to be
foreach (string loc in PatchLocations)
{
string path = Path.Combine(loc, Path.GetDirectoryName(pname));
string filename = FindFirstFile(path, Path.GetFileName(pname), true);
if (!string.IsNullOrEmpty(filename) && FileExists(filename))
return filename;
}
return pname;
}
@ -311,13 +313,8 @@ namespace CodeImp.DoomBuilder.Data
collection = LoadDirectoryImages(FLATS_DIR, ImageDataFormat.DOOMFLAT, true);
AddImagesToList(images, collection);
// Add images to the container-specific texture set
foreach(ImageData img in images.Values)
textureset.AddFlat(img);
// Load TEXTURES lump file
imgset.Clear();
string[] alltexturefiles = GetAllFilesWithTitle("", "TEXTURES", false);
string[] alltexturefiles = GetAllFilesWhichTitleStartsWith("", "TEXTURES"); //mxd
foreach(string texturesfile in alltexturefiles)
{
MemoryStream filedata = LoadFile(texturesfile);
@ -327,6 +324,13 @@ namespace CodeImp.DoomBuilder.Data
// Add images from TEXTURES lump file
AddImagesToList(images, imgset);
// Add images to the container-specific texture set
foreach(ImageData img in images.Values)
textureset.AddFlat(img);
// Add images from TEXTURES lump file
AddImagesToList(images, imgset);
return new List<ImageData>(images.Values);
}
@ -371,7 +375,7 @@ namespace CodeImp.DoomBuilder.Data
// Load TEXTURES lump file
imgset.Clear();
string[] alltexturefiles = GetAllFilesWithTitle("", "TEXTURES", false);
string[] alltexturefiles = GetAllFilesWhichTitleStartsWith("", "TEXTURES"); //mxd
foreach(string texturesfile in alltexturefiles)
{
MemoryStream filedata = LoadFile(texturesfile);

View file

@ -51,12 +51,16 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
} else {
// Unknown structure!
string token2;
do {
if (!SkipWhitespace(true)) break;
token2 = ReadToken();
if (token2 == null) break;
if (token != "{") {
do
{
if (!SkipWhitespace(true)) break;
token2 = ReadToken();
if (token2 == null) break;
}
while (token2 != "{");
}
while (token2 != "{");
int scopelevel = 1;
do {
if (!SkipWhitespace(true)) break;

View file

@ -30,7 +30,7 @@ namespace CodeImp.DoomBuilder.IO
public string filename; // bar.wad
public string filetitle; // bar
public string extension; // wad
public string path; // foo
public string path; // foo\
public string filepathname; // Foo\Bar.WAD
public string filepathtitle; // Foo\Bar
@ -47,7 +47,7 @@ namespace CodeImp.DoomBuilder.IO
extension = "";
path = Path.GetDirectoryName(fullname);
if(path.Length > (frompath.Length + 1))
path = path.Substring(frompath.Length + 1);
path = path.Substring(frompath.Length + 1) + Path.DirectorySeparatorChar;
else
path = "";
filepathname = Path.Combine(path, filename);
@ -72,6 +72,7 @@ namespace CodeImp.DoomBuilder.IO
else
extension = "";
path = Path.GetDirectoryName(fullname);
if(!string.IsNullOrEmpty(path)) path += Path.DirectorySeparatorChar; //mxd
filepathname = Path.Combine(path, filename);
filepathtitle = Path.Combine(path, filetitle);

View file

@ -288,20 +288,18 @@ namespace CodeImp.DoomBuilder.IO
return null;
}
// This fixes a path so that it doesn't have the \ at the end
// This fixes a path so that it ends with the proper directory separator (mxd)
private static string CorrectPath(string path)
{
if(path.Length > 0)
{
if((path[path.Length - 1] == Path.DirectorySeparatorChar) || (path[path.Length - 1] == Path.AltDirectorySeparatorChar))
return path.Substring(0, path.Length - 1);
else
return path;
}
else
{
return path;
if(path[path.Length - 1] == Path.DirectorySeparatorChar) return path;
if(path[path.Length - 1] == Path.AltDirectorySeparatorChar)
path = path.Substring(0, path.Length - 1);
return path + Path.DirectorySeparatorChar;
}
return path;
}
#endregion

View file

@ -1327,7 +1327,9 @@ namespace CodeImp.DoomBuilder.Rendering
graphics.Shaders.Things2D.FillColor = t.Selected ? cHighlight : cWire;
for(int i = 0; i < mde.Model.Meshes.Count; i++) {
Matrix modelcale = Matrix.Scaling(t.ScaleX, t.ScaleX, t.ScaleY);
float sx = t.ScaleX * t.ActorScale.Width;
float sy = t.ScaleY * t.ActorScale.Height;
Matrix modelcale = Matrix.Scaling(sx, sx, sy);
Matrix rotation = Matrix.RotationY(-(t.RollRad - General.Map.Data.ModeldefEntries[t.Type].RollOffset))
* Matrix.RotationX(-(t.PitchRad + General.Map.Data.ModeldefEntries[t.Type].PitchOffset))
* Matrix.RotationZ(t.Angle);

View file

@ -190,7 +190,8 @@ namespace CodeImp.DoomBuilder.Windows
label7.TabIndex = 25;
label7.Text = "Height offset:";
label7.TextAlign = System.Drawing.ContentAlignment.TopRight;
this.tooltip.SetToolTip(label7, "Changes floor and ceiling\r\nheight by given value");
this.tooltip.SetToolTip(label7, "Use ++ or -- prefixes to change\r\nheight by given value.\r\nUse * or / prefixes to m" +
"ultiply\r\nor divide height by given value.");
//
// label5
//
@ -202,7 +203,8 @@ namespace CodeImp.DoomBuilder.Windows
label5.TabIndex = 17;
label5.Text = "Floor height:";
label5.TextAlign = System.Drawing.ContentAlignment.TopRight;
this.tooltip.SetToolTip(label5, "Use ++ or -- prefixes to change\r\nheight by given value");
this.tooltip.SetToolTip(label5, "Use ++ or -- prefixes to change\r\nheight by given value.\r\nUse * or / prefixes to m" +
"ultiply\r\nor divide height by given value.");
//
// label6
//
@ -214,7 +216,8 @@ namespace CodeImp.DoomBuilder.Windows
label6.TabIndex = 19;
label6.Text = "Ceiling height:";
label6.TextAlign = System.Drawing.ContentAlignment.TopRight;
this.tooltip.SetToolTip(label6, "Use ++ or -- prefixes to change\r\nheight by given value");
this.tooltip.SetToolTip(label6, "Use ++ or -- prefixes to change\r\nheight by given value.\r\nUse * or / prefixes to m" +
"ultiply\r\nor divide height by given value.");
//
// heightoffset
//

View file

@ -73,6 +73,7 @@ namespace CodeImp.DoomBuilder.Windows
this.smallimages.Images.SetKeyName(4, "PK3TextureSet.ico");
this.smallimages.Images.SetKeyName(5, "FolderImage.png");
this.smallimages.Images.SetKeyName(6, "ArchiveImage.png");
this.smallimages.Images.SetKeyName(7, "TextLump.png");
//
// tvTextureSets
//

View file

@ -47,9 +47,10 @@ namespace CodeImp.DoomBuilder.Windows
public TextureBrowserForm(string selecttexture, bool browseFlats)
{
Cursor.Current = Cursors.WaitCursor;
TreeNode item;//mxd
TreeNode item; //mxd
long longname = Lump.MakeLongName(selecttexture ?? "");
selectedset = null;//mxd
int count; //mxd
selectedset = null; //mxd
this.browseFlats = browseFlats;
// Initialize
@ -75,9 +76,12 @@ namespace CodeImp.DoomBuilder.Windows
availgroup = browser.AddGroup("Available " + imgType + ":");
//mxd. Fill texture sets list with normal texture sets
foreach(IFilledTextureSet ts in General.Map.Data.TextureSets)
foreach(IFilledTextureSet ts in General.Map.Data.TextureSets)
{
item = tvTextureSets.Nodes.Add(ts.Name + " [" + ts.Textures.Count + "]");
count = (browseFlats ? ts.Flats.Count : ts.Textures.Count);
if(count == 0 && !General.Map.Config.MixTexturesFlats) continue;
item = tvTextureSets.Nodes.Add(ts.Name + " [" + count + "]");
item.Name = ts.Name;
item.Tag = ts;
item.ImageIndex = 0;
@ -86,7 +90,10 @@ namespace CodeImp.DoomBuilder.Windows
//mxd. Add container-specific texture sets
foreach(ResourceTextureSet ts in General.Map.Data.ResourceTextureSets)
{
item = tvTextureSets.Nodes.Add(ts.Name + " [" + ts.Textures.Count + "]");
count = (browseFlats ? ts.Flats.Count : ts.Textures.Count);
if(count == 0 && !General.Map.Config.MixTexturesFlats) continue;
item = tvTextureSets.Nodes.Add(ts.Name + " [" + count + "]");
item.Name = ts.Name;
item.Tag = ts;
item.ImageIndex = 2 + ts.Location.type;
@ -99,7 +106,8 @@ namespace CodeImp.DoomBuilder.Windows
}
//mxd. Add All textures set
item = tvTextureSets.Nodes.Add(General.Map.Data.AllTextureSet.Name + " [" + General.Map.Data.AllTextureSet.Textures.Count + "]");
count = (browseFlats ? General.Map.Data.AllTextureSet.Flats.Count : General.Map.Data.AllTextureSet.Textures.Count);
item = tvTextureSets.Nodes.Add(General.Map.Data.AllTextureSet.Name + " [" + count + "]");
item.Name = General.Map.Data.AllTextureSet.Name;
item.Tag = General.Map.Data.AllTextureSet;
item.ImageIndex = 1;
@ -175,7 +183,7 @@ namespace CodeImp.DoomBuilder.Windows
}
//mxd
private static TreeNode findTextureByLongName(TreeNode node, long longname)
private TreeNode findTextureByLongName(TreeNode node, long longname)
{
//first search in child nodes
TreeNode match;
@ -188,8 +196,16 @@ namespace CodeImp.DoomBuilder.Windows
//then - in current node
IFilledTextureSet set = (node.Tag as IFilledTextureSet);
foreach (ImageData img in set.Textures)
if (img.LongName == longname) return node;
if (browseFlats)
{
foreach(ImageData img in set.Flats)
if(img.LongName == longname) return node;
}
else
{
foreach(ImageData img in set.Textures)
if(img.LongName == longname) return node;
}
return null;
}
@ -218,8 +234,17 @@ namespace CodeImp.DoomBuilder.Windows
int imageIndex = set.Location.type + 4;
string[] separator = new[] { Path.DirectorySeparatorChar.ToString() };
ImageData[] textures = new ImageData[set.Textures.Count];
set.Textures.CopyTo(textures, 0);
ImageData[] textures;
if (browseFlats)
{
textures = new ImageData[set.Flats.Count];
set.Flats.CopyTo(textures, 0);
}
else
{
textures = new ImageData[set.Textures.Count];
set.Textures.CopyTo(textures, 0);
}
Array.Sort(textures, sortImageData);
foreach (ImageData image in textures) {
@ -228,6 +253,7 @@ namespace CodeImp.DoomBuilder.Windows
TreeNode curNode = root;
if (parts.Length == 1) continue;
int localindex = parts[0] == "[TEXTURES]" ? 7 : imageIndex;
for (int i = 0; i < parts.Length - 1; i++) {
string category = parts[i];
@ -237,7 +263,7 @@ namespace CodeImp.DoomBuilder.Windows
curNode = curNode.Nodes[category];
} else { //create a new one
TreeNode n = new TreeNode(category) {Name = category, ImageIndex = imageIndex, SelectedImageIndex = imageIndex};
TreeNode n = new TreeNode(category) { Name = category, ImageIndex = localindex, SelectedImageIndex = localindex };
curNode.Nodes.Add(n);
curNode = n;
@ -251,7 +277,10 @@ namespace CodeImp.DoomBuilder.Windows
TreeNode cn = curNode;
while (cn != root) {
ResourceTextureSet curTs = cn.Tag as ResourceTextureSet;
curTs.AddTexture(image);
if (image.IsFlat)
curTs.AddFlat(image);
else
curTs.AddTexture(image);
cn = cn.Parent;
}
}
@ -269,14 +298,21 @@ namespace CodeImp.DoomBuilder.Windows
}
//mxd
private static void SetItemsCount(TreeNode node)
private void SetItemsCount(TreeNode node)
{
ResourceTextureSet ts = node.Tag as ResourceTextureSet;
if (ts == null) throw new Exception("Expected IFilledTextureSet, but got null...");
node.Text += " [" + ts.Textures.Count + "]";
if (General.Map.Config.MixTexturesFlats)
if (node.Parent != null && General.Map.Config.MixTexturesFlats)
{
ts.MixTexturesAndFlats();
node.Text += " [" + ts.Textures.Count + "]";
}
else
{
node.Text += " [" + (browseFlats ? ts.Flats.Count : ts.Textures.Count) + "]";
}
foreach (TreeNode child in node.Nodes) SetItemsCount(child);
}

View file

@ -124,72 +124,76 @@
<value>
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAc
DwAAAk1TRnQBSQFMAgEBBwEAAeQBAAHkAQABEAEAARYBAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
AwABQAMAASwDAAEBAQABCAYAAQsYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA
AWYDAAGZAwABzAIAATMDAAIzAgABMwFmAgABMwGZAgABMwHMAgABMwH/AgABZgMAAWYBMwIAAmYCAAFm
AZkCAAFmAcwCAAFmAf8CAAGZAwABmQEzAgABmQFmAgACmQIAAZkBzAIAAZkB/wIAAcwDAAHMATMCAAHM
AWYCAAHMAZkCAALMAgABzAH/AgAB/wFmAgAB/wGZAgAB/wHMAQABMwH/AgAB/wEAATMBAAEzAQABZgEA
ATMBAAGZAQABMwEAAcwBAAEzAQAB/wEAAf8BMwIAAzMBAAIzAWYBAAIzAZkBAAIzAcwBAAIzAf8BAAEz
AWYCAAEzAWYBMwEAATMCZgEAATMBZgGZAQABMwFmAcwBAAEzAWYB/wEAATMBmQIAATMBmQEzAQABMwGZ
AWYBAAEzApkBAAEzAZkBzAEAATMBmQH/AQABMwHMAgABMwHMATMBAAEzAcwBZgEAATMBzAGZAQABMwLM
AQABMwHMAf8BAAEzAf8BMwEAATMB/wFmAQABMwH/AZkBAAEzAf8BzAEAATMC/wEAAWYDAAFmAQABMwEA
AWYBAAFmAQABZgEAAZkBAAFmAQABzAEAAWYBAAH/AQABZgEzAgABZgIzAQABZgEzAWYBAAFmATMBmQEA
AWYBMwHMAQABZgEzAf8BAAJmAgACZgEzAQADZgEAAmYBmQEAAmYBzAEAAWYBmQIAAWYBmQEzAQABZgGZ
AWYBAAFmApkBAAFmAZkBzAEAAWYBmQH/AQABZgHMAgABZgHMATMBAAFmAcwBmQEAAWYCzAEAAWYBzAH/
AQABZgH/AgABZgH/ATMBAAFmAf8BmQEAAWYB/wHMAQABzAEAAf8BAAH/AQABzAEAApkCAAGZATMBmQEA
AZkBAAGZAQABmQEAAcwBAAGZAwABmQIzAQABmQEAAWYBAAGZATMBzAEAAZkBAAH/AQABmQFmAgABmQFm
ATMBAAGZATMBZgEAAZkBZgGZAQABmQFmAcwBAAGZATMB/wEAApkBMwEAApkBZgEAA5kBAAKZAcwBAAKZ
Af8BAAGZAcwCAAGZAcwBMwEAAWYBzAFmAQABmQHMAZkBAAGZAswBAAGZAcwB/wEAAZkB/wIAAZkB/wEz
AQABmQHMAWYBAAGZAf8BmQEAAZkB/wHMAQABmQL/AQABzAMAAZkBAAEzAQABzAEAAWYBAAHMAQABmQEA
AcwBAAHMAQABmQEzAgABzAIzAQABzAEzAWYBAAHMATMBmQEAAcwBMwHMAQABzAEzAf8BAAHMAWYCAAHM
AWYBMwEAAZkCZgEAAcwBZgGZAQABzAFmAcwBAAGZAWYB/wEAAcwBmQIAAcwBmQEzAQABzAGZAWYBAAHM
ApkBAAHMAZkBzAEAAcwBmQH/AQACzAIAAswBMwEAAswBZgEAAswBmQEAA8wBAALMAf8BAAHMAf8CAAHM
Af8BMwEAAZkB/wFmAQABzAH/AZkBAAHMAf8BzAEAAcwC/wEAAcwBAAEzAQAB/wEAAWYBAAH/AQABmQEA
AcwBMwIAAf8CMwEAAf8BMwFmAQAB/wEzAZkBAAH/ATMBzAEAAf8BMwH/AQAB/wFmAgAB/wFmATMBAAHM
AmYBAAH/AWYBmQEAAf8BZgHMAQABzAFmAf8BAAH/AZkCAAH/AZkBMwEAAf8BmQFmAQAB/wKZAQAB/wGZ
AcwBAAH/AZkB/wEAAf8BzAIAAf8BzAEzAQAB/wHMAWYBAAH/AcwBmQEAAf8CzAEAAf8BzAH/AQAC/wEz
AQABzAH/AWYBAAL/AZkBAAL/AcwBAAJmAf8BAAFmAf8BZgEAAWYC/wEAAf8CZgEAAf8BZgH/AQAC/wFm
AQABIQEAAaUBAANfAQADdwEAA4YBAAOWAQADywEAA7IBAAPXAQAD3QEAA+MBAAPqAQAD8QEAA/gBAAHw
AfsB/wEAAaQCoAEAA4ADAAH/AgAB/wMAAv8BAAH/AwAB/wEAAf8BAAL/AgAD/9MADUsIAAKZGgAHDgEQ
AW0BbAIOAgABUQ1SAUsFAAHvAXMBHAFuAUoBBxcAAQ4BDQFsAZABuwIJAfcCbAFmAg4BAAFSAXoBUgGg
CHoBUgGgAVIBSwMAAZkBbgN0AVIBSwFEAUoBmR0AAQ4B6gFsAQ8BDgEAAVIBegFSAaABegFYBnkBWAGg
AVIBSwIAAXMBbgF0AZkCdAFSAksBbgFEAW4BGhQAAW0HAAFDAW0BDgIAAVIBegFSAaAKcwFSAUsBAAEc
AXQBmgJSAXQBegFMBUsBcxMAAW0B8QFtAQcBvAHwAfECAAERAQcB7AIAAVIBegFSAaABcwL/AfMD9ALz
AXMBUgFLAQABmQFzAVEBdAF6AnQBTANLAUoBSwGTEwADbQEHArwB8AIAAm0BDgIAAVIBegFSAaABcwH/
AdwF2wH0AXMBUgFLAQAB7AEcAXkCdAoSEgABbQHwAwcCvAIAAREBBwHsAgABUgGaAVIB/wG8Af8GGQHz
AbwBUgFLAQACHAJ0AgcD7wH3ARwD7QESEgABbQHwAe8DBwG8AgACbQEOAgABUgGgDVICAAHtARwBdAFL
ARwI/wHtARISAAFtAfAC7wMHAgABEQEHAewCAAFSA6ABHAH/Aa4BmgG9AXUB4wGuAf8B7QHrAgAB7AFz
AXQBSwH3Af8GrgH/Ae0BEhIAAW0B8APvAgcCAAJtAQ4CAAFSAf8CoAH3Af8BrgL/AnUBrgH/Ae0B6wIA
AZMDdAHvAf8BrgGUAf8BmgGUAa4B/wHtARISAAFtAbwE7wEHAgABEQEHAewDAAFSAv8B7wH/Aa4BlAH/
AZoBlAGuAf8B7QHrAgABHAGZAcMBegHvAf8C0wH/AZoC0wH/Ae0BEhIACG0BAAEPAewBDwQAAlIB7wH/
AdMErgHTAf8B7QHrAwACHAGaAe8B/wbTAf8B7QESEgAJDgHrAZEBDQYAAe8B/wbTAf8B7QHrBAABmQF0
AQcI/wHtARISAAEOAWUBkAG7BQkB9wFsAg4FAAEHCP8B7QHrBgACBwPvAfcBHAPtHgABDgYAAgcD7wH3
ARwD7QkAApn/AKgAAfcCrgFtAWwB6gJsBGY0AAH3Bf8C9AMZAWYJAAgOEwAB9wKuAW0BbAHqAmwEZgQA
AbUC/wKTAZkBBwG7AbQCGQNmBgABDgEABe8B9wEOAwACcwHrAW4BbQFKARMBFQFDAREBDwEOAQ8DAAH3
Bf8C9AMZAWYEAAG1Av8BkwGaAXoBnwGeAbsB9AHzAWYBGQFmBQABDgHvAQAB8ALxAvIBvAEOAwABcwIc
BzECSwFEAe0CAAG1Av8CkwGZAQcBuwG0AhkDZgIAAbUC/wG7AQgCnwF+AXkC9AFsARkDZgIAAQ4B7wEH
AQAB8ALxAvIB8AEOAwAB7AF6ARwBmgN6AlkBUwFSATEBSwHqAgABtQL/AZMBmgF6AZ8BngG7AfQB8wFm
ARkBZgIAAbUC/wLbAQkBCAF+AXkB/wH0AWwB8wFmARkBZgIAAQ4CAAHvAbwB8ALxAfIB8AEOAwAB7QF6
ARwBmQV6AlkBUwExAUQB7QEAAbUC/wG7AQgCnwF+AXkC9AFsARkDZgEHCv8BbAH0AWwBGQFmAgABDgHw
AgcCvALwAfEBvAEOAwAB7QGaAXoBHAGaBXoDWQFLAW0BAAG1Av8C2wEJAQgBfgF5Af8B9AFsAfMBZgEZ
AWYCBwS1AfcBtQLtApEB9AFsAfMBZgIAAQ4B8AMHArwC8AG8AQ4DAAEcAZoBegEcAZkHegFZAVIBSgHt
AQcK/wFsAfQBbAEZAWYBtQH/AQcK/wFsAfQBbAIAAQ4B8AQHArwB8AG8AQ4DAAEcAZoBoAF6ARwHmgJ6
AXQBbQIHBLUB9wG1Au0CkQH0AWwB8wFmAbUB/wIHBLUB9wG1Au0CkQH0AWwCAAEOAfAC7wQHAbwBBwEO
AwABHAOgCBwC7QHsAXMCAAEHCv8BbAH0AWwBBwP/AQcK/wFsAgABDgHwA+8FBwEOAwABHASgAZoGegFz
BQACBwS1AfcBtQLtApEB9AFsAgcCtQIHBLUB9wG1Au0CkQIAAQ4BvATvBAcBDgMAARwBoAHDA6ABegMc
Au0BcwcAAQcK/wFsAgABBwr/AWwB9AFsAgABDgG8Be8DBwEOAwABHAGZAsMCoAEcAe0MAAIHBLUB9wG1
Au0CkQIAAgcEtQH3AbUC7QKRAfQBbAIAAQ4B9APwA7wCBwEOBAAFHAHtHQABBwr/AWwCAAsOJwACBwS1
AfcBtQLtApHgAAFCAU0BPgcAAT4DAAEoAwABQAMAASwDAAEBAQABAQUAAWABARYAA/8BAAb/AgAG/wIA
Bv8CAAH/AcMBwAEBAf4BfwIAAeABAQGAAQAB+AEfAgABwAEBAgAB4AEHAgABgAEBAgABwAEBAgAB4AEj
AgABgAEBAgABwAEjAgABgAEBAgABwAEjAgABgAMAAcABIwIAAYADAAHAASMBAAEBAYADAAHAASMBAAEB
AYADAAHAASMBAAEBAYADAAHAASMBgAEBAYADAAHAASMBwAEBAcADAAGAAQEB8AEBAeADAAHAAQEB8AEB
AfgBAQIAAeABAwHwAQMB/gF/AgAG/wIABv8CAAb/AgAa/wEAAQ8G/wEAAQ8B+AEHAv8BAAEPAQABAwHw
AQcBAAEHAQABDwEAAQMB4AEHAQABAwEAAQMCAAHAAQcBAAEDAQABAwIAAcABBwEAAQEEAAHAAQcBAAEB
BAABwAEHBgABwAEHBgABwAEHAgABwAMAAcABBwEAAQcBwAMAAcABBwEAAQcB8AEAAcABAAHAAQcBAAH/
AfABAAHAAQABwAEHAYED/wHwAQABwAEHBP8B8AEAHP8L
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAi
EAAAAk1TRnQBSQFMAgEBCAEAAfwBAAH8AQABEAEAARYBAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
AwABQAMAAUIDAAEBAQABCAUAAYABEBgAAYACAAGAAwACgAEAAYADAAGAAQABgAEAAoACAAPAAQABwAHc
AcABAAHwAcoBpgEAATMFAAEzAQABMwEAATMBAAIzAgADFgEAAxwBAAMiAQADKQEAA1UBAANNAQADQgEA
AzkBAAGAAXwB/wEAAlAB/wEAAZMBAAHWAQAB/wHsAcwBAAHGAdYB7wEAAdYC5wEAAZABqQGtAgAB/wEz
AwABZgMAAZkDAAHMAgABMwMAAjMCAAEzAWYCAAEzAZkCAAEzAcwCAAEzAf8CAAFmAwABZgEzAgACZgIA
AWYBmQIAAWYBzAIAAWYB/wIAAZkDAAGZATMCAAGZAWYCAAKZAgABmQHMAgABmQH/AgABzAMAAcwBMwIA
AcwBZgIAAcwBmQIAAswCAAHMAf8CAAH/AWYCAAH/AZkCAAH/AcwBAAEzAf8CAAH/AQABMwEAATMBAAFm
AQABMwEAAZkBAAEzAQABzAEAATMBAAH/AQAB/wEzAgADMwEAAjMBZgEAAjMBmQEAAjMBzAEAAjMB/wEA
ATMBZgIAATMBZgEzAQABMwJmAQABMwFmAZkBAAEzAWYBzAEAATMBZgH/AQABMwGZAgABMwGZATMBAAEz
AZkBZgEAATMCmQEAATMBmQHMAQABMwGZAf8BAAEzAcwCAAEzAcwBMwEAATMBzAFmAQABMwHMAZkBAAEz
AswBAAEzAcwB/wEAATMB/wEzAQABMwH/AWYBAAEzAf8BmQEAATMB/wHMAQABMwL/AQABZgMAAWYBAAEz
AQABZgEAAWYBAAFmAQABmQEAAWYBAAHMAQABZgEAAf8BAAFmATMCAAFmAjMBAAFmATMBZgEAAWYBMwGZ
AQABZgEzAcwBAAFmATMB/wEAAmYCAAJmATMBAANmAQACZgGZAQACZgHMAQABZgGZAgABZgGZATMBAAFm
AZkBZgEAAWYCmQEAAWYBmQHMAQABZgGZAf8BAAFmAcwCAAFmAcwBMwEAAWYBzAGZAQABZgLMAQABZgHM
Af8BAAFmAf8CAAFmAf8BMwEAAWYB/wGZAQABZgH/AcwBAAHMAQAB/wEAAf8BAAHMAQACmQIAAZkBMwGZ
AQABmQEAAZkBAAGZAQABzAEAAZkDAAGZAjMBAAGZAQABZgEAAZkBMwHMAQABmQEAAf8BAAGZAWYCAAGZ
AWYBMwEAAZkBMwFmAQABmQFmAZkBAAGZAWYBzAEAAZkBMwH/AQACmQEzAQACmQFmAQADmQEAApkBzAEA
ApkB/wEAAZkBzAIAAZkBzAEzAQABZgHMAWYBAAGZAcwBmQEAAZkCzAEAAZkBzAH/AQABmQH/AgABmQH/
ATMBAAGZAcwBZgEAAZkB/wGZAQABmQH/AcwBAAGZAv8BAAHMAwABmQEAATMBAAHMAQABZgEAAcwBAAGZ
AQABzAEAAcwBAAGZATMCAAHMAjMBAAHMATMBZgEAAcwBMwGZAQABzAEzAcwBAAHMATMB/wEAAcwBZgIA
AcwBZgEzAQABmQJmAQABzAFmAZkBAAHMAWYBzAEAAZkBZgH/AQABzAGZAgABzAGZATMBAAHMAZkBZgEA
AcwCmQEAAcwBmQHMAQABzAGZAf8BAALMAgACzAEzAQACzAFmAQACzAGZAQADzAEAAswB/wEAAcwB/wIA
AcwB/wEzAQABmQH/AWYBAAHMAf8BmQEAAcwB/wHMAQABzAL/AQABzAEAATMBAAH/AQABZgEAAf8BAAGZ
AQABzAEzAgAB/wIzAQAB/wEzAWYBAAH/ATMBmQEAAf8BMwHMAQAB/wEzAf8BAAH/AWYCAAH/AWYBMwEA
AcwCZgEAAf8BZgGZAQAB/wFmAcwBAAHMAWYB/wEAAf8BmQIAAf8BmQEzAQAB/wGZAWYBAAH/ApkBAAH/
AZkBzAEAAf8BmQH/AQAB/wHMAgAB/wHMATMBAAH/AcwBZgEAAf8BzAGZAQAB/wLMAQAB/wHMAf8BAAL/
ATMBAAHMAf8BZgEAAv8BmQEAAv8BzAEAAmYB/wEAAWYB/wFmAQABZgL/AQAB/wJmAQAB/wFmAf8BAAL/
AWYBAAEhAQABpQEAA18BAAN3AQADhgEAA5YBAAPLAQADsgEAA9cBAAPdAQAD4wEAA+oBAAPxAQAD+AEA
AfAB+wH/AQABpAKgAQADgAMAAf8CAAH/AwAC/wEAAf8DAAH/AQAB/wEAAv8CAAP//wD/AP8A/wD/AP8A
WQANSwgAApkIAAEHDBIBBwQABw4BEAFtAWwCDgIAAVENUgFLBQAB7wFzARwBbgFKAQcGAAESDP8BEgMA
AQ4BDQFsAZABuwIJAfcCbAFmAg4BAAFSAXoBUgGgCHoBUgGgAVIBSwMAAZkBbgN0AVIBSwFEAUoBmQQA
AeoB/wn0AfMB/wHqCwABDgHqAWwBDwEOAQABUgF6AVIBoAF6AVgGeQFYAaABUgFLAgABcwFuAXQBmQJ0
AVICSwFuAUQBbgEaAgAB6gH/AfQI7AHzAf8B6gQAAW0HAAFDAW0BDgIAAVIBegFSAaAKcwFSAUsBAAEc
AXQBmgJSAXQBegFMBUsBcwIAAW0B/wX0BfMB/wFtAwABbQHxAW0BBwG8AfAB8QIAAREBBwHsAgABUgF6
AVIBoAFzAv8B8wP0AvMBcwFSAUsBAAGZAXMBUQF0AXoCdAFMA0sBSgFLAZMCAAFtAf8B9AjtAfMB/wFt
AwADbQEHArwB8AIAAm0BDgIAAVIBegFSAaABcwH/AdwF2wH0AXMBUgFLAQAB7AEcAXkCdAoSAQAB6wH/
AfQJ8wH/AesDAAFtAfADBwK8AgABEQEHAewCAAFSAZoBUgH/AbwB/wYZAfMBvAFSAUsBAAIcAnQCBwPv
AfcBHAPtARIBAAHrAf8B8wH3B5IB8wH/AesDAAFtAfAB7wMHAbwCAAJtAQ4CAAFSAaANUgIAAe0BHAF0
AUsBHAj/Ae0BEgEAAfgB/wrzAf8B+AMAAW0B8ALvAwcCAAERAQcB7AIAAVIDoAEcAf8BrgGaAb0BdQHj
Aa4B/wHtAesCAAHsAXMBdAFLAfcB/wauAf8B7QESAQAB7AH/AfMI7wHyAf8B7AMAAW0B8APvAgcCAAJt
AQ4CAAFSAf8CoAH3Af8BrgL/AnUBrgH/Ae0B6wIAAZMDdAHvAf8BrgGUAf8BmgGUAa4B/wHtARIBAAHs
Af8G8wX/AewDAAFtAbwE7wEHAgABEQEHAewDAAFSAv8B7wH/Aa4BlAH/AZoBlAGuAf8B7QHrAgABHAGZ
AcMBegHvAf8C0wH/AZoC0wH/Ae0BEgEAAe0B/wHzBe8B/wLyAfMB7QG8AwAIbQEAAQ8B7AEPBAACUgHv
Af8B0wSuAdMB/wHtAesDAAIcAZoB7wH/BtMB/wHtARIBAAHtAf8D8wPyAf8B8gHzAe0B8AQACQ4B6wGR
AQ0GAAHvAf8G0wH/Ae0B6wQAAZkBdAEHCP8B7QESAQABkgH/AfMF8gH/AfMBkgHwBQABDgFlAZABuwUJ
AfcBbAIOBQABBwj/Ae0B6wYAAgcD7wH3ARwD7QIAAZII/wGSAfARAAEOBgACBwPvAfcBHAPtCQACmQgA
AfAI9wHw/wCWAAH3Aq4BbQFsAeoCbARmNAAB9wX/AvQDGQFmCQAIDhMAAfcCrgFtAWwB6gJsBGYEAAG1
Av8CkwGZAQcBuwG0AhkDZgYAAQ4BAAXvAfcBDgMAAnMB6wFuAW0BSgETARUBQwERAQ8BDgEPAwAB9wX/
AvQDGQFmBAABtQL/AZMBmgF6AZ8BngG7AfQB8wFmARkBZgUAAQ4B7wEAAfAC8QLyAbwBDgMAAXMCHAcx
AksBRAHtAgABtQL/ApMBmQEHAbsBtAIZA2YCAAG1Av8BuwEIAp8BfgF5AvQBbAEZA2YCAAEOAe8BBwEA
AfAC8QLyAfABDgMAAewBegEcAZoDegJZAVMBUgExAUsB6gIAAbUC/wGTAZoBegGfAZ4BuwH0AfMBZgEZ
AWYCAAG1Av8C2wEJAQgBfgF5Af8B9AFsAfMBZgEZAWYCAAEOAgAB7wG8AfAC8QHyAfABDgMAAe0BegEc
AZkFegJZAVMBMQFEAe0BAAG1Av8BuwEIAp8BfgF5AvQBbAEZA2YBBwr/AWwB9AFsARkBZgIAAQ4B8AIH
ArwC8AHxAbwBDgMAAe0BmgF6ARwBmgV6A1kBSwFtAQABtQL/AtsBCQEIAX4BeQH/AfQBbAHzAWYBGQFm
AgcEtQH3AbUC7QKRAfQBbAHzAWYCAAEOAfADBwK8AvABvAEOAwABHAGaAXoBHAGZB3oBWQFSAUoB7QEH
Cv8BbAH0AWwBGQFmAbUB/wEHCv8BbAH0AWwCAAEOAfAEBwK8AfABvAEOAwABHAGaAaABegEcB5oCegF0
AW0CBwS1AfcBtQLtApEB9AFsAfMBZgG1Af8CBwS1AfcBtQLtApEB9AFsAgABDgHwAu8EBwG8AQcBDgMA
ARwDoAgcAu0B7AFzAgABBwr/AWwB9AFsAQcD/wEHCv8BbAIAAQ4B8APvBQcBDgMAARwEoAGaBnoBcwUA
AgcEtQH3AbUC7QKRAfQBbAIHArUCBwS1AfcBtQLtApECAAEOAbwE7wQHAQ4DAAEcAaABwwOgAXoDHALt
AXMHAAEHCv8BbAIAAQcK/wFsAfQBbAIAAQ4BvAXvAwcBDgMAARwBmQLDAqABHAHtDAACBwS1AfcBtQLt
ApECAAIHBLUB9wG1Au0CkQH0AWwCAAEOAfQD8AO8AgcBDgQABRwB7R0AAQcK/wFsAgALDicAAgcEtQH3
AbUC7QKR4AABQgFNAT4HAAE+AwABKAMAAUADAAFCAwABAQEAAQEFAAEQAQIWAAP/sQAZ/wHDAcABAQH+
AX8BgAEBAeABAQGAAQAB+AEfAYABAQHAAQECAAHgAQcBgAEBAYABAQIAAcABAQGAAQEB4AEjAgABgAEB
AYABAQHAASMCAAGAAQEBgAEBAcABIwIAAYABAAGAAQEBwAEjAgABgAEAAYABAQHAASMBAAEBAYABAAGA
AQEBwAEjAQABAQGAAQABgAEBAcABIwEAAQEBgAEAAYABAQHAASMBgAEBAYABAAGAAQEBwAEjAcABAQHA
AQABgAEDAYABAQHwAQEB4AEAAYABBwHAAQEB8AEBAfgBAQGAAQ8B4AEDAfABAwH+AX8BgAEfMv8BAAEP
Bv8BAAEPAfgBBwL/AQABDwEAAQMB8AEHAQABBwEAAQ8BAAEDAeABBwEAAQMBAAEDAgABwAEHAQABAwEA
AQMCAAHAAQcBAAEBBAABwAEHAQABAQQAAcABBwYAAcABBwYAAcABBwIAAcADAAHAAQcBAAEHAcADAAHA
AQcBAAEHAfABAAHAAQABwAEHAQAB/wHwAQABwAEAAcABBwGBA/8B8AEAAcABBwT/AfABABz/Cw==
</value>
</data>
<metadata name="$this.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">