GZDoom Builder 1.11a:

Things can now be cut, copied and pasted in Visual modes.
Sector geometry was not updated properly after Undo/Redo in GZDoom Visual mode.
Fixed an error when user selects multiple things and attempts to view their properties in Doom map format.
Added Decorate and Modeldef syntax hilighting, autocompletion and item recognition to Script editor.
Script Editor can now autodetect several script types when you open them (currently ACS, Decorate and Modeldef scripts are recognized).
Tag Explorer: fixed a bug when Tag Explorer update can block keyboard keys release detection logic.
This commit is contained in:
MaxED 2012-07-16 09:45:21 +00:00
parent 8891395b3a
commit 87731c9650
26 changed files with 1062 additions and 320 deletions

View file

@ -0,0 +1,35 @@
/*******************************************************************\
GZDoom Builder Script highlighting definitions for MODELDEF
\*******************************************************************/
// Editor settings
description = "GZDoom MODELDEF";
codepage = 0;
extensions = "mdd";
casesensitive = false;
insertcase = 1; // 0=Normal, 1=Lowercase, 2=Uppercase
lexer = 35; // CPP-style, case-insensitive
keywordhelp = "http://zdoom.org/wiki/MODELDEF";
keywords
{
Path = "Path <\"path\">";
Model = "Model <model index> <\"model file\">";
Skin = "Skin <model index> <\"skin file\">";
Scale = "Scale <float X scale> <float Y scale> <float Z scale>";
Frame = "Frame <XXXX> <X> <model index> <\"frame name\">";
FrameIndex = "FrameIndex <XXXX> <X> <model index> <frame number>";
Rotation-Speed = "Rotation-Speed <float>";
Rotation-Vector = "Rotation-Vector <float x> <float y> <float z>";
Rotation-Center = "Rotation-Center <float x> <float y> <float z>";
ZOffset = "ZOffset <float>";
}
constants
{
PITCHFROMMOMENTUM;
IGNORETRANSLATION;
INTERPOLATEDOUBLEDFRAMES;
ROTATING;
NOINTERPOLATION;
}

View file

@ -1,5 +1,5 @@
/*******************************************************************\
GZDoom Builder Script highlighting definitions for DECORATE
GZDoom Builder Script highlighting definitions for DECORATE
\*******************************************************************/
// Editor settings
@ -7,29 +7,32 @@ description = "ZDoom DECORATE";
codepage = 0;
extensions = "txt";
casesensitive = false;
insertcase = 1; // 0=Normal, 1=Lowercase, 2=Uppercase
lexer = 35; // CPP-style, case-insensitive
insertcase = 0; // 0=Normal, 1=Lowercase, 2=Uppercase
lexer = 35;
functionopen = "(";
functionclose = ")";
argumentdelimiter = ",";
terminator = ";";
keywordhelp = "http://www.zdoom.org/wiki/index.php?title=%K";
keywords
{
#Include = "#Include";
#Include = "#Include";
//Monster AI
A_AlertMonsters = "A_AlertMonsters(float maxrange)";
A_Burst = "A_Burst(string classname)";
A_CentaurDefend = "A_CentaurDefend";
A_Chase = "A_Chase[(str \"MeleeState\"[, str \"RangedState\"[, int Flags]])]";
A_ClearLastHeard = "A_ClearLastHeard";
A_ClearSoundTarget = "A_ClearSoundTarget";
A_ClearTarget = "A_ClearTarget";
A_DamageChildren = "A_DamageChildren(int amount, [string type])";
A_DamageMaster = "A_DamageMaster(int amount, [string type])";
A_DamageSiblings = "A_DamageSiblings(int amount, [string type])";
A_Die = "A_Die[(str DamageType)]";
A_FaceTarget = "A_FaceTarget[(float angle)[, float pitch]]";
A_FaceMaster = "A_FaceMaster[(float angle)[, float pitch]]";
A_KillChildren = "A_KillChildren(string damagetype)";
A_Burst = "A_Burst(string classname)";
A_CentaurDefend = "A_CentaurDefend";
A_Chase = "A_Chase[(str \"MeleeState\"[, str \"RangedState\"[, int Flags]])]";
A_ClearLastHeard = "A_ClearLastHeard";
A_ClearSoundTarget = "A_ClearSoundTarget";
A_ClearTarget = "A_ClearTarget";
A_DamageChildren = "A_DamageChildren(int amount, [string type])";
A_DamageMaster = "A_DamageMaster(int amount, [string type])";
A_DamageSiblings = "A_DamageSiblings(int amount, [string type])";
A_Die = "A_Die[(str DamageType)]";
A_FaceTarget = "A_FaceTarget[(float angle)[, float pitch]]";
A_FaceMaster = "A_FaceMaster[(float angle)[, float pitch]]";
A_KillChildren = "A_KillChildren(string damagetype)";
A_KillMaster = "A_KillMaster(string damagetype)";
A_KillSiblings = "A_KillSiblings(string damagetype)";
A_Look2 = "A_Look2";
@ -44,10 +47,313 @@ keywords
A_Teleport = "A_Teleport[(string teleportstate[, string targettype[, string fogtype[, int flags[, float mindist[, float maxdist]]]]])]";
A_VileChase = "A_VileChase";
A_Wander = "A_Wander";
//Generic monster attacks
A_CustomMissile = "A_CustomMissile(string missiletype[, float spawnheight[, int spawnofs_horiz[, angle angle[, int aimflags[, angle pitch]]]]])";
A_CustomBulletAttack = "A_CustomBulletAttack(float horz_spread, float vert_spread, int numbullets, int damageperbullet, string pufftype [, float range [, int flags]])";
A_CustomRailgun = "A_CustomRailgun(int damage [, int offset [, color ringcolor [, color corecolor [, int flags [, bool aim [, float maxdiff [, str pufftype[, float spread_xy[, float spread_z [, fixed range [, int duration [, float sparsity [, float driftspeed [, str spawnclass]]]]]]]]]]]]]])";
A_CustomMeleeAttack = "A_CustomMeleeAttack(int damage[, str meleesound[, str misssound[, str damagetype[, bool bleed]]]])";
A_CustomComboAttack = "A_CustomComboAttack(string missiletype, float spawnheight, int damage, string meleesound, string damagetype, bool bleed)";
A_MeleeAttack = "A_MeleeAttack";
A_MissileAttack = "A_BasicAttack(int meleedamage, string meleesound, string missiletype, float missileheight)";
A_MonsterRefire = "A_MonsterRefire(int chancecontinue, str \"abortstate\") ";
A_ComboAttack = "A_ComboAttack";
A_BasicAttack = "A_BasicAttack(int meleedamage, string meleesound, string missiletype, float missileheight)";
A_BulletAttack = "A_BulletAttack";
A_MonsterRail = "A_MonsterRail";
A_Explode = "A_Explode[(int explosiondamage [, int explosionradius [, bool hurtshooter [, bool alert[, int fulldamageradius[, int nails[, int naildamage]]]]]])]";
A_RadiusThrust = "A_RadiusThrust(int force, int distance[, int flags[, int fullthrustdistance]])";
A_Detonate = "A_Detonate";
A_ThrowGrenade = "A_ThrowGrenade(string spawntype [float spawnheight [, float throwspeed_horz [, float throwspeed_vert [, bool useammo]]]])";
//Freeze death functions
A_FreezeDeath = "A_FreezeDeath";
A_GenericFreezeDeath = "A_GenericFreezeDeath";
A_FreezeDeathChunks = "A_FreezeDeathChunks";
A_IceGuyDie = "A_IceGuyDie";
//Sound functions
A_PlaySound = "A_PlaySound(string soundname[, int slot[, float volume[, bool looping[, float attenuation]]]])";
A_PlaySoundEx = "A_PlaySoundEx(string soundname, string channel [, bool loop [, int attenuation]])";
A_PlayWeaponSound = "A_PlayWeaponSound(string soundname)";
A_ActiveSound = "A_ActiveSound";
A_LoopActiveSound = "A_LoopActiveSound";
A_FLoopActiveSound = "A_FLoopActiveSound";
A_StopSound = "A_StopSound[(int slot)]";
A_StopSoundEx = "A_StopSoundEx(string channel)";
A_Pain = "A_Pain";
A_Scream = "A_Scream";
A_XScream = "A_XScream";
A_PlayerScream = "A_PlayerScream";
A_VileStart = "A_VileStart";
A_BrainPain = "A_BrainPain";
A_BrainAwake = "A_BrainAwake";
A_BFGSound = "A_BFGSound";
//Print actions
A_Print = "A_Print(string text[, float time[, string fontname]])";
A_PrintBold = "A_PrintBold(string text[, float time[, string fontname]])";
A_Log = "A_Log(string text)";
A_LogInt = "A_LogInt(int number)";
//Special actions
A_BossDeath = "A_BossDeath";
A_KeenDie = "A_KeenDie[(int tag)]";
A_BrainDie = "A_BrainDie";
A_GetHurt = "A_GetHurt";
A_KlaxonBlare = "A_KlaxonBlare";
A_CheckTerrain = "A_CheckTerrain";
A_SetBlend = "A_SetBlend(color blendcolor, float alpha, int duration[, color fadecolor])";
A_CheckPlayerDone = "A_CheckPlayerDone";
A_PlayerSkinCheck = "A_PlayerSkinCheck(str state)";
A_SkullPop = "A_SkullPop[(string className)]";
//Spawn functions
A_TossGib = "A_TossGib";
A_SpawnDebris = "A_SpawnDebris(string type, bool translation)";
A_SpawnItem = "A_SpawnItem(string type, int distance, float zpos, bool useammo, bool translation)";
A_SpawnItemEx = "A_SpawnItemEx(string type, float xoffset, float yoffset, float zoffset, float xvelocity, float yvelocity, float zvelocity, float angle, int flags, int chance)";
//State jumps
A_CheckCeiling = "A_CheckCeiling(int offset OR str \"state\")";
A_CheckFloor = "A_CheckFloor(int offset OR str \"state\")";
A_CheckFlag = "A_CheckFlag(string flagname, state label, int check_pointer = AAPTR_DEFAULT)";
A_CheckSight = "A_CheckSight(int offset OR str \"state\")";
A_CheckSightOrRange = "A_CheckSightOrRange(float distance, int offset OR str \"state\")";
A_Jump = "A_Jump(int chance, int offset OR str \"state\", ...)";
A_JumpIf = "A_JumpIf(expression, int offset OR str \"state\")";
A_JumpIfArmorType = "A_JumpIfArmorType(string \"armortype\", str \"state\"[, int minimum])";
A_JumpIfCloser = "A_JumpIfCloser(int distance, int offset OR str \"state\")";
A_JumpIfHealthLower = "A_JumpIfHealthLower(int health, int offset OR str \"state\")";
A_JumpIfInventory = "A_JumpIfInventory (string \"inventorytype\", int amount, int offset OR str \"state\" [, int owner])";
A_JumpIfInTargetInventory = "A_JumpIfInTargetInventory(str \"item\", int count, int offset OR str \"state\" [, pointer forward])";
A_JumpIfInTargetLOS = "A_JumpIfInTargetLOS(int offset OR str \"state\" [, float fov[, int flags[, float dist_max[, float dist_close]]]])";
A_JumpIfMasterCloser = "A_JumpIfMasterCloser(int distance, int offset OR str \"state\")";
A_JumpIfNoAmmo = "A_JumpIfNoAmmo(int offset OR str \"state\")";
A_JumpIfTargetInLOS = "A_JumpIfTargetInLOS(int offset OR str \"state\" [, float fov[, int flags[, float dist_max[, float dist_close]]]])";
A_JumpIfTracerCloser = "A_JumpIfTracerCloser (int distance, int offset OR str \"state\")";
//Status changes
A_ActiveAndUnblock = "A_ActiveAndUnblock";
A_ChangeFlag = "A_ChangeFlag(string flagname, bool value)";
A_ChangeVelocity = "A_ChangeVelocity(float x, float y, float z, int flags)";
A_ClearShadow = "A_ClearShadow";
A_CopyFriendliness = "A_CopyFriendliness[(pointer copyfrom)]";
A_DeQueueCorpse = "A_DeQueueCorpse";
A_FadeIn = "A_FadeIn[(float increase_amount)]";
A_FadeOut = "A_FadeOut[(float reduce_amount[, bool remove])]";
A_FadeTo = "A_FadeTo(float target[, float amount[, bool remove]])";
A_Fall = "A_Fall";
A_Gravity = "A_Gravity";
A_HideThing = "A_HideThing";
A_LowGravity = "A_LowGravity";
A_NoBlocking = "A_NoBlocking";
A_NoGravity = "A_NoGravity";
A_QueueCorpse = "A_QueueCorpse";
A_RearrangePointers = "A_RearrangePointers(pointer target, pointer master, pointer tracer[, int flags])";
A_Respawn = "A_Respawn[(bool fog)]";
A_ScaleVelocity = "A_ScaleVelocity(float scale)";
A_ScreamAndUnblock = "A_ScreamAndUnblock";
A_SetAngle = "A_SetAngle(float angle)";
A_SetArg = "A_SetArg(int position, int value)";
A_SetFloat = "A_SetFloat";
A_SetFloorClip = "A_SetFloorClip";
A_SetInvulnerable = "A_SetInvulnerable";
A_SetMass = "A_SetMass(int mass)";
A_SetPitch = "A_SetPitch(float pitch[, int flags])";
A_SetReflective = "A_SetReflective";
A_SetReflectiveInvulnerable = "A_SetReflectiveInvulnerable";
A_SetScale = "A_SetScale(float scaleX[, float scaleY])";
A_SetShadow = "A_SetShadow";
A_SetShootable = "A_SetShootable";
A_SetSolid = "A_SetSolid";
A_SetSpecial = "A_SetSpecial(int special, int arg0, int arg1, int arg2, int arg3, int arg4)";
A_SetTranslucent = "A_SetTranslucent(float alpha, int mode)";
A_SetUserVar = "A_SetUserVar(string name, int value)";
A_TransferPointer = "A_TransferPointer(pointer source, pointer recipient, pointer sourcefield, pointer recipientfield[, int flags])";
A_UnHideThing = "A_UnHideThing";
A_UnsetFloat = "A_UnsetFloat";
A_UnSetFloorClip = "A_UnSetFloorClip";
A_UnSetInvulnerable = "A_UnSetInvulnerable";
A_UnSetReflective = "A_UnSetReflective";
A_UnSetReflectiveInvulnerable = "A_UnSetReflectiveInvulnerable";
A_UnSetShootable = "A_UnSetShootable";
A_UnsetSolid = "A_UnsetSolid";
//Missile movement
A_SeekerMissile = "A_SeekerMissile(angle threshold, angle maxturnangle, int flags = 0, int chance = 50, int distance = 10)";
A_Tracer = "A_Tracer";
A_Tracer2 = "A_Tracer2";
A_FaceTracer = "A_FaceTracer[(float angle)[, float pitch]]";
A_Fire = "A_Fire[(int height)]";
A_BishopMissileWeave = "A_BishopMissileWeave";
A_CStaffMissileSlither = "A_CStaffMissileSlither";
A_Weave = "A_Weave(int horzspeed, int vertspeed, float horzdist, float vertdist)";
A_Warp = "A_Warp(int ptr_destination, float x-offset, float y-offset, float z-offset, float angle, int flags , state success_state)";
A_Countdown = "A_Countdown";
A_CountdownArg = "A_CountdownArg(int arg[, str targstate])";
A_Stop = "A_Stop";
//Inventory functions
A_GiveInventory = "A_GiveInventory(string type, int count[, pointer giveto])";
A_GiveToTarget = "A_GiveToTarget(string type, int count[, pointer giveto])";
A_TakeInventory = "A_TakeInventory(string type, int count[, int flags[, pointer takefrom]])";
A_TakeFromTarget = "A_TakeFromTarget(string type, int count[, pointer takefrom])";
A_DropInventory = "A_DropInventory(string type)";
A_SelectWeapon = "A_SelectWeapon(string type)";
A_RadiusGive = "A_RadiusGive(str item, fixed distance, int flags, int amount)";
//Weapon functions
A_WeaponReady = "A_WeaponReady[(int flags)]";
A_Lower = "A_Lower";
A_Raise = "A_Raise";
A_ReFire = "A_ReFire[(str \"state\")]";
A_ClearReFire = "A_ClearReFire";
A_GunFlash = "A_GunFlash[(str state[, int flags])]";
A_CheckReload = "A_CheckReload";
A_CheckForReload = "A_CheckForReload(int counter, str state[, bool dontincrement])";
A_ResetReloadCounter = "A_ResetReloadCounter";
A_Light = "A_Light(int intensity)";
A_Light0 = "A_Light0";
A_Light1 = "A_Light1";
A_Light2 = "A_Light2";
A_LightInverse = "A_LightInverse";
A_Recoil = "A_Recoil(float force)";
A_ZoomFactor = "A_ZoomFactor(float zoom [, int flags])";
A_SetCrosshair = "A_SetCrosshair(int number)";
//Weapon attack functions
A_Punch = "A_Punch";
A_Saw = "A_Saw[(string fullsound [, string hitsound [, int damage [, string pufftype[, int flags[, float range[, float spread_xy[, float spread_z[, float lifesteal]]]]]]]])]";
A_CustomPunch = "A_CustomPunch(int damage [, bool norandom [, int flags [, string pufftype, [float range[, float lifesteal]]]]])";
A_FireBullets = "A_FireBullets(angle spread_horz, angle spread_vert, int numbullets, int damage [, string pufftype [,int flags [, float range]]])";
A_FireCustomMissile = "A_FireCustomMissile(string missiletype [, angle angle [, bool useammo [, int spawnofs_horz [, int spawnheight [, bool aim[, angle pitch]]]]]])";
A_RailAttack = "A_RailAttack(int damage [, int spawnofs_horz [, bool useammo [, color ringcolor [, color corecolor [, int flags [, int maxdiff [, str pufftype [, float spread_xy [, float spread_z [, fixed range [, int duration [, float sparsity [, float driftspeed [, str spawnclass]]]]]]]]]]]]]])";
A_FireAssaultGun = "A_FireAssaultGun";
A_FireBFG = "A_FireBFG";
A_FireOldBFG = "A_FireOldBFG";
A_FireShotgun = "A_FireShotgun";
A_FireShotgun2 = "A_FireShotgun2";
A_FireCGun = "A_FireCGun";
A_FireMissile = "A_FireMissile";
A_FirePlasma = "A_FirePlasma";
//Script functions
ACS_NamedExecute = "ACS_NamedExecute(string script, int map, int s_arg1, int s_arg2, int s_arg3):bool";
ACS_NamedSuspend = "ACS_NamedSuspend(string script, int map):bool";
ACS_NamedTerminate = "ACS_NamedTerminate(string script, int map):bool";
ACS_NamedLockedExecute = "ACS_NamedLockedExecute(string script, int map, int s_arg1, int s_arg2, int lock):bool";
ACS_NamedLockedExecuteDoor = "ACS_NamedLockedExecuteDoor(string script, int map, int s_arg1, int s_arg2, int lock):bool";
ACS_NamedExecuteWithResult = "ACS_NamedExecuteWithResult(string script, int s_arg1, int s_arg2, int s_arg3):int";
ACS_NamedExecuteAlways = "ACS_NamedExecuteAlways(string script, int map, int s_arg1, int s_arg2, int s_arg3):bool";
//Original Doom/Strife monster attacks
A_PosAttack = "A_PosAttack";
A_SPosAttack = "A_SPosAttack";
A_CPosAttack = "A_CPosAttack";
A_CPosRefire = "A_CPosRefire";
A_SpidRefire = "A_SpidRefire";
A_TroopAttack = "A_TroopAttack";
A_SargAttack = "A_SargAttack";
A_HeadAttack = "A_HeadAttack";
A_BruisAttack = "A_BruisAttack";
A_SkullAttack = "A_SkullAttack[(int speed)]";
A_BspiAttack = "A_BspiAttack";
A_CyberAttack = "A_CyberAttack";
A_PainAttack = "A_PainAttack[(string spawntype)[, float angle[, int flags[, int limit]]]]";
A_DualPainAttack = "A_DualPainAttack[(string spawntype)]";
A_PainDie = "A_PainDie[(string spawntype)]";
A_SkelFist = "A_SkelFist";
A_SkelMissile = "A_SkelMissile";
A_FatAttack1 = "A_FatAttack1[(string spawntype)]";
A_FatAttack2 = "A_FatAttack2[(string spawntype)]";
A_FatAttack3 = "A_FatAttack3[(string spawntype)]";
A_VileTarget = "A_VileTarget[(string type)]";
A_VileAttack = "A_VileAttack(str sound, int initialdamage, int blastdamage, int blastradius, float thrustfactor, str damagetype)";
A_BrainSpit = "A_BrainSpit[(string spawntype)]";
A_SpawnFly = "A_SpawnFly[(string FogActor)]";
A_SpawnSound = "A_SpawnSound";
A_BrainScream = "A_BrainScream";
A_BrainExplode = "A_BrainExplode";
A_Mushroom = "A_Mushroom[(string spawntype [, int amount[, int flags[, float vrange[, float hrange]]]])]";
A_M_Saw = "A_M_Saw[(string fullsound [, string hitsound [, int damage [, string pufftype]]])]";
A_SentinelRefire = "A_SentinelRefire";
A_BetaSkullAttack = "A_BetaSkullAttack";
//Miscellaneous functions for Doom
A_Hoof = "A_Hoof";
A_Metal = "A_Metal";
A_BabyMetal = "A_BabyMetal";
A_FatRaise = "A_FatRaise";
A_SkelWhoosh = "A_SkelWhoosh";
A_StartFire = "A_StartFire";
A_FireCrackle = "A_FireCrackle";
A_BFGSpray = "A_BFGSpray[(string flashtype [, int numrays [, int damage]])]";
A_BarrelDestroy = "A_BarrelDestroy";
//state keywords
Light = "Light(string lightname)";
Offset = "Offset(int x, int y)";
}
constants
{
Actor;
//states:
Spawn:;
Idle:;
See:;
Melee:;
Missile:;
Pain:;
Death:;
XDeath:;
Burn:;
Ice:;
Disintegrate:;
Raise:;
Heal:;
Crash:;
Crush:;
Wound:;
Greetings:;
Yes:;
No:;
Active:;
Inactive:;
//State keywords
//Bright;
Fast;
//flow control
loop;
stop;
wait;
fail;
goto;
//pointers
AAPTR_DEFAULT;
AAPTR_NULL;
AAPTR_TARGET;
AAPTR_MASTER;
AAPTR_TRACER;
AAPTR_PLAYER;
AAPTR_PLAYER_GETTARGET;
AAPTR_PLAYER_GETCONVERSATION;
SXF_SETMASTER;
SXF_TRANSFERPOINTERS;
//weapon flags
WRF_NOBOB;
WRF_NOFIRE;
WRF_NOSWITCH;
WRF_NOPRIMARY;
WRF_NOSECONDARY;
WRF_ALLOWRELOAD;
WRF_ALLOWZOOM;
ZOOM_INSTANT;
ZOOM_NOSCALETURNING;
CPF_USEAMMO;
CPF_DAGGER;
CPF_PULLIN;
FBF_USEAMMO;
FBF_NORANDOM;
FBF_EXPLICITANGLE;
FBF_NOPITCH;
RGF_SILENT;
RGF_NOPIERCING;
RGF_EXPLICITANGLE;
RGF_FULLBRIGHT;
//monster flags
PAF_NOSKULLATTACK;
PAF_AIMFACING;
PAF_NOTARGET;
//misc flags
MSF_Standard;
MSF_Classic;
MSF_DontHurt;
//combo flags
Monster;
Projectile;

View file

@ -27,7 +27,7 @@
<li>Fog rendering (including colored fog in maps in UDMF format).</li>
<li><a href="gz_gldefs.html">MD2 and MD3 models</a> rendering in 2D and 3D modes.</li>
<li><a href="gz_mode_drawrect.html">Draw Rectangle</a>, <a href="gz_mode_drawellipse.html">Draw Ellipse</a> and <a href="gz_mode_drawbridge.html">Bridge</a> modes.</li>
<li>Ability to <a href="gz_actions.html#movething">move</a>, insert and delete Things in Visual modes.</li>
<li>Ability to <a href="gz_actions.html#movething">move</a>, cut, copy, paste, insert and delete Things in Visual modes.</li>
<li><a href="gz_actions.html#newtestmap">"Test Map from current position"</a> feature.</li>
<li><a href="gz_settings.html">"Sync camera position between 2D and 3D modes"</a> feature.</li>
<li><a href="gz_actions.html#movethingtocursor">"Place Things at cursor position in Visual Modes"</a> feature.</li>

View file

@ -719,14 +719,17 @@
<Compile Include="GZBuilder\Data\MapInfo.cs" />
<Compile Include="GZBuilder\Data\ModeldefEntry.cs" />
<Compile Include="GZBuilder\Data\ScriptItem.cs" />
<Compile Include="GZBuilder\Data\ScriptType.cs" />
<Compile Include="GZBuilder\Data\TextureData.cs" />
<Compile Include="GZBuilder\Data\ThingBoundingBox.cs" />
<Compile Include="GZBuilder\Data\ThingCopyData.cs" />
<Compile Include="GZBuilder\GZDoom\DecorateParserSE.cs" />
<Compile Include="GZBuilder\GZDoom\GldefsParser.cs" />
<Compile Include="GZBuilder\GZDoom\MapinfoParser.cs" />
<Compile Include="GZBuilder\GZDoom\ModeldefParser.cs" />
<Compile Include="GZBuilder\GZDoom\ModeldefParserSE.cs" />
<Compile Include="GZBuilder\GZDoom\ModeldefStructure.cs" />
<Compile Include="GZBuilder\GZDoom\ScriptTypeParserSE.cs" />
<Compile Include="GZBuilder\GZGeneral.cs" />
<Compile Include="GZBuilder\md3\GZModel.cs" />
<Compile Include="GZBuilder\md3\ModelReader.cs" />

View file

@ -13,6 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UDMFControls", "..\Plugins\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColorPicker", "..\Plugins\ColorPicker\ColorPicker.csproj", "{A4761900-0EA3-4FE4-A919-847FD5080EFC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommentsPanel", "..\Plugins\CommentsPanel\CommentsPanel.csproj", "{58BD8A5B-1B48-435D-8473-A92F27D06C49}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -83,6 +85,16 @@ Global
{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|Mixed Platforms.Build.0 = Release|x86
{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|x86.ActiveCfg = Release|x86
{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|x86.Build.0 = Release|x86
{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Debug|Any CPU.ActiveCfg = Debug|x86
{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Debug|Mixed Platforms.Build.0 = Debug|x86
{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Debug|x86.ActiveCfg = Debug|x86
{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Debug|x86.Build.0 = Debug|x86
{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Release|Any CPU.ActiveCfg = Release|x86
{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Release|Mixed Platforms.ActiveCfg = Release|x86
{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Release|Mixed Platforms.Build.0 = Release|x86
{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Release|x86.ActiveCfg = Release|x86
{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View file

@ -107,6 +107,8 @@ namespace CodeImp.DoomBuilder.Config
this.title = "Argument " + (argindex + 1);
this.type = 0;
this.enumlist = new EnumList();
//mxd
this.defaultValue = 0;
}
#endregion

View file

@ -58,14 +58,6 @@ namespace CodeImp.DoomBuilder.Controls
protected ScriptEditorControl editor;
//mxd
protected ComboBox navigator;
protected enum ScriptTypes : int
{
ACS = 0,
MODELDEF = 1,
DECORATE = 2,
}
private string[] knownScriptTypes = { "ZDoom ACS script", "GZDoom MODELDEF", "ZDoom DECORATE" };
protected string[] KNOWN_SCRIPT_TYPES { get { return knownScriptTypes; } }
// Derived classes must set this!
protected ScriptConfiguration config;
@ -325,110 +317,82 @@ namespace CodeImp.DoomBuilder.Controls
//mxd
protected void updateNavigator() {
//mxd. known script type?
if (Array.IndexOf(KNOWN_SCRIPT_TYPES, config.Description) != -1)
navigator.Enabled = updateNavigator(new MemoryStream(editor.GetText()), config.Description);
if(navigator.Enabled)
if (Array.IndexOf(ScriptTypes.TYPES, config.Description) != -1) {
updateNavigator(new MemoryStream(editor.GetText()), config.Description);
navigator.Enabled = true;
navigator.SelectedIndexChanged += new EventHandler(navigator_SelectedIndexChanged);
}else{
navigator.Items.Clear();
navigator.Enabled = false;
}
}
//mxd
private bool updateNavigator(MemoryStream stream, string scriptType) {
if (scriptType == KNOWN_SCRIPT_TYPES[(int)ScriptTypes.ACS]) //ZDoom ACS script
return updateNavigatorAcs();
if (scriptType == KNOWN_SCRIPT_TYPES[(int)ScriptTypes.MODELDEF]) //GZDoom MODELDEF
return updateNavigatorModeldef(stream);
if (scriptType == KNOWN_SCRIPT_TYPES[(int)ScriptTypes.DECORATE])
return updateNavigatorDecorate(stream);
return false;
private void updateNavigator(MemoryStream stream, string scriptType) {
if (scriptType == ScriptTypes.TYPES[(int)ScriptType.ACS]) {
updateNavigatorAcs(stream);
} else if (scriptType == ScriptTypes.TYPES[(int)ScriptType.MODELDEF]) {
updateNavigatorModeldef(stream);
} else if (scriptType == ScriptTypes.TYPES[(int)ScriptType.DECORATE]) {
updateNavigatorDecorate(stream);
}
}
//mxd
private bool updateNavigatorDecorate(MemoryStream stream) {
if (stream == null) return false;
string selectedItem = "";
int selectedIndex = 0;
if (navigator.SelectedIndex != -1) selectedItem = navigator.Text;
private void updateNavigatorDecorate(MemoryStream stream) {
if (stream == null) return;
navigator.Items.Clear();
DecorateParserSE parser = new DecorateParserSE();
parser.Parse(stream, "DECORATE");
if (parser.Actors.Count == 0)
return false;
if (parser.Actors.Count == 0) return;
ScriptItem[] models = new ScriptItem[parser.Actors.Count];
int i = 0;
foreach (ScriptItem si in parser.Actors) {
models[i++] = si;
if (si.Name == selectedItem) selectedIndex = i - 1;
}
navigator.Items.AddRange(models);
return true;
navigator.Items.AddRange(parser.Actors.ToArray());
}
//mxd
private bool updateNavigatorModeldef(MemoryStream stream) {
if (stream == null) return false;
string selectedItem = "";
int selectedIndex = 0;
if (navigator.SelectedIndex != -1) selectedItem = navigator.Text;
private void updateNavigatorModeldef(MemoryStream stream) {
if (stream == null) return;
navigator.Items.Clear();
ModeldefParserSE parser = new ModeldefParserSE();
parser.Parse(stream, "MODELDEF");
if (parser.Models.Count == 0)
return false;
if (parser.Models.Count == 0) return;
ScriptItem[] models = new ScriptItem[parser.Models.Count];
int i = 0;
foreach (ScriptItem si in parser.Models) {
models[i++] = si;
if (si.Name == selectedItem) selectedIndex = i - 1;
}
navigator.Items.AddRange(models);
return true;
navigator.Items.AddRange(parser.Models.ToArray());
}
//mxd
private bool updateNavigatorAcs() {
string selectedItem = "";
int selectedIndex = 0;
if (navigator.SelectedIndex != -1) selectedItem = navigator.Text;
private void updateNavigatorAcs(MemoryStream stream) {
if (stream == null) return;
navigator.Items.Clear();
//add named scripts
int i = 0;
if (General.Map.UDMF) {
ScriptItem[] namedScripts = new ScriptItem[General.Map.NamedScripts.Count];
foreach (ScriptItem si in General.Map.NamedScripts) {
namedScripts[i++] = si;
if (si.Name == selectedItem) selectedIndex = i - 1;
}
navigator.Items.AddRange(namedScripts);
}
AcsParserSE parser = new AcsParserSE();
parser.Parse(stream, "ACS");
//add numbered scripts
ScriptItem[] numberedScripts = new ScriptItem[General.Map.NumberedScripts.Count];
int c = 0;
foreach (ScriptItem si in General.Map.NumberedScripts) {
numberedScripts[c++] = si;
if (si.Name == selectedItem) selectedIndex = i - 1 + c;
}
navigator.Items.AddRange(numberedScripts);
if (parser.NamedScripts.Count == 0 && parser.NumberedScripts.Count == 0) return;
if (navigator.Items.Count > 0) {
navigator.SelectedIndex = selectedIndex;
return true;
}
return false;
if(General.Map.UDMF)
navigator.Items.AddRange(parser.NamedScripts.ToArray());
navigator.Items.AddRange(parser.NumberedScripts.ToArray());
}
//mxd
internal ScriptType VerifyScriptType() {
ScriptTypeParserSE parser = new ScriptTypeParserSE();
if (parser.Parse(new MemoryStream(editor.GetText()), config.Description)) {
if (parser.ScriptType != (int)ScriptType.UNKNOWN && config.Description != ScriptTypes.TYPES[(int)parser.ScriptType])
return parser.ScriptType;
}
return ScriptType.UNKNOWN;
}
#endregion
#region ================== Events

View file

@ -33,6 +33,7 @@ using CodeImp.DoomBuilder.IO;
using System.Globalization;
using System.IO;
using CodeImp.DoomBuilder.Compilers;
using CodeImp.DoomBuilder.GZBuilder.Data;
#endregion
@ -521,7 +522,19 @@ namespace CodeImp.DoomBuilder.Controls
ScriptFileDocumentTab t = new ScriptFileDocumentTab(this, foundconfig);
if(t.Open(filename))
{
// Mark any errors this script may have
//mxd
ScriptType st = t.VerifyScriptType();
if (st != ScriptType.UNKNOWN) {
string cfgType = ScriptTypes.TYPES[(int)st];
foreach (ScriptConfiguration cfg in scriptconfigs) {
if (cfg.Description == cfgType) {
t.ChangeScriptConfig(cfg);
break;
}
}
}
// Mark any errors this script may have
if(compilererrors != null)
t.MarkScriptErrors(compilererrors);

View file

@ -31,6 +31,9 @@ using CodeImp.DoomBuilder.Types;
using CodeImp.DoomBuilder.IO;
using System.IO;
using CodeImp.DoomBuilder.Compilers;
//mxd
using CodeImp.DoomBuilder.GZBuilder.Data;
using CodeImp.DoomBuilder.GZBuilder.GZDoom;
#endregion
@ -70,7 +73,7 @@ namespace CodeImp.DoomBuilder.Controls
SetTitle("Untitled" + ext);
editor.ClearUndoRedo();
//mxd
navigator.Enabled = Array.IndexOf(KNOWN_SCRIPT_TYPES, config.Description) != -1;
navigator.Enabled = Array.IndexOf(ScriptTypes.TYPES, config.Description) != -1;
}
// Disposer
@ -190,10 +193,10 @@ namespace CodeImp.DoomBuilder.Controls
// This opens a file and returns true when successful
public bool Open(string filepathname)
{
try
try
{
// Read the file
editor.SetText(File.ReadAllBytes(filepathname));
editor.SetText(File.ReadAllBytes(filepathname));
}
catch(Exception e)
{
@ -208,6 +211,7 @@ namespace CodeImp.DoomBuilder.Controls
this.filepathname = filepathname;
SetTitle(Path.GetFileName(filepathname));
editor.ClearUndoRedo();
return true;
}

View file

@ -87,6 +87,8 @@ namespace CodeImp.DoomBuilder.Controls
{
editor.SetText(stream.ToArray());
editor.ClearUndoRedo();
//mxd
updateNavigator();
}
// Done
@ -117,10 +119,6 @@ namespace CodeImp.DoomBuilder.Controls
// Feed errors to panel
panel.ShowErrors(General.Map.Errors);
//mxd
if (config.Description == KNOWN_SCRIPT_TYPES[(int)ScriptTypes.ACS] && General.Map.Errors.Count == 0)
General.Map.UpdateScriptNames();
}
// Implicit save

View file

@ -1587,7 +1587,7 @@ namespace CodeImp.DoomBuilder.Data
gldefsEntries.Add(thingType, parser.LightsByName[e.Value]);
}
} else {
GZBuilder.GZGeneral.LogAndTraceWarning("Got GLDEFS for class '" + e.Key + "', but haven't found such class in Decorate");
GZBuilder.GZGeneral.LogAndTraceWarning("Got GLDEFS light for class '" + e.Key + "', but haven't found such class in Decorate");
}
}

View file

@ -34,8 +34,19 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data {
}
internal static int SortByName(ScriptItem i1, ScriptItem i2) {
if (i1.Name == i2.Name) return 0;
if (i1.Name.ToUpper()[0] > i2.Name.ToUpper()[0]) return 1;
if (i1.Name.ToUpper()[0] == i2.Name.ToUpper()[0]) return 0;
if (i1.Name.ToUpper()[0] == i2.Name.ToUpper()[0]) {
int len = Math.Min(i1.Name.Length, i2.Name.Length);
for (int i = 0; i < len; i++) {
if (i1.Name.ToUpper()[i] > i2.Name.ToUpper()[i]) return 1;
if (i1.Name.ToUpper()[i] < i2.Name.ToUpper()[i]) return -1;
}
if (i1.Name.Length > i2.Name.Length) return 1;
return -1;
}
return -1;
}

View file

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CodeImp.DoomBuilder.GZBuilder.Data {
internal enum ScriptType : int {
UNKNOWN = 0,
ACS = 1,
MODELDEF = 2,
DECORATE = 3,
}
internal struct ScriptTypes {
private static string[] knownScriptTypes = { "UNKNOWN SCRIPT", "ZDoom ACS script", "GZDoom MODELDEF", "ZDoom DECORATE" };
internal static string[] TYPES { get { return knownScriptTypes; } }
}
}

View file

@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Text;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Rendering;
namespace CodeImp.DoomBuilder.GZBuilder.Data {
public sealed class ThingCopyData {
// Properties
private int type;
private Vector3D pos;
private int angledoom; // Angle as entered / stored in file
private Dictionary<string, bool> flags;
private int tag;
private int action;
private int[] args;
private UniFields fields;
public Vector3D Position { get { return pos; } }
public ThingCopyData(Thing t) {
type = t.Type;
angledoom = t.AngleDoom;
pos = t.Position;
flags = new Dictionary<string, bool>(t.Flags); //t.Flags;
tag = t.Tag;
action = t.Action;
args = (int[])t.Args.Clone();
fields = new UniFields(t, t.Fields);
}
public void ApplyTo(Thing t) {
t.Type = type;
t.Rotate(angledoom);
t.Move(pos);
foreach(KeyValuePair<string, bool> group in flags)
t.SetFlag(group.Key, group.Value);
t.Tag = tag;
t.Action = action;
foreach(int i in args)
t.Args[i] = args[i];
foreach (KeyValuePair<string, UniValue> group in fields) {
if (t.Fields.ContainsKey(group.Key))
t.Fields[group.Key] = group.Value;
else
t.Fields.Add(group.Key, group.Value);
}
t.UpdateConfiguration();
}
}
}

View file

@ -0,0 +1,79 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using CodeImp.DoomBuilder.ZDoom;
using CodeImp.DoomBuilder.GZBuilder.Data;
//mxd. Parser used to determine which script type given text is.
namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
internal sealed class ScriptTypeParserSE :ZDTextParser {
private ScriptType scriptType;
internal ScriptType ScriptType { get { return scriptType; } }
internal ScriptTypeParserSE() {
scriptType = ScriptType.UNKNOWN;
}
public override bool Parse(Stream stream, string sourcefilename) {
base.Parse(stream, sourcefilename);
// Continue until at the end of the stream
while (SkipWhitespace(true)) {
string token = ReadToken();
if (!string.IsNullOrEmpty(token)) {
token = token.ToUpperInvariant();
if (token == "MODEL") {
SkipWhitespace(true);
token = ReadToken(); //should be model name
SkipWhitespace(true);
token = ReadToken();//should be opening brace
if (token == "{") {
scriptType = ScriptType.MODELDEF;
return true;
}
}else if(token == "SCRIPT"){
SkipWhitespace(true);
token = ReadToken(); //should be script name or number
SkipWhitespace(true);
token = ReadToken(); //should be script parameters/type
SkipWhitespace(true);
token = ReadToken(); //should be opening brace
if (token == "{") {
scriptType = ScriptType.ACS;
return true;
}
}else if(token == "ACTOR"){
SkipWhitespace(true);
token = ReadToken(); //should be actor name
SkipWhitespace(true);
token = ReadToken();
if (token == ":" || token == "{" || token == "REPLACES") {
scriptType = ScriptType.DECORATE;
return true;
}
SkipWhitespace(true);
token = ReadToken(); //should be actor name
if (token == "{") {
scriptType = ScriptType.DECORATE;
return true;
}
}
}
}
return false;
}
}
}

View file

@ -407,31 +407,31 @@ namespace CodeImp.DoomBuilder.VisualModes
protected void moveSelectedThingsLeft() {
moveSelectedThings(new Vector2D(0f, -General.Map.Grid.GridSize), false);
}
//mxd
[BeginAction("movethingright", BaseAction = true)]
protected void moveSelectedThingsRight() {
moveSelectedThings(new Vector2D(0f, General.Map.Grid.GridSize), false);
}
//mxd
[BeginAction("movethingfwd", BaseAction = true)]
protected void moveSelectedThingsForward() {
moveSelectedThings(new Vector2D(-General.Map.Grid.GridSize, 0f), false);
}
//mxd
[BeginAction("movethingback", BaseAction = true)]
protected void moveSelectedThingsBackward() {
moveSelectedThings(new Vector2D(General.Map.Grid.GridSize, 0f), false);
}
//mxd
[BeginAction("placethingatcursor", BaseAction = true)]
protected void placeThingAtCursor() {
Vector2D hitCoords = getHitPosition();
if (!hitCoords.IsFinite()) {
Vector2D hitpos = getHitPosition();
if (!hitpos.IsFinite()) {
General.Interface.DisplayStatus(StatusType.Warning, "Cannot place Thing here");
return;
}
moveSelectedThings(new Vector2D((float)Math.Round(hitCoords.x), (float)Math.Round(hitCoords.y)), true);
moveSelectedThings(new Vector2D((float)Math.Round(hitpos.x), (float)Math.Round(hitpos.y)), true);
}
//mxd.
@ -458,15 +458,14 @@ namespace CodeImp.DoomBuilder.VisualModes
return hitCoords;
}
//mxd. this checks intersection between line and plane
//mxd. This checks intersection between line and plane
protected Vector2D getIntersection(Vector3D start, Vector3D end, Vector3D planeCenter, Vector3D planeNormal) {
Vector3D delta = new Vector3D(planeCenter.x - start.x, planeCenter.y - start.y, planeCenter.z - start.z);
return start + Vector3D.DotProduct(planeNormal, delta) / Vector3D.DotProduct(planeNormal, end - start) * (end - start);
}
//should move selected things in specified direction
//mxd. Should move selected things in specified direction
protected abstract void moveSelectedThings(Vector2D direction, bool absolutePosition);
//end of mxd :)
#endregion

View file

@ -162,6 +162,7 @@ namespace CodeImp.DoomBuilder.Windows
this.MinimizeBox = false;
this.MinimumSize = new System.Drawing.Size(680, 300);
this.Name = "ErrorsForm";
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Errors and Warnings";
this.Shown += new System.EventHandler(this.ErrorsForm_Shown);

View file

@ -50,6 +50,7 @@ namespace CodeImp.DoomBuilder.ZDoom
// Inheriting
private ActorStructure baseclass;
private bool skipsuper;
private bool haveBaseClass;//mxd
// Flags
private Dictionary<string, bool> flags;
@ -110,7 +111,8 @@ namespace CodeImp.DoomBuilder.ZDoom
token = token.ToLowerInvariant();
if(token == ":")
{
// The next token must be the class to inherit from
haveBaseClass = true; //mxd
// The next token must be the class to inherit from
parser.SkipWhitespace(true);
inheritclass = parser.StripTokenQuotes(parser.ReadToken());
if(string.IsNullOrEmpty(inheritclass) || parser.IsSpecialToken(inheritclass))
@ -122,8 +124,10 @@ namespace CodeImp.DoomBuilder.ZDoom
{
// Find the actor to inherit from
baseclass = parser.GetArchivedActorByName(inheritclass);
if(baseclass == null)
General.ErrorLogger.Add(ErrorType.Warning, "Unable to find the DECORATE class '" + inheritclass + "' to inherit from, while parsing '" + classname + "'");
//mxd. Fat chances are that this actor is not ment to be placed in the map, so we'll better check baseclass AFTER we parsed doomednum
//if(baseclass == null)
//General.ErrorLogger.Add(ErrorType.Warning, "Unable to find the DECORATE class '" + inheritclass + "' to inherit from, while parsing '" + classname + "'");
}
}
else if(token == "replaces")
@ -170,6 +174,10 @@ namespace CodeImp.DoomBuilder.ZDoom
return;
}
}
//mxd. Check if baseclass is valid
if (haveBaseClass && doomednum > -1 && baseclass == null)
General.ErrorLogger.Add(ErrorType.Warning, "Unable to find the DECORATE class '" + inheritclass + "' to inherit from, while parsing '" + classname + ":" + doomednum +"'");
// Now parse the contents of actor structure
string previoustoken = "";

View file

@ -33,6 +33,7 @@ using CodeImp.DoomBuilder.Editing;
using CodeImp.DoomBuilder.Actions;
using CodeImp.DoomBuilder.VisualModes;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.GZBuilder.Data;
#endregion
@ -84,6 +85,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
// List of selected objects when an action is performed
private List<IVisualEventReceiver> selectedobjects;
//mxd. Used in Cut/PasteSelection actions
private List<ThingCopyData> copyBuffer;
#endregion
@ -133,6 +136,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Initialize
this.gravity = new Vector3D(0.0f, 0.0f, 0.0f);
this.selectedobjects = new List<IVisualEventReceiver>();
//mxd
this.copyBuffer = new List<ThingCopyData>();
// We have no destructor
GC.SuppressFinalize(this);
@ -427,57 +432,82 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd
protected override void moveSelectedThings(Vector2D direction, bool absolutePosition) {
List<VisualThing> things = GetSelectedVisualThings(true);
List<VisualThing> visualThings = GetSelectedVisualThings(true);
if (things.Count == 0) {
if (visualThings.Count == 0) {
General.Interface.DisplayStatus(StatusType.Warning, "Select some Things first!");
return;
}
PreAction(UndoGroup.SectorHeightChange);
Vector3D[] coords = new Vector3D[visualThings.Count];
for (int i = 0; i < visualThings.Count; i++)
coords[i] = visualThings[i].Thing.Position;
//move things...
Vector3D[] translatedCoords = translateCoordinates(coords, direction, absolutePosition);
for (int i = 0; i < visualThings.Count; i++) {
BaseVisualThing t = visualThings[i] as BaseVisualThing;
t.OnMove(translatedCoords[i]);
}
PostAction();
}
//mxd
private Vector3D[] translateCoordinates(Vector3D[] coordinates, Vector2D direction, bool absolutePosition) {
if (coordinates.Length == 0) return null;
direction.x = (float)Math.Round(direction.x);
direction.y = (float)Math.Round(direction.y);
Vector3D[] translatedCoords = new Vector3D[coordinates.Length];
//move things...
if (!absolutePosition) { //...relatively (that's easy)
int camAngle = (int)Math.Round(General.Map.VisualCamera.AngleXY * 180 / Math.PI);
int sector = (int)(General.ClampAngle(camAngle - 45f) / 90f);
direction = direction.GetRotated((float)(sector * Math.PI / 2f));
for (int i = 0; i < things.Count; i++) {
BaseVisualThing t = things[i] as BaseVisualThing;
t.OnMove(t.Thing.Position + new Vector3D(direction));
}
} else { //...to specified location preserving relative positioning (that's harder)
if (things.Count == 1) {//just move it there
BaseVisualThing t = things[0] as BaseVisualThing;
t.OnMove(new Vector3D(direction.x, direction.y, t.Thing.Position.z));
return;
}
for (int i = 0; i < coordinates.Length; i++)
translatedCoords[i] = coordinates[i] + new Vector3D(direction);
//we need some reference
float minX = things[0].Thing.Position.x;
float maxX = minX;
float minY = things[0].Thing.Position.y;
float maxY = minY;
//get bounding coordinates for selected things
for (int i = 1; i < things.Count; i++) {
if (things[i].Thing.Position.x < minX)
minX = things[i].Thing.Position.x;
else if (things[i].Thing.Position.x > maxX)
maxX = things[i].Thing.Position.x;
if (things[i].Thing.Position.y < minY)
minY = things[i].Thing.Position.y;
else if (things[i].Thing.Position.y > maxY)
maxY = things[i].Thing.Position.y;
}
Vector2D selectionCenter = new Vector2D(minX + (maxX - minX) / 2, minY + (maxY - minY) / 2);
//move them
for (int i = 0; i < things.Count; i++) {
BaseVisualThing t = things[i] as BaseVisualThing;
t.OnMove(new Vector3D(direction.x - (selectionCenter.x - t.Thing.Position.x), direction.y - (selectionCenter.y - t.Thing.Position.y), t.Thing.Position.z));
}
return translatedCoords;
}
//...to specified location preserving relative positioning (that's harder)
if (coordinates.Length == 1) {//just move it there
translatedCoords[0] = new Vector3D(direction.x, direction.y, coordinates[0].z);
return translatedCoords;
}
//we need some reference
float minX = coordinates[0].x;
float maxX = minX;
float minY = coordinates[0].y;
float maxY = minY;
//get bounding coordinates for selected things
for (int i = 1; i < coordinates.Length; i++) {
if (coordinates[i].x < minX)
minX = coordinates[i].x;
else if (coordinates[i].x > maxX)
maxX = coordinates[i].x;
if (coordinates[i].y < minY)
minY = coordinates[i].y;
else if (coordinates[i].y > maxY)
maxY = coordinates[i].y;
}
Vector2D selectionCenter = new Vector2D(minX + (maxX - minX) / 2, minY + (maxY - minY) / 2);
//move them
for (int i = 0; i < coordinates.Length; i++)
translatedCoords[i] = new Vector3D((float)Math.Round(direction.x - (selectionCenter.x - coordinates[i].x)), (float)Math.Round(direction.y - (selectionCenter.y - coordinates[i].y)), (float)Math.Round(coordinates[i].z));
return translatedCoords;
}
#endregion
@ -504,6 +534,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
public override void OnDisengage()
{
base.OnDisengage();
copyBuffer.Clear(); //mxd
General.Map.Map.Update();
}
@ -962,7 +993,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd. Copied from BuilderModes.ThingsMode
// This creates a new thing
private Thing InsertThing(Vector2D pos) {
private Thing CreateThing(Vector2D pos) {
if (pos.x < General.Map.Config.LeftBoundary || pos.x > General.Map.Config.RightBoundary ||
pos.y > General.Map.Config.TopBoundary || pos.y < General.Map.Config.BottomBoundary) {
General.Interface.DisplayStatus(StatusType.Warning, "Failed to insert thing: outside of map boundaries.");
@ -1345,7 +1376,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd. now we can actually insert things in Visual modes
[BeginAction("insertitem", BaseAction = true)]
public void Insert() {
public void InsertThing() {
Vector2D hitpos = getHitPosition();
if (!hitpos.IsFinite()) {
@ -1358,7 +1389,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
General.Map.UndoRedo.CreateUndo("Insert thing");
Thing t = InsertThing(new Vector2D(hitpos.x, hitpos.y));
Thing t = CreateThing(new Vector2D(hitpos.x, hitpos.y));
if (t == null) {
General.Map.UndoRedo.WithdrawUndo();
@ -1379,7 +1410,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
[BeginAction("deleteitem", BaseAction = true)] //mxd. now we can actually delete things in Visual modes
public void Delete() {
public void DeleteSelectedThings() {
List<IVisualEventReceiver> objs = GetSelectedObjects(false, false, true);
if (objs.Count == 0) return;
@ -1398,6 +1429,73 @@ namespace CodeImp.DoomBuilder.BuilderModes
PostAction();
}
//mxd
[BeginAction("copyselection", BaseAction = true)]
public void CopySelection() {
List<IVisualEventReceiver> objs = GetSelectedObjects(false, false, true);
if (objs.Count == 0) {
General.Interface.DisplayStatus(StatusType.Warning, "Nothing to copy, select some Things first!");
return;
}
copyBuffer.Clear();
foreach (IVisualEventReceiver i in objs) {
VisualThing vt = i as VisualThing;
if (vt != null) copyBuffer.Add(new ThingCopyData(vt.Thing));
}
General.Interface.DisplayStatus(StatusType.Info, "Copied " + copyBuffer.Count + " Things");
}
//mxd
[BeginAction("cutselection", BaseAction = true)]
public void CutSelection() {
CopySelection();
DeleteSelectedThings();
}
//mxd. We'll just use currently selected objects
[BeginAction("pasteselection", BaseAction = true)]
public void PasteSelection() {
if (copyBuffer.Count == 0) {
General.Interface.DisplayStatus(StatusType.Warning, "Nothing to paste, cut or copy some Things first!");
return;
}
Vector2D hitpos = getHitPosition();
if (!hitpos.IsFinite()) {
General.Interface.DisplayStatus(StatusType.Warning, "Cannot paste here!");
return;
}
General.Map.UndoRedo.ClearAllRedos();
string rest = copyBuffer.Count + " thing" + (copyBuffer.Count > 1 ? "s." : ".");
General.Map.UndoRedo.CreateUndo("Paste " + rest);
General.Interface.DisplayStatus(StatusType.Info, "Pasted " + rest);
PreActionNoChange();
ClearSelection();
//get translated positions
Vector3D[] coords = new Vector3D[copyBuffer.Count];
for (int i = 0; i < copyBuffer.Count; i++)
coords[i] = copyBuffer[i].Position;
Vector3D[] translatedCoords = translateCoordinates(coords, hitpos, true);
//create things from copyBuffer
for (int i = 0; i < copyBuffer.Count; i++) {
Thing t = CreateThing(new Vector2D());
if (t != null) {
copyBuffer[i].ApplyTo(t);
t.Move(translatedCoords[i]);
//add thing to blockmap
blockmap.AddThing(t);
}
}
PostAction();
}
#endregion
}

View file

@ -480,7 +480,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
Thing.Move(newPosition);
mode.SetActionResult("Changed thing position to " + Thing.Position.ToString() + ".");
this.Changed = true;
Rebuild();
}
#endregion

View file

@ -34,6 +34,7 @@ using CodeImp.DoomBuilder.Editing;
using CodeImp.DoomBuilder.Actions;
using CodeImp.DoomBuilder.VisualModes;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.GZBuilder.Data;
#endregion
@ -89,6 +90,8 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
// List of selected objects when an action is performed
private List<IVisualEventReceiver> selectedobjects;
//mxd. Used in Cut/PasteSelection actions
private List<ThingCopyData> copyBuffer;
#endregion
@ -138,6 +141,8 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
// Initialize
this.gravity = new Vector3D(0.0f, 0.0f, 0.0f);
this.selectedobjects = new List<IVisualEventReceiver>();
//mxd
this.copyBuffer = new List<ThingCopyData>();
// We have no destructor
GC.SuppressFinalize(this);
@ -444,57 +449,82 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
//mxd
protected override void moveSelectedThings(Vector2D direction, bool absolutePosition) {
List<VisualThing> things = GetSelectedVisualThings(true);
List<VisualThing> visualThings = GetSelectedVisualThings(true);
if (things.Count == 0) {
if (visualThings.Count == 0) {
General.Interface.DisplayStatus(StatusType.Warning, "Select some Things first!");
return;
}
PreAction(UndoGroup.SectorHeightChange);
Vector3D[] coords = new Vector3D[visualThings.Count];
for (int i = 0; i < visualThings.Count; i++)
coords[i] = visualThings[i].Thing.Position;
//move things...
Vector3D[] translatedCoords = translateCoordinates(coords, direction, absolutePosition);
for (int i = 0; i < visualThings.Count; i++) {
BaseVisualThing t = visualThings[i] as BaseVisualThing;
t.OnMove(translatedCoords[i]);
}
PostAction();
}
//mxd
private Vector3D[] translateCoordinates(Vector3D[] coordinates, Vector2D direction, bool absolutePosition) {
if (coordinates.Length == 0) return null;
direction.x = (float)Math.Round(direction.x);
direction.y = (float)Math.Round(direction.y);
Vector3D[] translatedCoords = new Vector3D[coordinates.Length];
//move things...
if (!absolutePosition) { //...relatively (that's easy)
int camAngle = (int)Math.Round(General.Map.VisualCamera.AngleXY * 180 / Math.PI);
int sector = (int)(General.ClampAngle(camAngle - 45f) / 90f);
direction = direction.GetRotated((float)(sector * Math.PI / 2f));
for (int i = 0; i < things.Count; i++) {
BaseVisualThing t = things[i] as BaseVisualThing;
t.OnMove(t.Thing.Position + new Vector3D(direction));
}
} else { //...to specified location preserving relative positioning (that's harder)
if (things.Count == 1) {//just move it there
BaseVisualThing t = things[0] as BaseVisualThing;
t.OnMove(new Vector3D(direction.x, direction.y, t.Thing.Position.z));
return;
}
//we need some reference
float minX = things[0].Thing.Position.x;
float maxX = minX;
float minY = things[0].Thing.Position.y;
float maxY = minY;
for (int i = 0; i < coordinates.Length; i++)
translatedCoords[i] = coordinates[i] + new Vector3D(direction);
//get bounding coordinates for selected things
for (int i = 1; i < things.Count; i++) {
if (things[i].Thing.Position.x < minX)
minX = things[i].Thing.Position.x;
else if (things[i].Thing.Position.x > maxX)
maxX = things[i].Thing.Position.x;
if (things[i].Thing.Position.y < minY)
minY = things[i].Thing.Position.y;
else if (things[i].Thing.Position.y > maxY)
maxY = things[i].Thing.Position.y;
}
Vector2D selectionCenter = new Vector2D(minX + (maxX - minX) / 2, minY + (maxY - minY) / 2);
//move them
for (int i = 0; i < things.Count; i++) {
BaseVisualThing t = things[i] as BaseVisualThing;
t.OnMove(new Vector3D(direction.x - (selectionCenter.x - t.Thing.Position.x), direction.y - (selectionCenter.y - t.Thing.Position.y), t.Thing.Position.z));
}
return translatedCoords;
}
//...to specified location preserving relative positioning (that's harder)
if (coordinates.Length == 1) {//just move it there
translatedCoords[0] = new Vector3D(direction.x, direction.y, coordinates[0].z);
return translatedCoords;
}
//we need some reference
float minX = coordinates[0].x;
float maxX = minX;
float minY = coordinates[0].y;
float maxY = minY;
//get bounding coordinates for selected things
for (int i = 1; i < coordinates.Length; i++) {
if (coordinates[i].x < minX)
minX = coordinates[i].x;
else if (coordinates[i].x > maxX)
maxX = coordinates[i].x;
if (coordinates[i].y < minY)
minY = coordinates[i].y;
else if (coordinates[i].y > maxY)
maxY = coordinates[i].y;
}
Vector2D selectionCenter = new Vector2D(minX + (maxX - minX) / 2, minY + (maxY - minY) / 2);
//move them
for (int i = 0; i < coordinates.Length; i++)
translatedCoords[i] = new Vector3D((float)Math.Round(direction.x - (selectionCenter.x - coordinates[i].x)), (float)Math.Round(direction.y - (selectionCenter.y - coordinates[i].y)), (float)Math.Round(coordinates[i].z));
return translatedCoords;
}
#endregion
@ -686,6 +716,7 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
public override void OnDisengage()
{
base.OnDisengage();
copyBuffer.Clear(); //mxd
General.Map.Map.Update();
}
@ -941,7 +972,14 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
// Undo performed
public override void OnUndoEnd()
{
base.OnUndoEnd();
base.OnUndoEnd();
//mxd
foreach(KeyValuePair<Sector, VisualSector> group in visiblesectors){
if (group.Value is BaseVisualSector)
((BaseVisualSector)group.Value).Rebuild();
}
RebuildSelectedObjectsList();
// We can't group with this undo level anymore
@ -952,6 +990,13 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
public override void OnRedoEnd()
{
base.OnRedoEnd();
//mxd
foreach (KeyValuePair<Sector, VisualSector> group in visiblesectors) {
if (group.Value is BaseVisualSector)
((BaseVisualSector)group.Value).Rebuild();
}
RebuildSelectedObjectsList();
}
@ -1206,7 +1251,7 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
//mxd. Copied from BuilderModes.ThingsMode
// This creates a new thing
private Thing InsertThing(Vector2D pos) {
private Thing CreateThing(Vector2D pos) {
if (pos.x < General.Map.Config.LeftBoundary || pos.x > General.Map.Config.RightBoundary ||
pos.y > General.Map.Config.TopBoundary || pos.y < General.Map.Config.BottomBoundary) {
General.Interface.DisplayStatus(StatusType.Warning, "Failed to insert thing: outside of map boundaries.");
@ -1588,22 +1633,23 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
PostAction();
}
[BeginAction("insertitem", BaseAction = true)] //mxd. now we can actually insert things in Visual modes
public void Insert()
//mxd. now we can actually insert things in Visual modes
[BeginAction("insertitem", BaseAction = true)]
public void InsertThing()
{
Vector2D hitpos = getHitPosition();
if (!hitpos.IsFinite()) {
General.Interface.DisplayStatus(StatusType.Warning, "Cannot insert item here!");
General.Interface.DisplayStatus(StatusType.Warning, "Cannot insert thing here!");
return;
}
ClearSelection();
PreActionNoChange();
General.Map.UndoRedo.ClearAllRedos();
General.Map.UndoRedo.CreateUndo("Insert thing");
Thing t = InsertThing(new Vector2D(hitpos.x, hitpos.y));
Thing t = CreateThing(new Vector2D(hitpos.x, hitpos.y));
if (t == null) {
General.Map.UndoRedo.WithdrawUndo();
@ -1618,25 +1664,24 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
blockmap.AddThing(t);
General.Interface.DisplayStatus(StatusType.Action, "Inserted a new thing.");
General.Map.IsChanged = true;
General.Map.ThingsFilter.Update();
PostAction();
}
[BeginAction("deleteitem", BaseAction = true)] //mxd. now we can actually delete things in Visual modes
public void Delete()
//mxd. now we can actually delete things in Visual modes
[BeginAction("deleteitem", BaseAction = true)]
public void DeleteSelectedThings()
{
List<IVisualEventReceiver> objs = GetSelectedObjects(false, false, true);
if(objs.Count == 0) return;
if (objs.Count == 0) return;
General.Map.UndoRedo.ClearAllRedos();
string rest = objs.Count + " thing" + (objs.Count > 1 ? "s." : ".");
//make undo
General.Map.UndoRedo.CreateUndo("Delete " + rest);
General.Interface.DisplayStatus(StatusType.Info, "Deleted " + rest);
PreActionNoChange();
foreach(IVisualEventReceiver i in objs) i.OnDelete(); //are they deleted from BlockMap automatically?..
foreach (IVisualEventReceiver i in objs) i.OnDelete(); //are they deleted from BlockMap automatically?..
// Update cache values
General.Map.IsChanged = true;
@ -1644,6 +1689,73 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
PostAction();
}
//mxd
[BeginAction("copyselection", BaseAction = true)]
public void CopySelection() {
List<IVisualEventReceiver> objs = GetSelectedObjects(false, false, true);
if (objs.Count == 0) {
General.Interface.DisplayStatus(StatusType.Warning, "Nothing to copy, select some Things first!");
return;
}
copyBuffer.Clear();
foreach (IVisualEventReceiver i in objs) {
VisualThing vt = i as VisualThing;
if (vt != null) copyBuffer.Add(new ThingCopyData(vt.Thing));
}
General.Interface.DisplayStatus(StatusType.Info, "Copied " + copyBuffer.Count + " Things");
}
//mxd
[BeginAction("cutselection", BaseAction = true)]
public void CutSelection() {
CopySelection();
DeleteSelectedThings();
}
//mxd. We'll just use currently selected objects
[BeginAction("pasteselection", BaseAction = true)]
public void PasteSelection() {
if(copyBuffer.Count == 0){
General.Interface.DisplayStatus(StatusType.Warning, "Nothing to paste, cut or copy some Things first!");
return;
}
Vector2D hitpos = getHitPosition();
if (!hitpos.IsFinite()) {
General.Interface.DisplayStatus(StatusType.Warning, "Cannot paste here!");
return;
}
General.Map.UndoRedo.ClearAllRedos();
string rest = copyBuffer.Count + " thing" + (copyBuffer.Count > 1 ? "s." : ".");
General.Map.UndoRedo.CreateUndo("Paste " + rest);
General.Interface.DisplayStatus(StatusType.Info, "Pasted " + rest);
PreActionNoChange();
ClearSelection();
//get translated positions
Vector3D[] coords = new Vector3D[copyBuffer.Count];
for (int i = 0; i < copyBuffer.Count; i++ )
coords[i] = copyBuffer[i].Position;
Vector3D[] translatedCoords = translateCoordinates(coords, hitpos, true);
//create things from copyBuffer
for (int i = 0; i < copyBuffer.Count; i++) {
Thing t = CreateThing(new Vector2D());
if (t != null) {
copyBuffer[i].ApplyTo(t);
t.Move(translatedCoords[i]);
//add thing to blockmap
blockmap.AddThing(t);
}
}
PostAction();
}
#endregion
}

View file

@ -537,7 +537,6 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
}
this.Changed = true;
Rebuild();
}
#endregion

View file

@ -59,24 +59,24 @@ namespace CodeImp.DoomBuilder.TagExplorer
// Geometry pasted
public override void OnPasteEnd(PasteOptions options) {
if (tagExplorer != null)
tagExplorer.UpdateTree(true);
tagExplorer.UpdateTreeSoon();
}
// Undo performed
public override void OnUndoEnd() {
if (tagExplorer != null)
tagExplorer.UpdateTree(true);
tagExplorer.UpdateTreeSoon();
}
// Redo performed
public override void OnRedoEnd() {
if (tagExplorer != null)
tagExplorer.UpdateTree(true);
tagExplorer.UpdateTreeSoon();
}
public override void OnActionEnd(CodeImp.DoomBuilder.Actions.Action action) {
if (tagExplorer != null && action.Name == "builder_deleteitem")
tagExplorer.UpdateTree(true);
tagExplorer.UpdateTreeSoon();
}
}
}

View file

@ -31,6 +31,7 @@
this.tbSearch = new System.Windows.Forms.TextBox();
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.updatetimer = new System.Windows.Forms.Timer(this.components);
this.groupBox1.SuspendLayout();
this.SuspendLayout();
//
@ -204,6 +205,11 @@
this.groupBox2.TabIndex = 8;
this.groupBox2.TabStop = false;
//
// updatetimer
//
this.updatetimer.Interval = 500;
this.updatetimer.Tick += new System.EventHandler(this.updatetimer_Tick);
//
// TagExplorer
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
@ -237,5 +243,6 @@
private System.Windows.Forms.CheckBox cbSelectOnClick;
private System.Windows.Forms.CheckBox cbCommentsOnly;
private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.Timer updatetimer;
}
}

View file

@ -80,14 +80,20 @@ namespace CodeImp.DoomBuilder.TagExplorer
public void Setup() {
if (this.ParentForm != null) this.ParentForm.Activated += ParentForm_Activated;
UpdateTree(true);
updateTree(true);
}
public void Terminate() {
if (this.ParentForm != null) this.ParentForm.Activated -= ParentForm_Activated;
}
public void UpdateTree(bool focusDisplay) {
// This sets the timer to update the list very soon (because we'll have problems if we just call updateTree now)
public void UpdateTreeSoon() {
updatetimer.Stop();
updatetimer.Start();
}
private void updateTree(bool focusDisplay) {
bool showTags = (currentDisplayMode == DISPLAY_TAGS || currentDisplayMode == DISPLAY_TAGS_AND_ACTIONS);
bool showActions = (currentDisplayMode == DISPLAY_ACTIONS || currentDisplayMode == DISPLAY_TAGS_AND_ACTIONS);
bool hasComment = false;
@ -503,12 +509,12 @@ namespace CodeImp.DoomBuilder.TagExplorer
//EVENTS
private void cbDisplayMode_SelectedIndexChanged(object sender, EventArgs e) {
currentDisplayMode = cbDisplayMode.SelectedItem.ToString();
UpdateTree(true);
updateTree(true);
}
private void cbSortMode_SelectedIndexChanged(object sender, EventArgs e) {
currentSortMode = cbSortMode.SelectedItem.ToString();
UpdateTree(true);
updateTree(true);
}
private void treeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) {
@ -542,7 +548,7 @@ namespace CodeImp.DoomBuilder.TagExplorer
}
General.Map.Map.Update();
UpdateTree(true);
updateTree(true);
} else {
//select element?
@ -674,7 +680,7 @@ namespace CodeImp.DoomBuilder.TagExplorer
//It is called every time a dialog window closes.
private void ParentForm_Activated(object sender, EventArgs e){
UpdateTree(true);
UpdateTreeSoon();
}
private void btnClearSearch_Click(object sender, EventArgs e) {
@ -683,11 +689,16 @@ namespace CodeImp.DoomBuilder.TagExplorer
}
private void tbSearch_TextChanged(object sender, EventArgs e) {
if (tbSearch.Text.Length > 1 || tbSearch.Text.Length == 0) UpdateTree(false);
if (tbSearch.Text.Length > 1 || tbSearch.Text.Length == 0) updateTree(false);
}
private void cbCommentsOnly_CheckedChanged(object sender, EventArgs e) {
UpdateTree(true);
updateTree(true);
}
private void updatetimer_Tick(object sender, EventArgs e) {
updatetimer.Stop();
updateTree(true);
}
}

View file

@ -125,99 +125,99 @@
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABA
FwAAAk1TRnQBSQFMAgEBBgEAAUABAAFAAQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA
AwABIAMAAQEBAAEgBgABIBYAAxIBGQMSARkDEgEZNAADEgEZAxIBGQMSARmwAAMwAUwBAgFBAecB/wEC
AS0BoQH/AzABTAMSARksAAMwAUwBswFvASUB/wF5AUkBGwH/AzABTAMSARmsAAEeAV4C/wEWAVgC/wEC
AToBzgH/AQIBLQGhAf8DEgEZLAAB4AGHAS0B/wHZAYYBLAH/AZ4BYwEiAf8BeQFJARsB/wMSARmsAAFy
AZsC/wHoAe8C/wEWAVgC/wECAUEB5wH/AxIBGSwAAf4BtAFqAv8B/QHlAf8B2QGGASwB/wGzAW8BJQH/
AxIBGawAAzABTAFyAZsC/wEeAV4C/wOJAf8DRgH/AyMBMygAAzABTAH+AbQBagH/AeABhwEtAf8BowGJ
AW8B/wNGAf8DIwEzsAADIwEzA7wB/wOBAf8DRgH/AyMBMwgAAyMBMwMjATMDIwEzGAADIwEzA7wB/wOB
Af8DRgH/AyMBMwgAAyMBMwMjATMDIwEznAADIwEzA80B/wOUAf8DRgH/AyMBMwMwAUwDRgH/A5QB/wMj
ATMcAAMjATMDzQH/A5QB/wNGAf8DIwEzAzABTANGAf8DlAH/AyMBM6AAAyMBMwPNAf8DlAH/A0YB/wNG
Af8DlAH/AyMBMyQAAyMBMwPNAf8DlAH/A0YB/wNGAf8DlAH/AyMBM6gAAyMBMwO4Af8DlAH/A4EB/wMj
ATMsAAMjATMDuAH/A5QB/wOBAf8DIwEzsAADIwEzA88B/wOUAf8DRgH/AyMBMywAAyMBMwPPAf8DlAH/
A0YB/wMjATOwAAMjATMDwwH/A5QB/wNGAf8DIwEzLAADIwEzA8MB/wOUAf8DRgH/AyMBM7AAAyMBMwO8
Af8DlAH/A0YB/wMSARkDEgEZAxIBGSQAAyMBMwO8Af8DlAH/A0YB/wMSARkDEgEZAxIBGagAAyMBMwPZ
Af8DtwH/AQIBQQHnAf8BAgEtAaEB/wMwAUwDEgEZJAADIwEzA9kB/wHRAbcBnQH/AbMBbwElAf8BeQFJ
ARsB/wMwAUwDEgEZqAADIwEzAR4BXgL/ARYBWAL/AQIBOgHOAf8BAgEtAaEB/wMSARkoAAMjATMB4AGH
AS0B/wHZAYYBLAH/AZ4BYwEiAf8BeQFJARsB/wMSARmsAAFyAZsC/wHoAe8C/wEWAVgC/wECAUEB5wH/
AxIBGSwAAf4BtAFqAv8B/QHlAf8B2QGGASwB/wGzAW8BJQH/AxIBGawAAzABTAFyAZsC/wEeAV4C/wMw
AUwwAAMwAUwB/gG0AWoB/wHgAYcBLQH/AzABTJgAAwgBCwMfAS0DJwE7AycBOwMnATsDHgErAxIBGAMS
FwAAAk1TRnQBSQFMAgEBBgEAAUgBAAFIAQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA
AwABIAMAAQEBAAEgBgABIBYAAxIBGQMSARkDEgEZNAADEgEZAxIBGQMSARmwAAMwAUwBAQFAAecB/wEB
ASwBoQH/AzABTAMSARksAAMwAUwBswFuASQB/wF4AUgBGgH/AzABTAMSARmsAAEdAV0C/wEVAVcC/wEB
ATkBzgH/AQEBLAGhAf8DEgEZLAAB4AGHASwB/wHZAYYBKwH/AZ4BYgEhAf8BeAFIARoB/wMSARmsAAFx
AZsC/wHoAe8C/wEVAVcC/wEBAUAB5wH/AxIBGSwAAf4BtAFpAv8B/QHlAf8B2QGGASsB/wGzAW4BJAH/
AxIBGawAAzABTAFxAZsC/wEdAV0C/wOJAf8DRQH/AyMBMygAAzABTAH+AbQBaQH/AeABhwEsAf8BowGJ
AW4B/wNFAf8DIwEzsAADIwEzA7wB/wOBAf8DRQH/AyMBMwgAAyMBMwMjATMDIwEzGAADIwEzA7wB/wOB
Af8DRQH/AyMBMwgAAyMBMwMjATMDIwEznAADIwEzA80B/wOUAf8DRQH/AyMBMwMwAUwDRQH/A5QB/wMj
ATMcAAMjATMDzQH/A5QB/wNFAf8DIwEzAzABTANFAf8DlAH/AyMBM6AAAyMBMwPNAf8DlAH/A0UB/wNF
Af8DlAH/AyMBMyQAAyMBMwPNAf8DlAH/A0UB/wNFAf8DlAH/AyMBM6gAAyMBMwO4Af8DlAH/A4EB/wMj
ATMsAAMjATMDuAH/A5QB/wOBAf8DIwEzsAADIwEzA88B/wOUAf8DRQH/AyMBMywAAyMBMwPPAf8DlAH/
A0UB/wMjATOwAAMjATMDwwH/A5QB/wNFAf8DIwEzLAADIwEzA8MB/wOUAf8DRQH/AyMBM7AAAyMBMwO8
Af8DlAH/A0UB/wMSARkDEgEZAxIBGSQAAyMBMwO8Af8DlAH/A0UB/wMSARkDEgEZAxIBGagAAyMBMwPZ
Af8DtwH/AQEBQAHnAf8BAQEsAaEB/wMwAUwDEgEZJAADIwEzA9kB/wHRAbcBnQH/AbMBbgEkAf8BeAFI
ARoB/wMwAUwDEgEZqAADIwEzAR0BXQL/ARUBVwL/AQEBOQHOAf8BAQEsAaEB/wMSARkoAAMjATMB4AGH
ASwB/wHZAYYBKwH/AZ4BYgEhAf8BeAFIARoB/wMSARmsAAFxAZsC/wHoAe8C/wEVAVcC/wEBAUAB5wH/
AxIBGSwAAf4BtAFpAv8B/QHlAf8B2QGGASsB/wGzAW4BJAH/AxIBGawAAzABTAFxAZsC/wEdAV0C/wMw
AUwwAAMwAUwB/gG0AWkB/wHgAYcBLAH/AzABTJgAAwgBCwMfAS0DJwE7AycBOwMnATsDHgErAxIBGAMS
ARggAAMIAQsDHwEtAycBOwMnATsDJwE7Ax4BKwMSARgDEgEYEAADEgEZAxIBGQMSARkgAAMSARkDEgEZ
AxIBGQgAAxIBGQMSARkDEgEZIAADEgEZAxIBGQMSARkUAAM4AVwCXwFkAegBJAEsAYEB/wEeASUBcgH/
AR0BJAFvAf8BHAEjAWgB/wJaAWAB5AM4AVwDJwE7AxIBGBgAAzgBXAFlAWEBXwHoAYEBVwEkAf8BcgFP
AR4B/wFvAU0BHQH/AWgBSAEcAf8BYQJaAeQDOAFcAycBOwMSARgIAAMwAUwBJgE1AbIB/wEcASkBeAH/
AzABTAMSARkDEgEZAxIBGQMSARkDEgEZAxIBGQMSARkDMAFMASYBNQGyAf8BHAEpAXgB/wMwAUwDEgEZ
AzABTAGyAW8BJgH/AXgBSQEcAf8DMAFMAxIBGQMSARkDEgEZAxIBGQMSARkDEgEZAxIBGQMwAUwBsgFv
ASYB/wF4AUkBHAH/AzABTAMSARkMAANaAcUBNAFAAbsB/wEyAT4BvAH/ATEBPQG6Af8BMAE8AbcB/wEu
ATgBtAH/ASwBNwGsAf8BJwEvAZQB/wEdASUBcgH/A1oBvQMnATsDEgEYEAADWgHFAbsBgwE0Af8BvAGC
ATIB/wG6AYEBMQH/AbcBgQEwAf8BtAGBAS4B/wGsAXUBLAH/AZQBZwEnAf8BcgFOAR0B/wNaAb0DJwE7
AxIBGAQAAS8BRwHfAf8BLQFBAdgB/wEiAS4BnQH/ARwBKQF4Af8DPwH/Az8B/wM/Af8DPwH/Az8B/wM/
Af8DPwH/AS8BRwHfAf8BLQFBAdgB/wEiAS4BnQH/ARwBKQF4Af8DEgEZAd8BhwEvAf8B2AGGAS0B/wGd
AWMBIgH/AXgBSQEcAf8DPwH/Az8B/wM/Af8DPwH/Az8B/wM/Af8DPwH/Ad8BhwEvAf8B2AGGAS0B/wGd
AWMBIgH/AXgBSQEcAf8DEgEZCAADWQG+ATkBRgHTAf8BPgFNAegB/wFCAVAB8wH/AUEBUAHwAf8BQAFQ
Ae8B/wFAAVAB7wH/AT8BTQHtAf8BPAFLAeIB/wEyAT4BuwH/ASIBKQGBAf8DWgG9AycBOwMSARgIAANZ
Ab4B0wGTATkB/wHoAaEBPgH/AfMBqgFCAf8B8AGnAUEB/wHvAaUBQAH/Ae8BpQFAAf8B7QGlAT8B/wHi
AZwBPAH/AbsBggEyAf8BgQFZASIB/wNaAb0DJwE7AxIBGAFrAYEB/QH/AewB5QL/AS0BQQHYAf8BJgE1
AbIB/wO4Af8DuAH/A7gB/wO4Af8DuAH/A6YB/wOYAf8BawGBAf0B/wHsAeUC/wEtAUEB2AH/ASYBNQGy
Af8DEgEZAf0BtAFrAv8B/QHlAf8B2AGGAS0B/wGyAW8BJgH/A7gB/wO4Af8DuAH/A7gB/wO4Af8DpgH/
A5gB/wH9AbQBawL/Af0B5QH/AdgBhgEtAf8BsgFvASYB/wMSARkEAAM4AVwBQgFQAeMB/wFBAU8B8QH/
ATEBPAGzAf8BLwE6AasB/wE/AU0B6gH/AUQBVAH6Af8BQwFSAfYB/wFBAU8B8QH/AUEBUAHwAf8BPgFM
AeoB/wExATwBvgH/ASEBJwGBAf8DOAFcAxIBGAQAAzgBXAHjAaABQgH/AfEBqAFBAf8BswGBATEB/wGr
AXYBLwH/AeoBowE/Af8B+gGuAUQB/wH2AawBQwH/AfEBqAFBAf8B8AGnAUEB/wHqAaMBPgH/Ab4BhAEx
Af8BgQFYASEB/wM4AVwDEgEYAzABTAFrAYEB/QH/AS8BRwHfAf8DMAFMDAADuAH/A04BmQgAAzABTAFr
AYEB/QH/AS8BRwHfAf8DMAFMBAADMAFMAf0BtAFrAf8B3wGHAS8B/wMwAUwMAAO4Af8DTgGZCAADMAFM
Af0BtAFrAf8B3wGHAS8B/wMwAUwIAANfAdsBUQFfAfYB/wFLAVoC/wExATwBsQH/AwIB/wEKAQwBJgH/
AR8BJgFyAf8BNgFBAcIB/wFBAVEB8QH/AUQBVAH6Af8BQgFSAfQB/wE7AUkB5AH/ASwBNwGsAf8CXAFk
AecDHgErBAADXwHbAfYBsQFRAv8BtAFLAf8BsQF6ATEB/wMCAf8BJgEbAQoB/wFyAU8BHwH/AcIBiAE2
Af8B8QGnAUEB/wH6Aa4BRAH/AfQBqQFCAf8B5AGeATsB/wGsAXUBLAH/AWQBYgFcAecDHgErBAADmAH/
A0YB/wMSARkMAAOlAf8DTgGZDAADmAH/Az8B/wMSARkIAAOYAf8DRgH/AxIBGQwAA6UB/wNOAZkMAAOY
Af8DPwH/AxIBGQgAAU4BXAL/AWYBdAL/AVUBYgH7Af8BRwFVAegB/wEKAQsBHAH/AwIB/wMCAf8DAgH/
AQ4BEQE1Af8BJAEsAYQB/wE4AUQBzgH/AUABTwHvAf8BNgFCAcwB/wElAS4BigH/AycBOwQAAf8BtgFO
Av8BvgFmAf8B+wG3AVUB/wHoAaUBRwH/ARwBFQEKAf8DAgH/AwIB/wMCAf8BNQElAQ4B/wGEAVsBJAH/
Ac4BkAE4Af8B7wGmAUAB/wHMAY4BNgH/AYoBXwElAf8DJwE7BAADpgH/A0YB/wMSARkgAAOmAf8DPwH/
AxIBGQgAA6YB/wNGAf8DEgEZIAADpgH/Az8B/wMSARkEAAMjATMBYQFuAv8BdwGEAv8BXwFrAfkB/wFR
AWAB/AH/ASIBKgF3Af8DAgH/AwIB/wMCAf8BCAEJAQ8B/wEbASIBYQH/ASsBNAGdAf8BPgFLAeQB/wE7
AUoB4QH/ASgBMQGcAf8DJwE7AyMBMwH/Ab0BYQL/AcYBdwH/AfkBugFfAf8B/AG0AVEB/wF3AVMBIgH/
AwIB/wMCAf8DAgH/AQ8BDAEIAf8BYQFDARsB/wGdAW0BKwH/AeQBoAE+Af8B4QGbATsB/wGcAWsBKAH/
AycBOwQAA7AB/wNGAf8DTgGZA04BmRQAA04BmQNOAZkDsAH/Az8B/wMSARkIAAOwAf8DRgH/A04BmQNO
AZkUAANOAZkDTgGZA7AB/wM/Af8DEgEZBAADIwEzAWsBeAL/AYEBjAL/AWABbgH4Af8BTwFfAfsB/wE3
AUMBywH/AgMBBQH/AwIB/wMCAf8BFAEYAUcB/wFEAVMB+QH/AUQBVAH6Af8BQQFQAfAB/wE7AUkB4wH/
ASkBMwGiAf8DJwE7AyMBMwH/AcEBawL/AcoBgQH/AfgBuAFgAf8B+wGyAU8B/wHLAY4BNwH/AQUBBAED
Af8DAgH/AwIB/wFHATIBFAH/AfkBrgFEAf8B+gGuAUQB/wHwAacBQQH/AeMBnQE7Af8BogFvASkB/wMn
ATsEAAO4Af8DuAH/A7gB/wOlAf8UAAOlAf8DuAH/A7gB/wM/Af8DEgEZCAADuAH/A7gB/wO4Af8DpQH/
FAADpQH/A7gB/wO4Af8DPwH/AxIBGQgAAWkBeAL/AY4BlwL/AWgBcwH+Af8BUQFgAfUB/wFHAVUB+AH/
ARMBGAFHAf8BBQEEAQYB/wEgASgBdgH/AwIB/wEXAR0BVgH/AUEBUAHwAf8BQgFQAfMB/wE5AUcB2gH/
ASsBNAGfAf8DIgExBAAB/wG/AWkC/wHQAY4B/wH+AcEBaAH/AfUBsAFRAf8B+AGvAUcB/wFHATEBEwH/
AgYBBAH/AXYBUQEgAf8DAgH/AVYBOwEXAf8B8AGnAUEB/wHzAaoBQgH/AdoBlwE5Af8BnwFvASsB/wMi
ATEEAAO4Af8DRgH/AxIBGSAAA7gB/wM/Af8DEgEZCAADuAH/A0YB/wMSARkgAAO4Af8DPwH/AxIBGQgA
A18B2wGWAaAC/wGGAZAC/wFpAXYB+QH/AVQBYgH+Af8BLAE2AZ0B/wESARcBQwH/AUYBVgL/ASoBMwGY
Af8DAgH/ARcBHQFWAf8BQAFPAe0B/wE5AUYB1QH/AlwBZAHqAwwBEAQAA18B2wH/AdIBlgL/AcwBhgH/
AfkBvAFpAf8B/gG4AVQB/wGdAW0BLAH/AUMBLgESAv8BsgFGAf8BmAFqASoB/wMCAf8BVgE7ARcB/wHt
AaUBQAH/AdUBlAE5Af8BZQFiAVwB6gMMARAEAAO4Af8DRgH/AxIBGSAAA7gB/wM/Af8DEgEZCAADuAH/
A0YB/wMSARkgAAO4Af8DPwH/AxIBGQgAAzgBXAGYAaIC/wGeAacC/wFyAYEC/wFeAWsB+QH/AUkBVAHk
Af8BOgFFAb4B/wFKAVoB+AH/AUwBWgH9Af8BMwE7AZwB/wMCAf8BMAE6AbEB/wE8AUkB3gH/AzgBXAgA
AzgBXAH/AdMBmAL/AdYBngL/AcUBcgH/AfkBuQFeAf8B5AGlAUkB/wG+AYcBOgH/AfgBrgFKAf8B/QG0
AUwB/wGcAXABMwH/AwIB/wGxAYABMAH/Ad4BmwE8Af8DOAFcCAADuAH/A0YB/wMSARkMAAOlAf8DTgGZ
DAADuAH/Az8B/wMSARkIAAO4Af8DRgH/AxIBGQwAA6UB/wNOAZkMAAO4Af8DPwH/AxIBGQwAA1UBsgGo
AbEC/wGJAZMC/wF4AYMC/wFvAYAB/AH/AWQBcAH2Af8BXgFqAfYB/wFdAWkB9QH/AVkBZgH7Af8BPAFG
AcIB/wE9AUsB4AH/A1sBxhAAA1UBsgH/AdkBqAL/Ac4BiQL/AcgBeAH/AfwBwQFvAf8B9gG5AWQB/wH2
AbcBXgH/AfUBtgFdAf8B+wG4AVkB/wHCAYsBPAH/AeABnAE9Af8DWwHGCAADMAFMASYBNQGyAf8BHAEp
AXgB/wMwAUwDEgEZAxIBGQMSARkDuAH/A04BmQMSARkDEgEZAzABTAEmATUBsgH/ARwBKQF4Af8DMAFM
AxIBGQMwAUwBsgFvASYB/wF4AUkBHAH/AzABTAMSARkDEgEZAxIBGQO4Af8DTgGZAxIBGQMSARkDMAFM
AbIBbwEmAf8BeAFJARwB/wMwAUwDEgEZDAADVgGxAZ8BqQL/AZcBogL/AYsBlQL/AXMBggL/AWEBcAH9
Af8BVwFkAfkB/wFLAVoB9wH/AUQBVAH6Af8DWgG9GAADVgGxAf8B1QGfAv8B0QGXAv8BzwGLAv8BwwFz
Af8B/QG6AWEB/wH5AbYBVwH/AfcBrwFLAf8B+gGtAUQB/wNaAb0MAAEvAUcB3wH/AS0BQQHYAf8BIgEu
AZ0B/wEcASkBeAH/A0YB/wNGAf8DRgH/A7gB/wNGAf8DRgH/A0YB/wEvAUcB3wH/AS0BQQHYAf8BIgEu
AZ0B/wEcASkBeAH/AxIBGQHfAYcBLwH/AdgBhgEtAf8BnQFjASIB/wF4AUkBHAH/A0YB/wNGAf8DRgH/
A7gB/wNGAf8DRgH/A0YB/wHfAYcBLwH/AdgBhgEtAf8BnQFjASIB/wF4AUkBHAH/AxIBGRAAAzgBXANe
AdgBegGHAv8BgwGNAv8BcwGDAv8BXgFsAv8DXgHYAzgBXCAAAzgBXANeAdgB/wHHAXoC/wHMAYMC/wHC
AXMC/wG8AV4B/wNeAdgDOAFcEAABawGBAf0B/wHsAeUC/wEtAUEB2AH/ASYBNQGyAf8DuAH/A7gB/wO4
Af8DuAH/A7gB/wOmAf8DmAH/AWsBgQH9Af8B7AHlAv8BLQFBAdgB/wEmATUBsgH/AxIBGQH9AbQBawL/
Af0B5QH/AdgBhgEtAf8BsgFvASYB/wO4Af8DuAH/A7gB/wO4Af8DuAH/A6YB/wOYAf8B/QG0AWsC/wH9
AeUB/wHYAYYBLQH/AbIBbwEmAf8DEgEZHAADIwEzAyMBMzgAAyMBMwMjATMcAAMwAUwBawGBAf0B/wEv
AUcB3wH/AzABTBwAAzABTAFrAYEB/QH/AS8BRwHfAf8DMAFMBAADMAFMAf0BtAFrAf8B3wGHAS8B/wMw
AUwcAAMwAUwB/QG0AWsB/wHfAYcBLwH/AzABTAQAAUIBTQE+BwABPgMAASgDAAFAAwABIAMAAQEBAAEB
AxIBGQgAAxIBGQMSARkDEgEZIAADEgEZAxIBGQMSARkUAAM4AVwCXwFjAegBIwErAYEB/wEdASQBcQH/
ARwBIwFuAf8BGwEiAWcB/wJaAWAB5AM4AVwDJwE7AxIBGBgAAzgBXAFkAWABXwHoAYEBVgEjAf8BcQFO
AR0B/wFuAUwBHAH/AWcBRwEbAf8BYQJaAeQDOAFcAycBOwMSARgIAAMwAUwBJQE0AbIB/wEbASgBdwH/
AzABTAMSARkDEgEZAxIBGQMSARkDEgEZAxIBGQMSARkDMAFMASUBNAGyAf8BGwEoAXcB/wMwAUwDEgEZ
AzABTAGyAW4BJQH/AXcBSAEbAf8DMAFMAxIBGQMSARkDEgEZAxIBGQMSARkDEgEZAxIBGQMwAUwBsgFu
ASUB/wF3AUgBGwH/AzABTAMSARkMAANaAcUBMwE/AbsB/wExAT0BvAH/ATABPAG6Af8BLwE7AbcB/wEt
ATcBtAH/ASsBNgGsAf8BJgEuAZQB/wEcASQBcQH/A1oBvQMnATsDEgEYEAADWgHFAbsBgwEzAf8BvAGC
ATEB/wG6AYEBMAH/AbcBgQEvAf8BtAGBAS0B/wGsAXQBKwH/AZQBZgEmAf8BcQFNARwB/wNaAb0DJwE7
AxIBGAQAAS4BRgHfAf8BLAFAAdgB/wEhAS0BnQH/ARsBKAF3Af8DPgH/Az4B/wM+Af8DPgH/Az4B/wM+
Af8DPgH/AS4BRgHfAf8BLAFAAdgB/wEhAS0BnQH/ARsBKAF3Af8DEgEZAd8BhwEuAf8B2AGGASwB/wGd
AWIBIQH/AXcBSAEbAf8DPgH/Az4B/wM+Af8DPgH/Az4B/wM+Af8DPgH/Ad8BhwEuAf8B2AGGASwB/wGd
AWIBIQH/AXcBSAEbAf8DEgEZCAADWQG+ATgBRQHTAf8BPQFMAegB/wFBAU8B8wH/AUABTwHwAf8BPwFP
Ae8B/wE/AU8B7wH/AT4BTAHtAf8BOwFKAeIB/wExAT0BuwH/ASEBKAGBAf8DWgG9AycBOwMSARgIAANZ
Ab4B0wGTATgB/wHoAaEBPQH/AfMBqgFBAf8B8AGnAUAB/wHvAaUBPwH/Ae8BpQE/Af8B7QGlAT4B/wHi
AZwBOwH/AbsBggExAf8BgQFYASEB/wNaAb0DJwE7AxIBGAFqAYEB/QH/AewB5QL/ASwBQAHYAf8BJQE0
AbIB/wO4Af8DuAH/A7gB/wO4Af8DuAH/A6YB/wOYAf8BagGBAf0B/wHsAeUC/wEsAUAB2AH/ASUBNAGy
Af8DEgEZAf0BtAFqAv8B/QHlAf8B2AGGASwB/wGyAW4BJQH/A7gB/wO4Af8DuAH/A7gB/wO4Af8DpgH/
A5gB/wH9AbQBagL/Af0B5QH/AdgBhgEsAf8BsgFuASUB/wMSARkEAAM4AVwBQQFPAeMB/wFAAU4B8QH/
ATABOwGzAf8BLgE5AasB/wE+AUwB6gH/AUMBUwH6Af8BQgFRAfYB/wFAAU4B8QH/AUABTwHwAf8BPQFL
AeoB/wEwATsBvgH/ASABJgGBAf8DOAFcAxIBGAQAAzgBXAHjAaABQQH/AfEBqAFAAf8BswGBATAB/wGr
AXUBLgH/AeoBowE+Af8B+gGuAUMB/wH2AawBQgH/AfEBqAFAAf8B8AGnAUAB/wHqAaMBPQH/Ab4BhAEw
Af8BgQFXASAB/wM4AVwDEgEYAzABTAFqAYEB/QH/AS4BRgHfAf8DMAFMDAADuAH/A04BmQgAAzABTAFq
AYEB/QH/AS4BRgHfAf8DMAFMBAADMAFMAf0BtAFqAf8B3wGHAS4B/wMwAUwMAAO4Af8DTgGZCAADMAFM
Af0BtAFqAf8B3wGHAS4B/wMwAUwIAANfAdsBUAFeAfYB/wFKAVkC/wEwATsBsQH/AwEB/wEJAQsBJQH/
AR4BJQFxAf8BNQFAAcIB/wFAAVAB8QH/AUMBUwH6Af8BQQFRAfQB/wE6AUgB5AH/ASsBNgGsAf8CXAFk
AecDHgErBAADXwHbAfYBsQFQAv8BtAFKAf8BsQF5ATAB/wMBAf8BJQEaAQkB/wFxAU4BHgH/AcIBiAE1
Af8B8QGnAUAB/wH6Aa4BQwH/AfQBqQFBAf8B5AGeAToB/wGsAXQBKwH/AWQBYgFcAecDHgErBAADmAH/
A0UB/wMSARkMAAOlAf8DTgGZDAADmAH/Az4B/wMSARkIAAOYAf8DRQH/AxIBGQwAA6UB/wNOAZkMAAOY
Af8DPgH/AxIBGQgAAU0BWwL/AWUBcwL/AVQBYQH7Af8BRgFUAegB/wEJAQoBGwH/AwEB/wMBAf8DAQH/
AQ0BEAE0Af8BIwErAYQB/wE3AUMBzgH/AT8BTgHvAf8BNQFBAcwB/wEkAS0BigH/AycBOwQAAf8BtgFN
Av8BvgFlAf8B+wG3AVQB/wHoAaUBRgH/ARsBFAEJAf8DAQH/AwEB/wMBAf8BNAEkAQ0B/wGEAVoBIwH/
Ac4BkAE3Af8B7wGmAT8B/wHMAY4BNQH/AYoBXgEkAf8DJwE7BAADpgH/A0UB/wMSARkgAAOmAf8DPgH/
AxIBGQgAA6YB/wNFAf8DEgEZIAADpgH/Az4B/wMSARkEAAMjATMBYAFtAv8BdgGEAv8BXgFqAfkB/wFQ
AV8B/AH/ASEBKQF2Af8DAQH/AwEB/wMBAf8BBwEIAQ4B/wEaASEBYAH/ASoBMwGdAf8BPQFKAeQB/wE6
AUkB4QH/AScBMAGcAf8DJwE7AyMBMwH/Ab0BYAL/AcYBdgH/AfkBugFeAf8B/AG0AVAB/wF2AVIBIQH/
AwEB/wMBAf8DAQH/AQ4BCwEHAf8BYAFCARoB/wGdAWwBKgH/AeQBoAE9Af8B4QGbAToB/wGcAWoBJwH/
AycBOwQAA7AB/wNFAf8DTgGZA04BmRQAA04BmQNOAZkDsAH/Az4B/wMSARkIAAOwAf8DRQH/A04BmQNO
AZkUAANOAZkDTgGZA7AB/wM+Af8DEgEZBAADIwEzAWoBdwL/AYEBjAL/AV8BbQH4Af8BTgFeAfsB/wE2
AUIBywH/AgIBBAH/AwEB/wMBAf8BEwEXAUYB/wFDAVIB+QH/AUMBUwH6Af8BQAFPAfAB/wE6AUgB4wH/
ASgBMgGiAf8DJwE7AyMBMwH/AcEBagL/AcoBgQH/AfgBuAFfAf8B+wGyAU4B/wHLAY4BNgH/AQQBAwEC
Af8DAQH/AwEB/wFGATEBEwH/AfkBrgFDAf8B+gGuAUMB/wHwAacBQAH/AeMBnQE6Af8BogFuASgB/wMn
ATsEAAO4Af8DuAH/A7gB/wOlAf8UAAOlAf8DuAH/A7gB/wM+Af8DEgEZCAADuAH/A7gB/wO4Af8DpQH/
FAADpQH/A7gB/wO4Af8DPgH/AxIBGQgAAWgBdwL/AY4BlwL/AWcBcgH+Af8BUAFfAfUB/wFGAVQB+AH/
ARIBFwFGAf8BBAEDAQUB/wEfAScBdQH/AwEB/wEWARwBVQH/AUABTwHwAf8BQQFPAfMB/wE4AUYB2gH/
ASoBMwGfAf8DIgExBAAB/wG/AWgC/wHQAY4B/wH+AcEBZwH/AfUBsAFQAf8B+AGvAUYB/wFGATABEgH/
AgUBAwH/AXUBUAEfAf8DAQH/AVUBOgEWAf8B8AGnAUAB/wHzAaoBQQH/AdoBlwE4Af8BnwFuASoB/wMi
ATEEAAO4Af8DRQH/AxIBGSAAA7gB/wM+Af8DEgEZCAADuAH/A0UB/wMSARkgAAO4Af8DPgH/AxIBGQgA
A18B2wGWAaAC/wGGAZAC/wFoAXUB+QH/AVMBYQH+Af8BKwE1AZ0B/wERARYBQgH/AUUBVQL/ASkBMgGY
Af8DAQH/ARYBHAFVAf8BPwFOAe0B/wE4AUUB1QH/AlwBYwHqAwwBEAQAA18B2wH/AdIBlgL/AcwBhgH/
AfkBvAFoAf8B/gG4AVMB/wGdAWwBKwH/AUIBLQERAv8BsgFFAf8BmAFpASkB/wMBAf8BVQE6ARYB/wHt
AaUBPwH/AdUBlAE4Af8BZAFhAVwB6gMMARAEAAO4Af8DRQH/AxIBGSAAA7gB/wM+Af8DEgEZCAADuAH/
A0UB/wMSARkgAAO4Af8DPgH/AxIBGQgAAzgBXAGYAaIC/wGeAacC/wFxAYEC/wFdAWoB+QH/AUgBUwHk
Af8BOQFEAb4B/wFJAVkB+AH/AUsBWQH9Af8BMgE6AZwB/wMBAf8BLwE5AbEB/wE7AUgB3gH/AzgBXAgA
AzgBXAH/AdMBmAL/AdYBngL/AcUBcQH/AfkBuQFdAf8B5AGlAUgB/wG+AYcBOQH/AfgBrgFJAf8B/QG0
AUsB/wGcAW8BMgH/AwEB/wGxAYABLwH/Ad4BmwE7Af8DOAFcCAADuAH/A0UB/wMSARkMAAOlAf8DTgGZ
DAADuAH/Az4B/wMSARkIAAO4Af8DRQH/AxIBGQwAA6UB/wNOAZkMAAO4Af8DPgH/AxIBGQwAA1UBsgGo
AbEC/wGJAZMC/wF3AYMC/wFuAYAB/AH/AWMBbwH2Af8BXQFpAfYB/wFcAWgB9QH/AVgBZQH7Af8BOwFF
AcIB/wE8AUoB4AH/A1sBxhAAA1UBsgH/AdkBqAL/Ac4BiQL/AcgBdwH/AfwBwQFuAf8B9gG5AWMB/wH2
AbcBXQH/AfUBtgFcAf8B+wG4AVgB/wHCAYsBOwH/AeABnAE8Af8DWwHGCAADMAFMASUBNAGyAf8BGwEo
AXcB/wMwAUwDEgEZAxIBGQMSARkDuAH/A04BmQMSARkDEgEZAzABTAElATQBsgH/ARsBKAF3Af8DMAFM
AxIBGQMwAUwBsgFuASUB/wF3AUgBGwH/AzABTAMSARkDEgEZAxIBGQO4Af8DTgGZAxIBGQMSARkDMAFM
AbIBbgElAf8BdwFIARsB/wMwAUwDEgEZDAADVgGxAZ8BqQL/AZcBogL/AYsBlQL/AXIBggL/AWABbwH9
Af8BVgFjAfkB/wFKAVkB9wH/AUMBUwH6Af8DWgG9GAADVgGxAf8B1QGfAv8B0QGXAv8BzwGLAv8BwwFy
Af8B/QG6AWAB/wH5AbYBVgH/AfcBrwFKAf8B+gGtAUMB/wNaAb0MAAEuAUYB3wH/ASwBQAHYAf8BIQEt
AZ0B/wEbASgBdwH/A0UB/wNFAf8DRQH/A7gB/wNFAf8DRQH/A0UB/wEuAUYB3wH/ASwBQAHYAf8BIQEt
AZ0B/wEbASgBdwH/AxIBGQHfAYcBLgH/AdgBhgEsAf8BnQFiASEB/wF3AUgBGwH/A0UB/wNFAf8DRQH/
A7gB/wNFAf8DRQH/A0UB/wHfAYcBLgH/AdgBhgEsAf8BnQFiASEB/wF3AUgBGwH/AxIBGRAAAzgBXANe
AdgBeQGHAv8BgwGNAv8BcgGDAv8BXQFrAv8DXgHYAzgBXCAAAzgBXANeAdgB/wHHAXkC/wHMAYMC/wHC
AXIC/wG8AV0B/wNeAdgDOAFcEAABagGBAf0B/wHsAeUC/wEsAUAB2AH/ASUBNAGyAf8DuAH/A7gB/wO4
Af8DuAH/A7gB/wOmAf8DmAH/AWoBgQH9Af8B7AHlAv8BLAFAAdgB/wElATQBsgH/AxIBGQH9AbQBagL/
Af0B5QH/AdgBhgEsAf8BsgFuASUB/wO4Af8DuAH/A7gB/wO4Af8DuAH/A6YB/wOYAf8B/QG0AWoC/wH9
AeUB/wHYAYYBLAH/AbIBbgElAf8DEgEZHAADIwEzAyMBMzgAAyMBMwMjATMcAAMwAUwBagGBAf0B/wEu
AUYB3wH/AzABTBwAAzABTAFqAYEB/QH/AS4BRgHfAf8DMAFMBAADMAFMAf0BtAFqAf8B3wGHAS4B/wMw
AUwcAAMwAUwB/QG0AWoB/wHfAYcBLgH/AzABTAQAAUIBTQE+BwABPgMAASgDAAFAAwABIAMAAQEBAAEB
BgABARYAA/8BAAGPAf8BjwH/BAABBwH/AQcB/wQAAQcB/wEHAf8EAAEHAf8BBwH/BAABAwH/AQMB/wQA
AcEBjwHBAY8EAAHgAQ8B4AEPBAAB8AEfAfABHwQAAfgBPwH4AT8EAAH8AR8B/AEfBAAB/gEPAf4BDwQA
Af8BAQH/AQEEAAH/AYAB/wGABAAB/wHAAf8BwAQAAf8B4AH/AeAEAAH/AeEB/wHhBAAB+AEHAfgBBwGP
@ -230,4 +230,10 @@
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>122, 17</value>
</metadata>
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>122, 17</value>
</metadata>
<metadata name="updatetimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>219, 17</value>
</metadata>
</root>