diff --git a/Build/Builder.exe b/Build/Builder.exe
new file mode 100644
index 0000000000000000000000000000000000000000..112682d98bc8a45d788bc5eb7a869811aacbdcbb
Binary files /dev/null and b/Build/Builder.exe differ
diff --git a/Build/Plugins/BuilderModes.dll b/Build/Plugins/BuilderModes.dll
new file mode 100644
index 0000000000000000000000000000000000000000..05c96fd4fff1fcae17693f482e309ab86a5dd56d
Binary files /dev/null and b/Build/Plugins/BuilderModes.dll differ
diff --git a/Build/Plugins/ColorPicker.dll b/Build/Plugins/ColorPicker.dll
new file mode 100644
index 0000000000000000000000000000000000000000..cd85d7d8feddb25cfee96b10a784034292eb46ed
Binary files /dev/null and b/Build/Plugins/ColorPicker.dll differ
diff --git a/Build/Plugins/CopyPasteSectorProps.dll b/Build/Plugins/CopyPasteSectorProps.dll
new file mode 100644
index 0000000000000000000000000000000000000000..2f364263d489e697ca6ba1ce695cac22e2f73b23
Binary files /dev/null and b/Build/Plugins/CopyPasteSectorProps.dll differ
diff --git a/Build/Plugins/GZDoomEditing.dll b/Build/Plugins/GZDoomEditing.dll
new file mode 100644
index 0000000000000000000000000000000000000000..ea6290fa4a057ebd9d45c2b5a40d04ffb5617c19
Binary files /dev/null and b/Build/Plugins/GZDoomEditing.dll differ
diff --git a/Build/Plugins/GZDoomEditing.txt b/Build/Plugins/GZDoomEditing.txt
new file mode 100644
index 0000000000000000000000000000000000000000..0970b4dfff6901deec4b5bb6232c4426699fb2c9
--- /dev/null
+++ b/Build/Plugins/GZDoomEditing.txt
@@ -0,0 +1,57 @@
+
+Doom Builder Plugin Information
+===========================================================================
+
+Title:                  (G)ZDoom Editing Plugin
+
+Author:                 Pascal vd Heiden
+
+Plugin version:         0.0
+
+Core version needed:    2.1.0.1394
+
+
+
+Description
+===========================================================================
+
+This plugins adds features to help editing with the new features in the
+ZDoom and GZDoom sourceports and those derived from these sourceports.
+
+List of supported features in this plugin:
+- Slopes
+- 3D floors (also sloped)
+- Colored sector lighting
+- Light levels in sectors (also sloped)
+- Flat scaling, rotation and offsets
+- Texture scaling and offsets
+
+
+
+Installation
+===========================================================================
+
+1) Place the GZDoomEditing.dll file in Doom Builder's "Plugins" directory.
+
+2) Start Doom Builder and go to Tools menu, Preferences. Choose the
+Controls tab and find the "GZDoom Visual Mode" action in the Modes group.
+Set this action to a key you wish to use to switch into and out from
+Visual Mode. You can give this the same key as your original mode, because
+now we will replace the original Visual Mode with the new one.
+
+3) Go to Tools menu, Game Configurations. Choose the game configuration on
+which you wish to use the new Visual Mode. This plugin is made for UDMF
+formats, but some features also work for Hexen format. Go to the Modes tab
+and UNCHECK the original Visual Mode and CHECK the "GZDoom Visual Mode".
+
+You can also have both Visual Modes together (simply do not uncheck the
+original Visual Modein step 3) but you will need a different key for the
+action that switches to the mode.
+
+
+
+Usage
+===========================================================================
+
+I don't feel like writing this now. Figure it out yourself.
+
diff --git a/Build/Plugins/WadAuthorMode.dll b/Build/Plugins/WadAuthorMode.dll
new file mode 100644
index 0000000000000000000000000000000000000000..628fe7edec3ca233109acfabf6dd7b66ac863f22
Binary files /dev/null and b/Build/Plugins/WadAuthorMode.dll differ
diff --git a/Source/Core/Builder.csproj b/Source/Core/Builder.csproj
index 21271f529d0ab303b45c7761e37812582e582d44..c06dc53540d57a12047244a67ea090d333caeb87 100644
--- a/Source/Core/Builder.csproj
+++ b/Source/Core/Builder.csproj
@@ -705,6 +705,12 @@
     <Compile Include="General\ErrorItem.cs" />
     <Compile Include="General\ErrorLogger.cs" />
     <Compile Include="General\SavePurpose.cs" />
+    <Compile Include="GZBuilder\Controls\ConsoleDocker.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="GZBuilder\Controls\ConsoleDocker.Designer.cs">
+      <DependentUpon>ConsoleDocker.cs</DependentUpon>
+    </Compile>
     <Compile Include="GZBuilder\Data\BoundingBox.cs" />
     <Compile Include="GZBuilder\Data\GZDoomLight.cs" />
     <Compile Include="GZBuilder\Data\ModelDefEntry.cs" />
@@ -713,12 +719,6 @@
     <Compile Include="GZBuilder\IO\ModelDefParser.cs" />
     <Compile Include="GZBuilder\md3\GZModel.cs" />
     <Compile Include="GZBuilder\md3\ModelReader.cs" />
-    <Compile Include="GZBuilder\Windows\DebugForm.cs">
-      <SubType>Form</SubType>
-    </Compile>
-    <Compile Include="GZBuilder\Windows\DebugForm.designer.cs">
-      <DependentUpon>DebugForm.cs</DependentUpon>
-    </Compile>
     <Compile Include="IO\DoomColormapReader.cs" />
     <Compile Include="Map\SelectionType.cs" />
     <Compile Include="Map\MapElementCollection.cs" />
@@ -785,8 +785,8 @@
       <SubType>Designer</SubType>
       <DependentUpon>ThingBrowserControl.cs</DependentUpon>
     </EmbeddedResource>
-    <EmbeddedResource Include="GZBuilder\Windows\DebugForm.resx">
-      <DependentUpon>DebugForm.cs</DependentUpon>
+    <EmbeddedResource Include="GZBuilder\Controls\ConsoleDocker.resx">
+      <DependentUpon>ConsoleDocker.cs</DependentUpon>
     </EmbeddedResource>
     <EmbeddedResource Include="Resources\Crosshair.png" />
     <EmbeddedResource Include="Resources\CrosshairBusy.png" />
diff --git a/Source/Core/Builder.sln b/Source/Core/Builder.sln
index 0ee1d968cdbb629bd452be1a56a2b50e10155aa2..754c0063434b1a105f150b3bc8024132ab0d02ee 100644
--- a/Source/Core/Builder.sln
+++ b/Source/Core/Builder.sln
@@ -3,16 +3,64 @@ Microsoft Visual Studio Solution File, Format Version 10.00
 # Visual C# Express 2008
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Builder", "Builder.csproj", "{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColorPicker", "..\Plugins\ColorPicker\ColorPicker.csproj", "{A4761900-0EA3-4FE4-A919-847FD5080EFC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GZDoomEditing", "..\Plugins\GZDoomEditing\GZDoomEditing.csproj", "{760A9BC7-CB73-4C36-858B-994C14996FCD}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BuilderModes", "..\Plugins\BuilderModes\BuilderModes.csproj", "{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Debug|Mixed Platforms = Debug|Mixed Platforms
 		Debug|x86 = Debug|x86
+		Release|Any CPU = Release|Any CPU
+		Release|Mixed Platforms = Release|Mixed Platforms
 		Release|x86 = Release|x86
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Debug|Any CPU.ActiveCfg = Debug|x86
+		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Debug|Mixed Platforms.Build.0 = Debug|x86
 		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Debug|x86.ActiveCfg = Debug|x86
 		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Debug|x86.Build.0 = Debug|x86
+		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|Any CPU.ActiveCfg = Release|x86
+		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|Mixed Platforms.ActiveCfg = Release|x86
+		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|Mixed Platforms.Build.0 = Release|x86
 		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|x86.ActiveCfg = Release|x86
 		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|x86.Build.0 = Release|x86
+		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Debug|x86.ActiveCfg = Debug|x86
+		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Debug|x86.Build.0 = Debug|x86
+		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|Any CPU.Build.0 = Release|Any CPU
+		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|x86.ActiveCfg = Release|x86
+		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|x86.Build.0 = Release|x86
+		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|Any CPU.ActiveCfg = Debug|x86
+		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|Mixed Platforms.Build.0 = Debug|x86
+		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|x86.ActiveCfg = Debug|x86
+		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|x86.Build.0 = Debug|x86
+		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|Any CPU.ActiveCfg = Release|x86
+		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|Mixed Platforms.ActiveCfg = Release|x86
+		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|Mixed Platforms.Build.0 = Release|x86
+		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|x86.ActiveCfg = Release|x86
+		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|x86.Build.0 = Release|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|Any CPU.ActiveCfg = Debug|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|Mixed Platforms.Build.0 = Debug|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|x86.ActiveCfg = Debug|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|x86.Build.0 = Debug|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|Any CPU.ActiveCfg = Release|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|Mixed Platforms.ActiveCfg = Release|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|Mixed Platforms.Build.0 = Release|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|x86.ActiveCfg = Release|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|x86.Build.0 = Release|x86
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/Source/Core/GZBuilder/Controls/ConsoleDocker.Designer.cs b/Source/Core/GZBuilder/Controls/ConsoleDocker.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..455790be57001cd6e85c3ae4dc9bc2a799ec6b14
--- /dev/null
+++ b/Source/Core/GZBuilder/Controls/ConsoleDocker.Designer.cs
@@ -0,0 +1,90 @@
+namespace CodeImp.DoomBuilder.GZBuilder.Controls
+{
+    partial class ConsoleDocker
+    {
+#if DEBUG        
+        /// <summary> 
+        /// Требуется переменная конструктора.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Освободить все используемые ресурсы.
+        /// </summary>
+        /// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
+        protected override void Dispose(bool disposing) {
+            if (disposing && (components != null)) {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Код, автоматически созданный конструктором компонентов
+
+        /// <summary> 
+        /// Обязательный метод для поддержки конструктора - не изменяйте 
+        /// содержимое данного метода при помощи редактора кода.
+        /// </summary>
+        private void InitializeComponent() {
+            this.buttonClear = new System.Windows.Forms.Button();
+            this.textBox = new System.Windows.Forms.TextBox();
+            this.label1 = new System.Windows.Forms.Label();
+            this.SuspendLayout();
+            // 
+            // buttonClear
+            // 
+            this.buttonClear.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.buttonClear.Location = new System.Drawing.Point(3, 274);
+            this.buttonClear.Name = "buttonClear";
+            this.buttonClear.Size = new System.Drawing.Size(244, 23);
+            this.buttonClear.TabIndex = 0;
+            this.buttonClear.Text = "Clear";
+            this.buttonClear.UseVisualStyleBackColor = true;
+            this.buttonClear.Click += new System.EventHandler(this.buttonClear_Click);
+            // 
+            // textBox
+            // 
+            this.textBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                        | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.textBox.Location = new System.Drawing.Point(3, 24);
+            this.textBox.Multiline = true;
+            this.textBox.Name = "textBox";
+            this.textBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+            this.textBox.Size = new System.Drawing.Size(244, 244);
+            this.textBox.TabIndex = 1;
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
+            this.label1.Location = new System.Drawing.Point(3, 7);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(53, 14);
+            this.label1.TabIndex = 2;
+            this.label1.Text = "Console";
+            // 
+            // ConsoleDocker
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+            this.Controls.Add(this.label1);
+            this.Controls.Add(this.textBox);
+            this.Controls.Add(this.buttonClear);
+            this.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
+            this.Name = "ConsoleDocker";
+            this.Size = new System.Drawing.Size(250, 300);
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Button buttonClear;
+        private System.Windows.Forms.TextBox textBox;
+        private System.Windows.Forms.Label label1;
+#endif
+    }
+}
diff --git a/Source/Core/GZBuilder/Controls/ConsoleDocker.cs b/Source/Core/GZBuilder/Controls/ConsoleDocker.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a19aaebb3e852a86dae60030c98ac47d8f6049e5
--- /dev/null
+++ b/Source/Core/GZBuilder/Controls/ConsoleDocker.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Windows.Forms;
+
+namespace CodeImp.DoomBuilder.GZBuilder.Controls
+{
+    public partial class ConsoleDocker : UserControl
+    {
+#if DEBUG        
+        public ConsoleDocker() {
+            InitializeComponent();
+        }
+
+        public void TraceInHeader(string message) {
+            label1.Text = message;
+        }
+
+        public void Trace(string message) {
+            Trace(message, true);
+        }
+
+        public void Trace(string message, bool addLineBreak) {
+            textBox.AppendText(message + (addLineBreak ? Environment.NewLine : ""));
+        }
+
+        public void Clear() {
+            textBox.Clear();
+        }
+
+//events
+        private void buttonClear_Click(object sender, EventArgs e) {
+            textBox.Clear();
+        }
+#endif
+    }
+}
diff --git a/Source/Core/GZBuilder/Controls/ConsoleDocker.resx b/Source/Core/GZBuilder/Controls/ConsoleDocker.resx
new file mode 100644
index 0000000000000000000000000000000000000000..ff31a6db56e23b5a334f34387830ba5b4bd33eb8
--- /dev/null
+++ b/Source/Core/GZBuilder/Controls/ConsoleDocker.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
diff --git a/Source/Core/GZBuilder/GZGeneral.cs b/Source/Core/GZBuilder/GZGeneral.cs
index 523898e803826b4f889ee5dec11f61414093d631..20e9ce0af696a5bea4f6027b4fb2ef68e57a881b 100644
--- a/Source/Core/GZBuilder/GZGeneral.cs
+++ b/Source/Core/GZBuilder/GZGeneral.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Drawing;
 using System.Windows.Forms;
 
+using CodeImp.DoomBuilder.Controls;
 using CodeImp.DoomBuilder.Map;
 using CodeImp.DoomBuilder.ZDoom;
 using CodeImp.DoomBuilder.Actions;
@@ -11,7 +12,7 @@ using CodeImp.DoomBuilder.Config;
 
 using CodeImp.DoomBuilder.GZBuilder.IO;
 using CodeImp.DoomBuilder.GZBuilder.Data;
-using CodeImp.DoomBuilder.GZBuilder.Windows;
+using CodeImp.DoomBuilder.GZBuilder.Controls;
 
 using ColladaDotNet.Pipeline.MD3;
 
@@ -24,17 +25,20 @@ namespace CodeImp.DoomBuilder.GZBuilder
         public static Dictionary<int, ModelDefEntry> ModelDefEntries { get { return modelDefEntries; } }
 
         //gzdoom light types
-        private static int[] gz_lights = { /* normal lights */ 9800, 9801, 9802, 9803, 9804, /* additive lights */ 9810, 9811, 9812, 9813, 9814, /* negative lights */ 9820, 9821, 9822, 9823, 9824, /* vavoom lights */ 1502, 1503};
-        public static int[] GZ_LIGHTS { get { return gz_lights; } }
-        private static int[] gz_lightTypes = { 5, 10, 15 };
-        public static int[] GZ_LIGHT_TYPES { get { return gz_lightTypes; } } 
+        private static int[] gzLights = { /* normal lights */ 9800, 9801, 9802, 9803, 9804, /* additive lights */ 9810, 9811, 9812, 9813, 9814, /* negative lights */ 9820, 9821, 9822, 9823, 9824, /* vavoom lights */ 1502, 1503};
+        public static int[] GZ_LIGHTS { get { return gzLights; } }
+        private static int[] gzLightTypes = { 5, 10, 15 }; //this is actually offsets in gz_lights
+        public static int[] GZ_LIGHT_TYPES { get { return gzLightTypes; } }
+        private static int[] gzAnimatedLightTypes = { (int)GZDoomLightType.FLICKER, (int)GZDoomLightType.RANDOM, (int)GZDoomLightType.PULSE };
+        public static int[] GZ_ANIMATED_LIGHT_TYPES {  get { return gzAnimatedLightTypes; } }
+
 
         //version
-        public const string Version = "1.04";
+        public const float Version = 1.05f;
 
-        //debug form
+        //debug console
 #if DEBUG
-        private static DebugForm form;
+        private static Docker console;
 #endif
 
 
@@ -43,26 +47,33 @@ namespace CodeImp.DoomBuilder.GZBuilder
             General.Actions.BindMethods(typeof(GZGeneral));
             General.MainWindow.UpdateGZDoomPannel();
 
-            //create debug form
+            //create console
 #if DEBUG
-            form = new DebugForm();
-            form.Show();
-            form.Location = new Point(General.MainWindow.Location.X + General.MainWindow.Width, General.MainWindow.Location.Y);
-            form.Height = General.MainWindow.Height;
+            ConsoleDocker cd = new ConsoleDocker();
+            console = new Docker("consoledockerpannel", "Console", cd);
+            ((MainForm)General.Interface).addDocker(console);
+            ((MainForm)General.Interface).selectDocker(console);
 #endif
         }
 
         public static void OnMapOpenEnd() {
             loadModelDefs();
             loadModels();
+            General.MainWindow.UpdateGZDoomPannel();
         }
 
         public static void OnReloadResources() {
             loadModelDefs();
             loadModels();
+
+#if DEBUG
+            ((ConsoleDocker)console.Control).Clear();
+#endif
         }
 
-        //!!!!!!!!!!! General.Map.FormatInterface.HasCustomFields  == UMDF!!!!!!!!
+        //General.Map.Config.FormatInterface == "UniversalMapSetIO"  == UMDF
+        //General.Interface.RedrawDisplay();
+        //General.Editing.Mode is ClassicMode
 
         public static bool LoadModelForThing(Thing t) {
             if (modelDefEntries.ContainsKey(t.Type)) {
@@ -129,23 +140,23 @@ namespace CodeImp.DoomBuilder.GZBuilder
 //debug
         public static void Trace(string message) {
 #if DEBUG
-            form.TextPannel.AppendText(message);
+            ((ConsoleDocker)console.Control).Trace(message);
 #endif
         }
-        public static void TraceLine(string message) {
+        public static void Trace(string message, bool addLineBreak) {
 #if DEBUG
-            form.TextPannel.AppendText(message + Environment.NewLine);
+            ((ConsoleDocker)console.Control).Trace(message, addLineBreak);
 #endif
         }
         public static void ClearTrace() {
 #if DEBUG
-            form.TextPannel.Text = "";
+            ((ConsoleDocker)console.Control).Clear();
 #endif
         }
 
         public static void TraceInHeader(string message) {
 #if DEBUG
-            form.Text = message;
+            ((ConsoleDocker)console.Control).TraceInHeader(message);
 #endif
         }
 
@@ -211,16 +222,9 @@ namespace CodeImp.DoomBuilder.GZBuilder
             General.MainWindow.RedrawDisplay();
         }
 
-        [BeginAction("gztogglelightpannel")]
-        public static void ToggleLightPannel() {
-            General.ShowWarningMessage("Not implemented yet...", MessageBoxButtons.OK);
-        }
-
         [BeginAction("gztogglefogpannel")]
         public static void ToggleFogPannel() {
             General.ShowWarningMessage("Not implemented yet...", MessageBoxButtons.OK);
         }
-
-
     }
 }
diff --git a/Source/Core/GZBuilder/IO/ModelDefParser.cs b/Source/Core/GZBuilder/IO/ModelDefParser.cs
index a07e05047349765fb661924f1f6d6b2465f0c925..a5852838b6ac9651353ab23faa208ed3d71425a9 100644
--- a/Source/Core/GZBuilder/IO/ModelDefParser.cs
+++ b/Source/Core/GZBuilder/IO/ModelDefParser.cs
@@ -16,17 +16,14 @@ namespace CodeImp.DoomBuilder.GZBuilder.IO
                     Parse(modelDefEntriesByName, path, fileName);
             }
 
-            //dbg
             #if DEBUG
                 General.ErrorLogger.Add(ErrorType.Warning, "ModelDefParser: parsed " + modelDefEntriesByName.Count + " definitions;");
             #else
                 General.WriteLogLine("ModelDefParser: parsed " + modelDefEntriesByName.Count + " definitions;");
             #endif
-
         }
 
         public static void Parse(Dictionary<string, ModelDefEntry> modelDefEntriesByName, string path, string fileName) {
-            //dbg
             #if DEBUG
                 General.ErrorLogger.Add(ErrorType.Warning, "ModelDefParser: Parsing '" + fileName + "'");
             #else
diff --git a/Source/Core/GZBuilder/Windows/ColorChangedEventArgs.cs b/Source/Core/GZBuilder/Windows/ColorChangedEventArgs.cs
new file mode 100644
index 0000000000000000000000000000000000000000..ff218e9059dcb9f3c5c875a88336e9009e59144c
--- /dev/null
+++ b/Source/Core/GZBuilder/Windows/ColorChangedEventArgs.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace CodeImp.DoomBuilder.GZBuilder.Windows {
+    public class ColorChangedEventArgs : EventArgs {
+        private ColorHandler.RGB mRGB;
+        private ColorHandler.HSV mHSV;
+
+        public ColorChangedEventArgs(ColorHandler.RGB RGB, ColorHandler.HSV HSV) {
+            mRGB = RGB;
+            mHSV = HSV;
+        }
+
+        public ColorHandler.RGB RGB { get { return mRGB; } }
+        public ColorHandler.HSV HSV { get { return mHSV; } }
+    }
+}
\ No newline at end of file
diff --git a/Source/Core/GZBuilder/Windows/ColorChooserForm.cs b/Source/Core/GZBuilder/Windows/ColorChooserForm.cs
new file mode 100644
index 0000000000000000000000000000000000000000..3a30dc7abb4294d241ee6845580208a33cdac6d4
--- /dev/null
+++ b/Source/Core/GZBuilder/Windows/ColorChooserForm.cs
@@ -0,0 +1,493 @@
+using System;
+using System.Drawing;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Windows.Forms;
+
+using CodeImp.DoomBuilder.Map;
+using CodeImp.DoomBuilder.Windows;
+
+namespace CodeImp.DoomBuilder.GZBuilder.Windows {
+    public class ColorChooserForm : DelayedForm {
+        internal System.Windows.Forms.Button btnCancel;
+        internal System.Windows.Forms.Button btnOK;
+        internal System.Windows.Forms.Label Label3;
+        internal System.Windows.Forms.NumericUpDown nudRed;
+        internal System.Windows.Forms.Panel pnlColor;
+        internal System.Windows.Forms.Label Label1;
+        internal System.Windows.Forms.Panel pnlBrightness;
+        internal System.Windows.Forms.NumericUpDown nudBlue;
+        internal System.Windows.Forms.NumericUpDown nudGreen;
+        internal System.Windows.Forms.Label Label2;
+        private Dotnetrix.Controls.TrackBar trackBar1;
+        internal Label labelName1;
+        internal Label labelName2;
+        private Dotnetrix.Controls.TrackBar trackBar2;
+        internal NumericUpDown numericUpDown1;
+        internal NumericUpDown numericUpDown2;
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.Container components = null;
+
+        public ColorChooserForm() {
+            InitializeComponent();
+
+
+        }
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        protected override void Dispose(bool disposing) {
+            if (disposing) {
+                if (components != null) {
+                    components.Dispose();
+                }
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent() {
+            this.btnCancel = new System.Windows.Forms.Button();
+            this.btnOK = new System.Windows.Forms.Button();
+            this.Label3 = new System.Windows.Forms.Label();
+            this.nudRed = new System.Windows.Forms.NumericUpDown();
+            this.pnlColor = new System.Windows.Forms.Panel();
+            this.Label1 = new System.Windows.Forms.Label();
+            this.pnlBrightness = new System.Windows.Forms.Panel();
+            this.nudBlue = new System.Windows.Forms.NumericUpDown();
+            this.nudGreen = new System.Windows.Forms.NumericUpDown();
+            this.Label2 = new System.Windows.Forms.Label();
+            this.trackBar1 = new Dotnetrix.Controls.TrackBar();
+            this.labelName1 = new System.Windows.Forms.Label();
+            this.labelName2 = new System.Windows.Forms.Label();
+            this.trackBar2 = new Dotnetrix.Controls.TrackBar();
+            this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
+            this.numericUpDown2 = new System.Windows.Forms.NumericUpDown();
+            ((System.ComponentModel.ISupportInitialize)(this.nudRed)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.nudBlue)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.nudGreen)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.trackBar2)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // btnCancel
+            // 
+            this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+            this.btnCancel.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
+            this.btnCancel.Font = new System.Drawing.Font("Arial", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.btnCancel.Location = new System.Drawing.Point(219, 49);
+            this.btnCancel.Name = "btnCancel";
+            this.btnCancel.Size = new System.Drawing.Size(94, 42);
+            this.btnCancel.TabIndex = 11;
+            this.btnCancel.Text = "Cancel";
+            this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
+            // 
+            // btnOK
+            // 
+            this.btnOK.BackColor = System.Drawing.SystemColors.Control;
+            this.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK;
+            this.btnOK.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
+            this.btnOK.Font = new System.Drawing.Font("Arial", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.btnOK.ForeColor = System.Drawing.SystemColors.ControlText;
+            this.btnOK.Location = new System.Drawing.Point(219, 8);
+            this.btnOK.Name = "btnOK";
+            this.btnOK.Size = new System.Drawing.Size(94, 42);
+            this.btnOK.TabIndex = 10;
+            this.btnOK.Text = "OK";
+            this.btnOK.UseVisualStyleBackColor = true;
+            this.btnOK.Click += new System.EventHandler(this.btnOK_Click);
+            // 
+            // Label3
+            // 
+            this.Label3.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.Label3.Location = new System.Drawing.Point(219, 152);
+            this.Label3.Name = "Label3";
+            this.Label3.Size = new System.Drawing.Size(40, 23);
+            this.Label3.TabIndex = 45;
+            this.Label3.Text = "Blue:";
+            this.Label3.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            // 
+            // nudRed
+            // 
+            this.nudRed.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.nudRed.Location = new System.Drawing.Point(265, 106);
+            this.nudRed.Maximum = new decimal(new int[] {
+            255,
+            0,
+            0,
+            0});
+            this.nudRed.Name = "nudRed";
+            this.nudRed.Size = new System.Drawing.Size(48, 20);
+            this.nudRed.TabIndex = 38;
+            this.nudRed.ValueChanged += new System.EventHandler(this.HandleRGBChange);
+            // 
+            // pnlColor
+            // 
+            this.pnlColor.Location = new System.Drawing.Point(8, 8);
+            this.pnlColor.Name = "pnlColor";
+            this.pnlColor.Size = new System.Drawing.Size(176, 176);
+            this.pnlColor.TabIndex = 51;
+            this.pnlColor.Visible = false;
+            this.pnlColor.MouseUp += new System.Windows.Forms.MouseEventHandler(this.frmMain_MouseUp);
+            // 
+            // Label1
+            // 
+            this.Label1.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.Label1.Location = new System.Drawing.Point(219, 104);
+            this.Label1.Name = "Label1";
+            this.Label1.Size = new System.Drawing.Size(40, 23);
+            this.Label1.TabIndex = 43;
+            this.Label1.Text = "Red:";
+            this.Label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            // 
+            // pnlBrightness
+            // 
+            this.pnlBrightness.Location = new System.Drawing.Point(190, 8);
+            this.pnlBrightness.Name = "pnlBrightness";
+            this.pnlBrightness.Size = new System.Drawing.Size(16, 176);
+            this.pnlBrightness.TabIndex = 52;
+            this.pnlBrightness.Visible = false;
+            // 
+            // nudBlue
+            // 
+            this.nudBlue.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.nudBlue.Location = new System.Drawing.Point(265, 154);
+            this.nudBlue.Maximum = new decimal(new int[] {
+            255,
+            0,
+            0,
+            0});
+            this.nudBlue.Name = "nudBlue";
+            this.nudBlue.Size = new System.Drawing.Size(48, 20);
+            this.nudBlue.TabIndex = 40;
+            this.nudBlue.ValueChanged += new System.EventHandler(this.HandleRGBChange);
+            // 
+            // nudGreen
+            // 
+            this.nudGreen.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.nudGreen.Location = new System.Drawing.Point(265, 130);
+            this.nudGreen.Maximum = new decimal(new int[] {
+            255,
+            0,
+            0,
+            0});
+            this.nudGreen.Name = "nudGreen";
+            this.nudGreen.Size = new System.Drawing.Size(48, 20);
+            this.nudGreen.TabIndex = 39;
+            this.nudGreen.ValueChanged += new System.EventHandler(this.HandleRGBChange);
+            // 
+            // Label2
+            // 
+            this.Label2.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.Label2.Location = new System.Drawing.Point(219, 128);
+            this.Label2.Name = "Label2";
+            this.Label2.Size = new System.Drawing.Size(40, 23);
+            this.Label2.TabIndex = 44;
+            this.Label2.Text = "Green:";
+            this.Label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            // 
+            // trackBar1
+            // 
+            this.trackBar1.LargeChange = 64;
+            this.trackBar1.Location = new System.Drawing.Point(91, 190);
+            this.trackBar1.Maximum = 512;
+            this.trackBar1.Name = "trackBar1";
+            this.trackBar1.Size = new System.Drawing.Size(166, 45);
+            this.trackBar1.SmallChange = 8;
+            this.trackBar1.TabIndex = 56;
+            this.trackBar1.TickFrequency = 16;
+            this.trackBar1.TickStyle = System.Windows.Forms.TickStyle.Both;
+            this.trackBar1.ValueChanged += new System.EventHandler(this.trackBar1_ValueChanged);
+            // 
+            // labelName1
+            // 
+            this.labelName1.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.labelName1.Location = new System.Drawing.Point(5, 199);
+            this.labelName1.Name = "labelName1";
+            this.labelName1.Size = new System.Drawing.Size(80, 23);
+            this.labelName1.TabIndex = 57;
+            this.labelName1.Text = "Start intensity:";
+            this.labelName1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            // 
+            // labelName2
+            // 
+            this.labelName2.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.labelName2.Location = new System.Drawing.Point(5, 250);
+            this.labelName2.Name = "labelName2";
+            this.labelName2.Size = new System.Drawing.Size(80, 23);
+            this.labelName2.TabIndex = 60;
+            this.labelName2.Text = "Start intensity:";
+            this.labelName2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            // 
+            // trackBar2
+            // 
+            this.trackBar2.LargeChange = 64;
+            this.trackBar2.Location = new System.Drawing.Point(91, 241);
+            this.trackBar2.Maximum = 512;
+            this.trackBar2.Name = "trackBar2";
+            this.trackBar2.Size = new System.Drawing.Size(166, 45);
+            this.trackBar2.SmallChange = 8;
+            this.trackBar2.TabIndex = 59;
+            this.trackBar2.TickFrequency = 16;
+            this.trackBar2.TickStyle = System.Windows.Forms.TickStyle.Both;
+            this.trackBar2.ValueChanged += new System.EventHandler(this.trackBar2_ValueChanged);
+            // 
+            // numericUpDown1
+            // 
+            this.numericUpDown1.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.numericUpDown1.Location = new System.Drawing.Point(257, 200);
+            this.numericUpDown1.Maximum = new decimal(new int[] {
+            9000,
+            0,
+            0,
+            0});
+            this.numericUpDown1.Name = "numericUpDown1";
+            this.numericUpDown1.Size = new System.Drawing.Size(56, 20);
+            this.numericUpDown1.TabIndex = 57;
+            this.numericUpDown1.ValueChanged += new System.EventHandler(this.numericUpDown1_ValueChanged);
+            // 
+            // numericUpDown2
+            // 
+            this.numericUpDown2.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.numericUpDown2.Location = new System.Drawing.Point(257, 250);
+            this.numericUpDown2.Maximum = new decimal(new int[] {
+            9000,
+            0,
+            0,
+            0});
+            this.numericUpDown2.Name = "numericUpDown2";
+            this.numericUpDown2.Size = new System.Drawing.Size(56, 20);
+            this.numericUpDown2.TabIndex = 62;
+            this.numericUpDown2.ValueChanged += new System.EventHandler(this.numericUpDown2_ValueChanged);
+            // 
+            // ColorChooserForm
+            // 
+            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
+            this.ClientSize = new System.Drawing.Size(319, 286);
+            this.Controls.Add(this.numericUpDown2);
+            this.Controls.Add(this.numericUpDown1);
+            this.Controls.Add(this.labelName2);
+            this.Controls.Add(this.trackBar2);
+            this.Controls.Add(this.labelName1);
+            this.Controls.Add(this.trackBar1);
+            this.Controls.Add(this.btnCancel);
+            this.Controls.Add(this.btnOK);
+            this.Controls.Add(this.Label3);
+            this.Controls.Add(this.nudRed);
+            this.Controls.Add(this.pnlColor);
+            this.Controls.Add(this.Label1);
+            this.Controls.Add(this.pnlBrightness);
+            this.Controls.Add(this.nudBlue);
+            this.Controls.Add(this.nudGreen);
+            this.Controls.Add(this.Label2);
+            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+            this.MaximizeBox = false;
+            this.MinimizeBox = false;
+            this.Name = "ColorChooserForm";
+            this.Opacity = 0;
+            this.Text = "Select Color";
+            this.Load += new System.EventHandler(this.ColorChooser1_Load);
+            this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.frmMain_MouseUp);
+            this.Paint += new System.Windows.Forms.PaintEventHandler(this.ColorChooser1_Paint);
+            this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.HandleMouse);
+            this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.HandleMouse);
+            ((System.ComponentModel.ISupportInitialize)(this.nudRed)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.nudBlue)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.nudGreen)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.trackBar2)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).EndInit();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+        #endregion
+
+        private enum ChangeStyle {
+            MouseMove,
+            RGB,
+            None
+        }
+
+        private ChangeStyle changeType = ChangeStyle.None;
+        private Point selectedPoint;
+
+        private ColorWheel colorWheel;
+        private ColorHandler.RGB RGB;
+        private bool isInUpdate = false;
+
+
+        private List<Thing> selectedLights;
+        private List<Sector> selectedLights;
+
+        //private Color startColor;
+
+        /*public void SetData(Color startColor, string[] labels) {
+            btnCancel.BackColor = startColor;
+            btnOK.BackColor = startColor;
+            if (startColor.R < 128 && startColor.G < 128 && startColor.B < 128) {
+                btnCancel.ForeColor = Color.White;
+                btnOK.ForeColor = Color.White;
+            }
+            this.startColor = startColor;
+
+            if (labels == null || labels.Length == 0) {
+                numericUpDown1.Visible = false;
+                numericUpDown2.Visible = false;
+                labelName1.Visible = false;
+                labelName2.Visible = false;
+                trackBar1.Visible = false;
+                trackBar2.Visible = false;
+                this.ClientSize = new Size(this.ClientSize.Width, trackBar1.Location.Y);
+            } else if (labels.Length == 1) {
+                labelName1.Text = labels[0] + ":";
+
+                numericUpDown2.Visible = false;
+                labelName2.Visible = false;
+                trackBar2.Visible = false;
+                this.ClientSize = new Size(this.ClientSize.Width, trackBar2.Location.Y);
+            } else {
+                labelName1.Text = labels[0] + ":";
+                labelName2.Text = labels[1] + ":";
+            }
+        }*/
+
+        private void ColorChooser1_Load(object sender, System.EventArgs e) {
+            // Turn on double-buffering, so the form looks better. 
+            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
+            this.SetStyle(ControlStyles.UserPaint, true);
+            this.SetStyle(ControlStyles.DoubleBuffer, true);
+
+            Rectangle BrightnessRectangle = new Rectangle(pnlBrightness.Location, pnlBrightness.Size);
+            Rectangle ColorRectangle = new Rectangle(pnlColor.Location, pnlColor.Size);
+
+            // Create the new ColorWheel class, indicating the locations of the color wheel itself, the
+            // brightness area, and the position of the selected color.
+            colorWheel = new ColorWheel(ColorRectangle, BrightnessRectangle);
+            colorWheel.ColorChanged += new ColorWheel.ColorChangedEventHandler(this.myColorWheel_ColorChanged);
+
+            //set initial color
+
+
+
+            isInUpdate = true;
+            changeType = ChangeStyle.RGB;
+            RGB = new ColorHandler.RGB(startColor.R, startColor.G, startColor.B);
+
+            RefreshValue(nudRed, RGB.Red);
+            RefreshValue(nudBlue, RGB.Blue);
+            RefreshValue(nudGreen, RGB.Green);
+            isInUpdate = false;
+            this.Invalidate();
+        }
+
+        private void HandleMouse(object sender, MouseEventArgs e) {
+            if (e.Button == MouseButtons.Left) {
+                changeType = ChangeStyle.MouseMove;
+                selectedPoint = new Point(e.X, e.Y);
+                this.Invalidate();
+            }
+        }
+
+        private void frmMain_MouseUp(object sender, MouseEventArgs e) {
+            colorWheel.SetMouseUp();
+            changeType = ChangeStyle.None;
+        }
+
+        private void HandleRGBChange(object sender, System.EventArgs e) {
+
+            // If the R, G, or B values change, use this code to update the HSV values and invalidate
+            // the color wheel (so it updates the pointers).
+            // Check the isInUpdate flag to avoid recursive events when you update the NumericUpdownControls.
+            if (!isInUpdate) {
+                changeType = ChangeStyle.RGB;
+                RGB = new ColorHandler.RGB((int)nudRed.Value, (int)nudGreen.Value, (int)nudBlue.Value);
+                this.Invalidate();
+            }
+        }
+
+        private void SetRGB(ColorHandler.RGB RGB) {
+            // Update the RGB values on the form, but don't trigger the ValueChanged event of the form. The isInUpdate
+            // variable ensures that the event procedures exit without doing anything.
+            isInUpdate = true;
+            RefreshValue(nudRed, RGB.Red);
+            RefreshValue(nudBlue, RGB.Blue);
+            RefreshValue(nudGreen, RGB.Green);
+
+            btnOK.BackColor = ColorHandler.RGBtoColor(RGB);
+            if (RGB.Red < 128 && RGB.Green < 128 && RGB.Blue < 128)
+                btnOK.ForeColor = Color.White;
+            else
+                btnOK.ForeColor = Color.Black;
+            isInUpdate = false;
+        }
+
+        private void RefreshValue(NumericUpDown nud, int value) {
+            // Update the value of the NumericUpDown control, if the value is different than the current value.
+            // Refresh the control, causing an immediate repaint.
+            if (nud.Value != value) {
+                nud.Value = value;
+                nud.Refresh();
+            }
+        }
+
+//Properties
+        public Color Color { get { return colorWheel.Color; } }
+        public int Value1 { get { return (int)numericUpDown1.Value; } }
+        public int Value2 { get { return (int)numericUpDown2.Value; } }
+
+//Events
+        private void myColorWheel_ColorChanged(object sender, ColorChangedEventArgs e) {
+            SetRGB(e.RGB);
+        }
+
+        private void ColorChooser1_Paint(object sender, System.Windows.Forms.PaintEventArgs e) {
+            // Depending on the circumstances, force a repaint of the color wheel passing different information.
+            switch (changeType) {
+                case ChangeStyle.MouseMove:
+                case ChangeStyle.None:
+                    colorWheel.Draw(e.Graphics, selectedPoint);
+                    break;
+                case ChangeStyle.RGB:
+                    colorWheel.Draw(e.Graphics, RGB);
+                    break;
+            }
+        }
+
+        private void trackBar1_ValueChanged(object sender, EventArgs e) {
+            numericUpDown1.Value = trackBar1.Value;
+        }
+
+        private void trackBar2_ValueChanged(object sender, EventArgs e) {
+            numericUpDown2.Value = trackBar2.Value;
+        }
+
+        private void numericUpDown1_ValueChanged(object sender, EventArgs e) {
+            trackBar1.Value = (int)numericUpDown1.Value > trackBar1.Maximum ? trackBar1.Maximum : (int)numericUpDown1.Value;
+        }
+
+        private void numericUpDown2_ValueChanged(object sender, EventArgs e) {
+            trackBar2.Value = (int)numericUpDown2.Value > trackBar2.Maximum ? trackBar2.Maximum : (int)numericUpDown2.Value;
+        }
+
+//buttons
+        private void btnOK_Click(object sender, EventArgs e) {
+            this.Close();
+        }
+
+        private void btnCancel_Click(object sender, EventArgs e) {
+            this.Close();
+        }
+    }
+}
diff --git a/Source/Core/GZBuilder/Windows/ColorChooserForm.resx b/Source/Core/GZBuilder/Windows/ColorChooserForm.resx
new file mode 100644
index 0000000000000000000000000000000000000000..ff31a6db56e23b5a334f34387830ba5b4bd33eb8
--- /dev/null
+++ b/Source/Core/GZBuilder/Windows/ColorChooserForm.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
diff --git a/Source/Core/GZBuilder/Windows/ColorHandler.cs b/Source/Core/GZBuilder/Windows/ColorHandler.cs
new file mode 100644
index 0000000000000000000000000000000000000000..0c3a77ed35ba2b148a79d09d3a3662f05d2ed401
--- /dev/null
+++ b/Source/Core/GZBuilder/Windows/ColorHandler.cs
@@ -0,0 +1,210 @@
+using System;
+using System.Drawing;
+
+namespace CodeImp.DoomBuilder.GZBuilder.Windows {
+    public class ColorHandler {
+        // Handle conversions between RGB and HSV    
+        // (and Color types, as well).
+        public struct RGB {
+            // All values are between 0 and 255.
+            public int Red;
+            public int Green;
+            public int Blue;
+
+            public RGB(int R, int G, int B) {
+                Red = R;
+                Green = G;
+                Blue = B;
+            }
+
+        }
+
+        public struct HSV {
+            // All values are between 0 and 255.
+            public int Hue;
+            public int Saturation;
+            public int value;
+
+            public HSV(int H, int S, int V) {
+                Hue = H;
+                Saturation = S;
+                value = V;
+            }
+
+            public override string ToString() {
+                return String.Format("({0}, {1}, {2})", Hue, Saturation, value);
+            }
+        }
+
+        public static RGB HSVtoRGB(int H, int S, int V) {
+            // H, S, and V must all be between 0 and 255.
+            return HSVtoRGB(new HSV(H, S, V));
+        }
+
+        public static Color HSVtoColor(HSV hsv) {
+            RGB RGB = HSVtoRGB(hsv);
+            return Color.FromArgb(RGB.Red, RGB.Green, RGB.Blue);
+        }
+
+        public static Color HSVtoColor(int H, int S, int V) {
+            return HSVtoColor(new HSV(H, S, V));
+        }
+
+        public static Color RGBtoColor(RGB rgb) {
+            return Color.FromArgb(rgb.Red, rgb.Green, rgb.Blue);
+        }
+
+        public static RGB HSVtoRGB(HSV HSV) {
+            // HSV contains values scaled as in the color wheel:
+            // that is, all from 0 to 255. 
+
+            // for ( this code to work, HSV.Hue needs
+            // to be scaled from 0 to 360 (it//s the angle of the selected
+            // point within the circle). HSV.Saturation and HSV.value must be 
+            // scaled to be between 0 and 1.
+
+            double h;
+            double s;
+            double v;
+
+            double r = 0;
+            double g = 0;
+            double b = 0;
+
+            // Scale Hue to be between 0 and 360. Saturation
+            // and value scale to be between 0 and 1.
+            h = ((double)HSV.Hue / 255 * 360) % 360;
+            s = (double)HSV.Saturation / 255;
+            v = (double)HSV.value / 255;
+
+            if (s == 0) {
+                // If s is 0, all colors are the same.
+                // This is some flavor of gray.
+                r = v;
+                g = v;
+                b = v;
+            } else {
+                double p;
+                double q;
+                double t;
+
+                double fractionalSector;
+                int sectorNumber;
+                double sectorPos;
+
+                // The color wheel consists of 6 sectors.
+                // Figure out which sector you//re in.
+                sectorPos = h / 60;
+                sectorNumber = (int)(Math.Floor(sectorPos));
+
+                // get the fractional part of the sector.
+                // That is, how many degrees into the sector
+                // are you?
+                fractionalSector = sectorPos - sectorNumber;
+
+                // Calculate values for the three axes
+                // of the color. 
+                p = v * (1 - s);
+                q = v * (1 - (s * fractionalSector));
+                t = v * (1 - (s * (1 - fractionalSector)));
+
+                // Assign the fractional colors to r, g, and b
+                // based on the sector the angle is in.
+                switch (sectorNumber) {
+                    case 0:
+                        r = v;
+                        g = t;
+                        b = p;
+                        break;
+
+                    case 1:
+                        r = q;
+                        g = v;
+                        b = p;
+                        break;
+
+                    case 2:
+                        r = p;
+                        g = v;
+                        b = t;
+                        break;
+
+                    case 3:
+                        r = p;
+                        g = q;
+                        b = v;
+                        break;
+
+                    case 4:
+                        r = t;
+                        g = p;
+                        b = v;
+                        break;
+
+                    case 5:
+                        r = v;
+                        g = p;
+                        b = q;
+                        break;
+                }
+            }
+            // return an RGB structure, with values scaled
+            // to be between 0 and 255.
+            return new RGB((int)(r * 255), (int)(g * 255), (int)(b * 255));
+        }
+
+        public static HSV RGBtoHSV(RGB RGB) {
+            // In this function, R, G, and B values must be scaled 
+            // to be between 0 and 1.
+            // HSV.Hue will be a value between 0 and 360, and 
+            // HSV.Saturation and value are between 0 and 1.
+            // The code must scale these to be between 0 and 255 for
+            // the purposes of this application.
+
+            double min;
+            double max;
+            double delta;
+
+            double r = (double)RGB.Red / 255;
+            double g = (double)RGB.Green / 255;
+            double b = (double)RGB.Blue / 255;
+
+            double h;
+            double s;
+            double v;
+
+            min = Math.Min(Math.Min(r, g), b);
+            max = Math.Max(Math.Max(r, g), b);
+            v = max;
+            delta = max - min;
+            if (max == 0 || delta == 0) {
+                // R, G, and B must be 0, or all the same. In this case, S is 0, and H is undefined.
+                // Using H = 0 is as good as any...
+                s = 0;
+                h = 0;
+            } else {
+                s = delta / max;
+                if (r == max) {
+                    // Between Yellow and Magenta
+                    h = (g - b) / delta;
+                } else if (g == max) {
+                    // Between Cyan and Yellow
+                    h = 2 + (b - r) / delta;
+                } else {
+                    // Between Magenta and Cyan
+                    h = 4 + (r - g) / delta;
+                }
+
+            }
+            // Scale h to be between 0 and 360. 
+            // This may require adding 360, if the value is negative.
+            h *= 60;
+            if (h < 0) {
+                h += 360;
+            }
+
+            // Scale to the requirements of this application. All values are between 0 and 255.
+            return new HSV((int)(h / 360 * 255), (int)(s * 255), (int)(v * 255));
+        }
+    }
+}
diff --git a/Source/Core/GZBuilder/Windows/ColorWheel.cs b/Source/Core/GZBuilder/Windows/ColorWheel.cs
new file mode 100644
index 0000000000000000000000000000000000000000..df42e2076e6c6b95a42b5caa0c04d2bc7b6902ed
--- /dev/null
+++ b/Source/Core/GZBuilder/Windows/ColorWheel.cs
@@ -0,0 +1,469 @@
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+
+namespace CodeImp.DoomBuilder.GZBuilder.Windows {
+    public class ColorWheel : IDisposable {
+
+        // These resources should be disposed
+        // of when you're done with them.
+        private Graphics g;
+        private Region colorRegion;
+        private Region brightnessRegion;
+        private Bitmap colorImage;
+
+        public delegate void ColorChangedEventHandler(object sender, ColorChangedEventArgs e);
+        public ColorChangedEventHandler ColorChanged;
+
+        // Keep track of the current mouse state. 
+        public enum MouseState {
+            MouseUp,
+            ClickOnColor,
+            DragInColor,
+            ClickOnBrightness,
+            DragInBrightness,
+            ClickOutsideRegion,
+            DragOutsideRegion,
+        }
+        private MouseState currentState = MouseState.MouseUp;
+
+        // The code needs to convert back and forth between 
+        // degrees and radians. There are 2*PI radians in a 
+        // full circle, and 360 degrees. This constant allows
+        // you to convert back and forth.
+        private const double DEGREES_PER_RADIAN = 180.0 / Math.PI;
+
+        // COLOR_COUNT represents the number of distinct colors
+        // used to create the circular gradient. Its value 
+        // is somewhat arbitrary -- change this to 6, for 
+        // example, to see what happens. 1536 (6 * 256) seems 
+        // a good compromise -- it's enough to get a full 
+        // range of colors, but it doesn't overwhelm the processor
+        // attempting to generate the image. The color wheel
+        // contains 6 sections, and each section displays 
+        // 256 colors. Seems like a reasonable compromise.
+        private const int COLOR_COUNT = 6 * 256;
+
+        private Point centerPoint;
+        private int radius;
+
+        private Rectangle colorRectangle;
+        private Rectangle brightnessRectangle;
+        private int brightnessX;
+        private double brightnessScaling;
+
+        // selectedColor is the actual value selected
+        // by the user. fullColor is the same color, 
+        // with its brightness set to 255.
+        private Color selectedColor = Color.White;
+        private Color fullColor;
+
+        private ColorHandler.RGB RGB;
+        private ColorHandler.HSV HSV;
+
+        // Locations for the two "pointers" on the form.
+        private Point colorPoint;
+        private Point brightnessPoint;
+
+        private int brightness;
+        private int brightnessMin;
+        private int brightnessMax;
+
+        public Color Color { get { return selectedColor; } }
+
+        public ColorWheel(Rectangle colorRectangle, Rectangle brightnessRectangle) {
+
+            // Caller must provide locations for color wheel
+            // (colorRectangle), brightness "strip" (brightnessRectangle)
+            // and location to display selected color (selectedColorRectangle).
+
+            using (GraphicsPath path = new GraphicsPath()) {
+                // Store away locations for later use. 
+                this.colorRectangle = colorRectangle;
+                this.brightnessRectangle = brightnessRectangle;
+                //this.selectedColorRectangle = selectedColorRectangle;
+
+                // Calculate the center of the circle.
+                // Start with the location, then offset
+                // the point by the radius.
+                // Use the smaller of the width and height of
+                // the colorRectangle value.
+                this.radius = (int)Math.Min(colorRectangle.Width, colorRectangle.Height) / 2;
+                this.centerPoint = colorRectangle.Location;
+                this.centerPoint.Offset(radius, radius);
+
+                // Start the pointer in the center.
+                this.colorPoint = this.centerPoint;
+
+                // Create a region corresponding to the color circle.
+                // Code uses this later to determine if a specified
+                // point is within the region, using the IsVisible 
+                // method.
+                path.AddEllipse(colorRectangle);
+                colorRegion = new Region(path);
+
+                // set { the range for the brightness selector.
+                this.brightnessMin = this.brightnessRectangle.Top;
+                this.brightnessMax = this.brightnessRectangle.Bottom;
+
+                // Create a region corresponding to the
+                // brightness rectangle, with a little extra 
+                // "breathing room". 
+
+                path.AddRectangle(new Rectangle(brightnessRectangle.Left, brightnessRectangle.Top - 10, brightnessRectangle.Width + 10, brightnessRectangle.Height + 20));
+                // Create region corresponding to brightness
+                // rectangle. Later code uses this to 
+                // determine if a specified point is within
+                // the region, using the IsVisible method.
+                brightnessRegion = new Region(path);
+
+                // Set the location for the brightness indicator "marker".
+                // Also calculate the scaling factor, scaling the height
+                // to be between 0 and 255. 
+                brightnessX = brightnessRectangle.Left + brightnessRectangle.Width;
+                brightnessScaling = (double)255 / (brightnessMax - brightnessMin);
+
+                // Calculate the location of the brightness
+                // pointer. Assume it's at the highest position.
+                brightnessPoint = new Point(brightnessX, brightnessMax);
+
+                // Create the bitmap that contains the circular gradient.
+                CreateGradient();
+            }
+        }
+
+        protected void OnColorChanged(ColorHandler.RGB RGB, ColorHandler.HSV HSV) {
+            ColorChangedEventArgs e = new ColorChangedEventArgs(RGB, HSV);
+            ColorChanged(this, e);
+        }
+
+        void IDisposable.Dispose() {
+            // Dispose of graphic resources
+            if (colorImage != null)
+                colorImage.Dispose();
+            if (colorRegion != null)
+                colorRegion.Dispose();
+            if (brightnessRegion != null)
+                brightnessRegion.Dispose();
+            if (g != null)
+                g.Dispose();
+        }
+
+        public void SetMouseUp() {
+            // Indicate that the user has
+            // released the mouse.
+            currentState = MouseState.MouseUp;
+        }
+
+        public void Draw(Graphics g, ColorHandler.RGB RGB) {
+            // Given RGB values, calculate HSV and then update the screen.
+            this.g = g;
+            this.HSV = ColorHandler.RGBtoHSV(RGB);
+            CalcCoordsAndUpdate(this.HSV);
+            UpdateDisplay();
+        }
+
+        public void Draw(Graphics g, Point mousePoint) {
+            // You've moved the mouse. 
+            // Now update the screen to match.
+
+            double distance;
+            int degrees;
+            Point delta;
+            Point newColorPoint;
+            Point newBrightnessPoint;
+            Point newPoint;
+
+            // Keep track of the previous color pointer point, 
+            // so you can put the mouse there in case the 
+            // user has clicked outside the circle.
+            newColorPoint = colorPoint;
+            newBrightnessPoint = brightnessPoint;
+
+            // Store this away for later use.
+            this.g = g;
+
+            if (currentState == MouseState.MouseUp) {
+                if (!mousePoint.IsEmpty) {
+                    if (colorRegion.IsVisible(mousePoint)) {
+                        // Is the mouse point within the color circle?
+                        // If so, you just clicked on the color wheel.
+                        currentState = MouseState.ClickOnColor;
+                    } else if (brightnessRegion.IsVisible(mousePoint)) {
+                        // Is the mouse point within the brightness area?
+                        // You clicked on the brightness area.
+                        currentState = MouseState.ClickOnBrightness;
+                    } else {
+                        // Clicked outside the color and the brightness
+                        // regions. In that case, just put the 
+                        // pointers back where they were.
+                        currentState = MouseState.ClickOutsideRegion;
+                    }
+                }
+            }
+
+            switch (currentState) {
+                case MouseState.ClickOnBrightness:
+                case MouseState.DragInBrightness:
+                    // Calculate new color information
+                    // based on the brightness, which may have changed.
+                    newPoint = mousePoint;
+                    if (newPoint.Y < brightnessMin) {
+                        newPoint.Y = brightnessMin;
+                    } else if (newPoint.Y > brightnessMax) {
+                        newPoint.Y = brightnessMax;
+                    }
+                    newBrightnessPoint = new Point(brightnessX, newPoint.Y);
+                    brightness = (int)((brightnessMax - newPoint.Y) * brightnessScaling);
+                    HSV.value = brightness;
+                    RGB = ColorHandler.HSVtoRGB(HSV);
+                    break;
+
+                case MouseState.ClickOnColor:
+                case MouseState.DragInColor:
+                    // Calculate new color information
+                    // based on selected color, which may have changed.
+                    newColorPoint = mousePoint;
+
+                    // Calculate x and y distance from the center,
+                    // and then calculate the angle corresponding to the
+                    // new location.
+                    delta = new Point(
+                        mousePoint.X - centerPoint.X, mousePoint.Y - centerPoint.Y);
+                    degrees = CalcDegrees(delta);
+
+                    // Calculate distance from the center to the new point 
+                    // as a fraction of the radius. Use your old friend, 
+                    // the Pythagorean theorem, to calculate this value.
+                    distance = Math.Sqrt(delta.X * delta.X + delta.Y * delta.Y) / radius;
+
+                    if (currentState == MouseState.DragInColor) {
+                        if (distance > 1) {
+                            // Mouse is down, and outside the circle, but you 
+                            // were previously dragging in the color circle. 
+                            // What to do?
+                            // In that case, move the point to the edge of the 
+                            // circle at the correct angle.
+                            distance = 1;
+                            newColorPoint = GetPoint(degrees, radius, centerPoint);
+                        }
+                    }
+
+                    // Calculate the new HSV and RGB values.
+                    HSV.Hue = (int)(degrees * 255 / 360);
+                    HSV.Saturation = (int)(distance * 255);
+                    HSV.value = brightness;
+                    RGB = ColorHandler.HSVtoRGB(HSV);
+                    fullColor = ColorHandler.HSVtoColor(HSV.Hue, HSV.Saturation, 255);
+                    break;
+            }
+            selectedColor = ColorHandler.HSVtoColor(HSV);
+
+            // Raise an event back to the parent form,
+            // so the form can update any UI it's using 
+            // to display selected color values.
+            OnColorChanged(RGB, HSV);
+
+            // On the way out, set the new state.
+            switch (currentState) {
+                case MouseState.ClickOnBrightness:
+                    currentState = MouseState.DragInBrightness;
+                    break;
+                case MouseState.ClickOnColor:
+                    currentState = MouseState.DragInColor;
+                    break;
+                case MouseState.ClickOutsideRegion:
+                    currentState = MouseState.DragOutsideRegion;
+                    break;
+            }
+
+            // Store away the current points for next time.
+            colorPoint = newColorPoint;
+            brightnessPoint = newBrightnessPoint;
+
+            // Draw the gradients and points. 
+            UpdateDisplay();
+        }
+
+        private Point CalcBrightnessPoint(int brightness) {
+            // Take the value for brightness (0 to 255), scale to the 
+            // scaling used in the brightness bar, then add the value 
+            // to the bottom of the bar. return the correct point at which 
+            // to display the brightness pointer.
+            return new Point(brightnessX, (int)(brightnessMax - brightness / brightnessScaling));
+        }
+
+        /*public void SetColor(Color c) {
+            fullColor = c;
+            UpdateDisplay();
+        }*/
+
+        private void UpdateDisplay() {
+            // Update the gradients, and place the pointers correctly based on colors and 
+            // brightness.
+
+            using (Brush selectedBrush = new SolidBrush(selectedColor)) {
+                // Draw the saved color wheel image.
+                g.DrawImage(colorImage, colorRectangle);
+
+                // Draw the "brightness" rectangle.
+                DrawLinearGradient(fullColor);
+                // Draw the two pointers.
+                DrawColorPointer(colorPoint);
+                DrawBrightnessPointer(brightnessPoint);
+            }
+        }
+
+        private void CalcCoordsAndUpdate(ColorHandler.HSV HSV) {
+            // Convert color to real-world coordinates and then calculate
+            // the various points. HSV.Hue represents the degrees (0 to 360), 
+            // HSV.Saturation represents the radius. 
+            // This procedure doesn't draw anything--it simply 
+            // updates class-level variables. The UpdateDisplay
+            // procedure uses these values to update the screen.
+
+            // Given the angle (HSV.Hue), and distance from 
+            // the center (HSV.Saturation), and the center, 
+            // calculate the point corresponding to 
+            // the selected color, on the color wheel.
+            colorPoint = GetPoint((double)HSV.Hue / 255 * 360,
+                (double)HSV.Saturation / 255 * radius,
+                centerPoint);
+
+            // Given the brightness (HSV.value), calculate the 
+            // point corresponding to the brightness indicator.
+            brightnessPoint = CalcBrightnessPoint(HSV.value);
+
+            // Store information about the selected color.
+            brightness = HSV.value;
+            selectedColor = ColorHandler.HSVtoColor(HSV);
+            RGB = ColorHandler.HSVtoRGB(HSV);
+
+            // The full color is the same as HSV, except that the 
+            // brightness is set to full (255). This is the top-most
+            // color in the brightness gradient.
+            fullColor = ColorHandler.HSVtoColor(HSV.Hue, HSV.Saturation, 255);
+        }
+
+        private void DrawLinearGradient(Color TopColor) {
+            // Given the top color, draw a linear gradient
+            // ranging from black to the top color. Use the 
+            // brightness rectangle as the area to fill.
+            using (LinearGradientBrush lgb =
+                             new LinearGradientBrush(brightnessRectangle, TopColor,
+                             Color.Black, LinearGradientMode.Vertical)) {
+                g.FillRectangle(lgb, brightnessRectangle);
+            }
+        }
+
+        private int CalcDegrees(Point pt) {
+            int degrees;
+
+            if (pt.X == 0) {
+                // The point is on the y-axis. Determine whether it's above or below the x-axis, and return the 
+                // corresponding angle. Note that the orientation of the y-coordinate is backwards. That is, 
+                // A positive Y value indicates a point BELOW the x-axis.
+                if (pt.Y > 0) {
+                    degrees = 270;
+                } else {
+                    degrees = 90;
+                }
+            } else {
+                // This value needs to be multiplied by -1 because the y-coordinate
+                // is opposite from the normal direction here.
+                // That is, a y-coordinate that's "higher" on the form has a lower y-value, in this coordinate
+                // system. So everything's off by a factor of -1 when performing the ratio calculations.
+                degrees = (int)(-Math.Atan((double)pt.Y / pt.X) * DEGREES_PER_RADIAN);
+
+                // If the x-coordinate of the selected point is to the left of the center of the circle, you 
+                // need to add 180 degrees to the angle. ArcTan only gives you a value on the right-hand side 
+                // of the circle.
+                if (pt.X < 0) {
+                    degrees += 180;
+                }
+
+                // Ensure that the return value is between 0 and 360.
+                degrees = (degrees + 360) % 360;
+            }
+            return degrees;
+        }
+
+        private void CreateGradient() {
+            // Create a new PathGradientBrush, supplying an array of points created by calling
+            // the GetPoints method.
+            using (PathGradientBrush pgb =
+                new PathGradientBrush(GetPoints(radius, new Point(radius, radius)))) {
+                // Set the various properties. Note the SurroundColors property, which contains an array of points, 
+                // in a one-to-one relationship with the points that created the gradient.
+                pgb.CenterColor = Color.White;
+                pgb.CenterPoint = new PointF(radius, radius);
+                pgb.SurroundColors = GetColors();
+
+                // Create a new bitmap containing the color wheel gradient, so the 
+                // code only needs to do all this work once. Later code uses the bitmap
+                // rather than recreating the gradient.
+                colorImage = new Bitmap(
+                    colorRectangle.Width, colorRectangle.Height,
+                    PixelFormat.Format32bppArgb);
+
+                using (Graphics newGraphics =
+                                 Graphics.FromImage(colorImage)) {
+                    newGraphics.FillEllipse(pgb, 0, 0,
+                        colorRectangle.Width, colorRectangle.Height);
+                }
+            }
+        }
+
+        private Color[] GetColors() {
+            // Create an array of COLOR_COUNT colors, looping through all the hues between 0 and 255, broken
+            // into COLOR_COUNT intervals. HSV is particularly well-suited for this, because the only value 
+            // that changes as you create colors is the Hue.
+            Color[] Colors = new Color[COLOR_COUNT];
+
+            for (int i = 0; i <= COLOR_COUNT - 1; i++)
+                Colors[i] = ColorHandler.HSVtoColor((int)((double)(i * 255) / COLOR_COUNT), 255, 255);
+            return Colors;
+        }
+
+        private Point[] GetPoints(double radius, Point centerPoint) {
+            // Generate the array of points that describe the locations of the COLOR_COUNT colors to be 
+            // displayed on the color wheel.
+            Point[] Points = new Point[COLOR_COUNT];
+
+            for (int i = 0; i <= COLOR_COUNT - 1; i++)
+                Points[i] = GetPoint((double)(i * 360) / COLOR_COUNT, radius, centerPoint);
+            return Points;
+        }
+
+        private Point GetPoint(double degrees, double radius, Point centerPoint) {
+            // Given the center of a circle and its radius, along
+            // with the angle corresponding to the point, find the coordinates. 
+            // In other words, conver  t from polar to rectangular coordinates.
+            double radians = degrees / DEGREES_PER_RADIAN;
+
+            return new Point((int)(centerPoint.X + Math.Floor(radius * Math.Cos(radians))),
+                (int)(centerPoint.Y - Math.Floor(radius * Math.Sin(radians))));
+        }
+
+        private void DrawColorPointer(Point pt) {
+            // Given a point, draw the color selector. The constant SIZE represents half
+            // the width -- the square will be twice this value in width and height.
+            const int SIZE = 3;
+            g.DrawRectangle(Pens.Black,
+                pt.X - SIZE, pt.Y - SIZE, SIZE * 2, SIZE * 2);
+        }
+
+        private void DrawBrightnessPointer(Point pt) {
+            // Draw a triangle for the brightness indicator that "points" at the provided point.
+            const int HEIGHT = 10;
+            const int WIDTH = 7;
+
+            Point[] Points = new Point[3];
+            Points[0] = pt;
+            Points[1] = new Point(pt.X + WIDTH, pt.Y + HEIGHT / 2);
+            Points[2] = new Point(pt.X + WIDTH, pt.Y - HEIGHT / 2);
+            g.FillPolygon(Brushes.Black, Points);
+        }
+    }
+}
diff --git a/Source/Core/General/General.cs b/Source/Core/General/General.cs
index f257fbb1f5a709ce5f7dec619811aebaa9d25d54..39e50b1e274eb03a09801b32a2480b4d8dfb1a4a 100644
--- a/Source/Core/General/General.cs
+++ b/Source/Core/General/General.cs
@@ -206,7 +206,7 @@ namespace CodeImp.DoomBuilder
 		internal static Dictionary<string, ScriptConfiguration> ScriptConfigs { get { return scriptconfigs; } }
 		public static MapManager Map { get { return map; } }
 		public static ActionManager Actions { get { return actions; } }
-		internal static PluginManager Plugins { get { return plugins; } }
+        internal static PluginManager Plugins { get { return plugins; } }
 		public static Clock Clock { get { return clock; } }
 		public static bool DebugBuild { get { return debugbuild; } }
 		internal static TypesManager Types { get { return types; } }
@@ -219,7 +219,7 @@ namespace CodeImp.DoomBuilder
 		public static bool NoSettings { get { return nosettings; } }
 		public static EditingManager Editing { get { return editing; } }
 		public static ErrorLogger ErrorLogger { get { return errorlogger; } }
-		
+
 		#endregion
 
 		#region ================== Configurations
@@ -1436,7 +1436,12 @@ namespace CodeImp.DoomBuilder
 		public static void Fail(string message)
 		{
 			General.WriteLogLine("FAIL: " + message);
+//mxd. Lets notify the user about our Epic Failure before crashing...
+#if DEBUG
 			Debug.Fail(message);
+#else
+            ShowErrorMessage(message, MessageBoxButtons.OK);
+#endif
 			Terminate(false);
 		}
 		
@@ -1527,6 +1532,14 @@ namespace CodeImp.DoomBuilder
 		{
 			return Math.Min(Math.Max(min, value), max);
 		}
+
+        //mxd. This clamps angle between 0 and 359
+        public static int ClampAngle(int angle) {
+            if (angle > -1 && angle < 360) return angle;
+            int n = angle / 360;
+            if (angle > 0) return angle - n * 360;
+            return 360 - Math.Abs(angle) + Math.Abs(n) * 360;
+        }
 		
 		// This returns an element from a collection by index
 		public static T GetByIndex<T>(ICollection<T> collection, int index)
diff --git a/Source/Core/Plugins/Plug.cs b/Source/Core/Plugins/Plug.cs
index 1a8b77fbec42bbca905743ccc653c1ee72b7ab92..56127b7f4416a3b2822cc07e5105fff3f9d4ad50 100644
--- a/Source/Core/Plugins/Plug.cs
+++ b/Source/Core/Plugins/Plug.cs
@@ -1,6 +1,7 @@
 #region ================== Namespaces
 
 using System;
+using System.Drawing;
 using System.Collections;
 using System.Collections.Generic;
 using System.Globalization;
@@ -37,6 +38,18 @@ namespace CodeImp.DoomBuilder.Plugins
 		// Disposing
 		private bool isdisposed = false;
 
+        //mxd. It's nice to have these avaliable to plugins...
+        protected static Point DisplayLocationAbs {
+            get {
+                if (General.MainWindow == null || General.MainWindow.Display == null)
+                    return new Point();
+                return new Point(General.MainWindow.Location.X + General.MainWindow.ClientRectangle.X + General.MainWindow.Display.Location.X, General.MainWindow.Location.Y + General.MainWindow.ClientRectangle.Y + General.MainWindow.Display.Location.Y);
+            }
+        }
+
+        //mxd. It's nice to have these avaliable to plugins...
+        protected static Size DisplaySize { get { return (General.MainWindow == null || General.MainWindow.Display == null) ? new Size() : General.MainWindow.Display.Size; } }
+
 		#endregion
 		
 		#region ================== Properties
@@ -115,6 +128,15 @@ namespace CodeImp.DoomBuilder.Plugins
 			return plugin.GetResourceStream(resourcename);
 		}
 
+        //mxd. It's nice to have these avaliable to plugins...
+        public static bool DisplayStatus(StatusType type, string message) {
+            if (General.MainWindow != null) {
+                General.MainWindow.DisplayStatus(type, message);
+                return true;
+            }
+            return false;
+        }
+
 		#endregion
 
 		#region ================== Events
diff --git a/Source/Core/Rendering/PixelColor.cs b/Source/Core/Rendering/PixelColor.cs
index 5d94892bb0d2ea5223ecb1119400826674c1ca87..17de0701cb163d7c0fe081c48c6024d8ff793645 100644
--- a/Source/Core/Rendering/PixelColor.cs
+++ b/Source/Core/Rendering/PixelColor.cs
@@ -119,7 +119,9 @@ namespace CodeImp.DoomBuilder.Rendering
 		// To ColorRef (alpha-less)
 		public int ToColorRef()
 		{
-			return ((int)r + ((int)b << 16) + ((int)g << 8));
+			//mxd
+            //return ((int)r + ((int)b << 16) + ((int)g << 8));
+            return (((int)r << 16) + ((int)g << 8) + (int)b);
 		}
 		
 		// To ColorValue
diff --git a/Source/Core/Rendering/Renderer2D.cs b/Source/Core/Rendering/Renderer2D.cs
index dc8a37c02b5fc135d707b51168ba2d2f969d7f7a..5893fd50ed678e819abf77c4b2d1ecaefb0ad0b3 100644
--- a/Source/Core/Rendering/Renderer2D.cs
+++ b/Source/Core/Rendering/Renderer2D.cs
@@ -1065,6 +1065,7 @@ namespace CodeImp.DoomBuilder.Rendering
 				int locksize = (things.Count > THING_BUFFER_SIZE) ? THING_BUFFER_SIZE : things.Count;
 				FlatVertex[] verts = new FlatVertex[THING_BUFFER_SIZE * 12];
 
+                //mxd
                 thingsWithModel = new Dictionary<Vector2D, Thing>();
 
 				// Go for all things
@@ -1113,7 +1114,6 @@ namespace CodeImp.DoomBuilder.Rendering
                 //mxd. Render models
                 if (thingsWithModel.Count > 0) {
                     // Set renderstates for rendering
-                    //graphics.Device.SetRenderState(RenderState.ZEnable, false);
                     graphics.Device.SetRenderState(RenderState.AlphaBlendEnable, false);
                     graphics.Device.SetRenderState(RenderState.TextureFactor, -1);
 
diff --git a/Source/Core/Rendering/Renderer3D.cs b/Source/Core/Rendering/Renderer3D.cs
index 57f0cf82b7abc8c05e2244c22082662d7393391d..3243c142e290fcbf05ce618ac9269405f6dc6835 100644
--- a/Source/Core/Rendering/Renderer3D.cs
+++ b/Source/Core/Rendering/Renderer3D.cs
@@ -742,9 +742,11 @@ namespace CodeImp.DoomBuilder.Rendering
 						
                         //mxd. Seems that translucent lines aren't affected by dynamic lights in GZDoom
                         if (g.RenderPass != RenderPass.Alpha && General.Settings.GZDrawLights && !fullbrightness && thingsWithLight.Count > 0) {
-                            if (!litGeometry.ContainsKey(curtexture.Texture))
-                                litGeometry[curtexture.Texture] = new List<VisualGeometry>();
-                            litGeometry[curtexture.Texture].Add(g);
+                            if (curtexture.Texture != null) {
+                                if (!litGeometry.ContainsKey(curtexture.Texture))
+                                    litGeometry[curtexture.Texture] = new List<VisualGeometry>();
+                                litGeometry[curtexture.Texture].Add(g);
+                            }
                         }
 
 						// Switch shader pass?
@@ -1103,7 +1105,7 @@ namespace CodeImp.DoomBuilder.Rendering
                     t.CalculateCameraDistance3D(D3DDevice.V3(cameraposition));
                     //t.CameraDistance3D is actually squared distance, hence (t.LightRadius * t.LightRadius)
                     if (t.CameraDistance3D < (t.LightRadius * t.LightRadius) || isThingOnScreen(t.BoundingBox)) { //always render light if camera is within it's radius 
-                        if (t.LightType == (int)GZDoomLightType.FLICKER || t.LightType == (int)GZDoomLightType.PULSE || t.LightType == (int)GZDoomLightType.RANDOM)
+                        if (Array.IndexOf(GZBuilder.GZGeneral.GZ_ANIMATED_LIGHT_TYPES, t.LightType) != -1)
                             t.UpdateBoundingBox(t.LightRadius, t.LightRadius * 2);
                         thingsWithLight.Add(t);
                     }
diff --git a/Source/Core/Resources/Actions.cfg b/Source/Core/Resources/Actions.cfg
index bc40d5609892ba1fe3670bb696b89179b073ffc5..c34c909a3825257a9cc0ffb6dbc589fef72964e6 100644
--- a/Source/Core/Resources/Actions.cfg
+++ b/Source/Core/Resources/Actions.cfg
@@ -878,17 +878,6 @@ gzdrawselectedmodelsonly
 	allowscroll = false;
 }
 
-//panels
-gztogglelightpannel
-{
-    title = "Toggle dynamic light pannel";
-	category = "gzdoombuilder";
-	description = "Select dynamic light thing(s), then use this pannel to set light properties quickly.";
-	allowkeys = true;
-	allowmouse = true;
-	allowscroll = false;
-}
-
 gztogglefogpannel
 {
     title = "Toggle fog pannel";
diff --git a/Source/Core/Resources/Splash3_trans.png b/Source/Core/Resources/Splash3_trans.png
index e57db6f847aa9f9e73ae427c117db05576c58aea..9b9ebe242796bb39254bb87aec2ca3d33df22197 100644
Binary files a/Source/Core/Resources/Splash3_trans.png and b/Source/Core/Resources/Splash3_trans.png differ
diff --git a/Source/Core/VisualModes/VisualCamera.cs b/Source/Core/VisualModes/VisualCamera.cs
index 41c4537016b33cf5d780d50873a2486e88f8cddf..11e2505760149b8b7ca8715d6b7f64c6e1ca6dc3 100644
--- a/Source/Core/VisualModes/VisualCamera.cs
+++ b/Source/Core/VisualModes/VisualCamera.cs
@@ -55,7 +55,7 @@ namespace CodeImp.DoomBuilder.VisualModes
 		{
 			// Initialize
 			this.movemultiplier = new Vector3D(1.0f, 1.0f, 1.0f);
-			this.position = position;
+			//this.position = position;
 			this.anglexy = 0.0f;
 			this.anglez = Angle2D.PI;
 			this.sector = null;
diff --git a/Source/Core/VisualModes/VisualGeometry.cs b/Source/Core/VisualModes/VisualGeometry.cs
index cdb24f1790c3a170fc1968a219f2393ec3229a0b..ba57592ceb8f662f4c4ca0550df18f5e712e3b11 100644
--- a/Source/Core/VisualModes/VisualGeometry.cs
+++ b/Source/Core/VisualModes/VisualGeometry.cs
@@ -99,7 +99,6 @@ namespace CodeImp.DoomBuilder.VisualModes
 
         //mxd
         internal Vector3[] BoundingBox { get { return boundingBox; } }
-        //internal Vector3D Normal { get { return normal; } }
 
 		/// <summary>
 		/// Render pass in which this geometry must be rendered. Default is Solid.
@@ -175,48 +174,51 @@ namespace CodeImp.DoomBuilder.VisualModes
 
         //mxd. Taken from OpenGl wiki 
         protected void CalculateNormalsAndShading() {
-            int startIndex;
-            Vector3 U, V;
-
-            BoundingBoxSizes bbs = new BoundingBoxSizes(vertices[0]);
-
-            for (int i = 0; i < triangles; i++) {
-                startIndex = i * 3;
-                WorldVertex p1 = vertices[startIndex];
-                WorldVertex p2 = vertices[startIndex + 1];
-                WorldVertex p3 = vertices[startIndex + 2];
-
-                U = new Vector3(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
-                V = new Vector3(p3.x - p1.x, p3.y - p1.y, p3.z - p1.z);
-
-                p1.nx = p2.nx = p3.nx = -(U.Y * V.Z - U.Z * V.Y);
-                p1.ny = p2.ny = p3.ny = -(U.Z * V.X - U.X * V.Z);
-                p1.nz = p2.nz = p3.nz = -(U.X * V.Y - U.Y * V.X);
-
-                //doom-style walls shading
-                //not very apropriate place to put this, but most convinient :)
-                if (sidedef != null) {
-                    byte valMod = (byte)(Math.Abs((float)Math.Sin(sidedef.Angle)) * 0.07f * 255);
-                    PixelColor modColor = new PixelColor(255, valMod, valMod, valMod);
-                    PixelColor pc = PixelColor.FromInt(p1.c);
-
-                    if (pc.r < modColor.r) modColor.r = pc.r;
-                    if (pc.g < modColor.g) modColor.g = pc.g;
-                    if (pc.b < modColor.b) modColor.b = pc.b;
-
-                    p1.c = p2.c = p3.c -= modColor.ToColorRef();
+            if (vertices.Length > 0) {
+                int startIndex;
+                Vector3 U, V;
+
+                BoundingBoxSizes bbs = new BoundingBoxSizes(vertices[0]);
+
+                for (int i = 0; i < triangles; i++) {
+                    startIndex = i * 3;
+                    WorldVertex p1 = vertices[startIndex];
+                    WorldVertex p2 = vertices[startIndex + 1];
+                    WorldVertex p3 = vertices[startIndex + 2];
+
+                    U = new Vector3(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
+                    V = new Vector3(p3.x - p1.x, p3.y - p1.y, p3.z - p1.z);
+
+                    p1.nx = p2.nx = p3.nx = -(U.Y * V.Z - U.Z * V.Y);
+                    p1.ny = p2.ny = p3.ny = -(U.Z * V.X - U.X * V.Z);
+                    p1.nz = p2.nz = p3.nz = -(U.X * V.Y - U.Y * V.X);
+
+                    //doom-style walls shading
+                    //not very apropriate place to put this, but most convinient :)
+                    if (sidedef != null) {
+                        float valMod = 1.0f - Math.Abs((float)Math.Sin(sidedef.Angle)) * 0.07f; //0.07
+                        PixelColor pc = PixelColor.FromInt(p1.c);
+
+                        pc.r = (byte)((float)pc.r * valMod);
+                        pc.g = (byte)((float)pc.g * valMod);
+                        pc.b = (byte)((float)pc.b * valMod);
+
+                        int colorRef = pc.ToColorRef();
+                        p1.c = colorRef;
+                        p2.c = colorRef;
+                        p3.c = colorRef;
+                    }
+                    vertices[startIndex] = p1;
+                    vertices[startIndex + 1] = p2;
+                    vertices[startIndex + 2] = p3;
+
+                    BoundingBoxTools.UpdateBoundingBoxSizes(ref bbs, p1);
+                    BoundingBoxTools.UpdateBoundingBoxSizes(ref bbs, p2);
+                    BoundingBoxTools.UpdateBoundingBoxSizes(ref bbs, p3);
                 }
 
-                vertices[startIndex] = p1;
-                vertices[startIndex + 1] = p2;
-                vertices[startIndex + 2] = p3;
-
-                BoundingBoxTools.UpdateBoundingBoxSizes(ref bbs, p1);
-                BoundingBoxTools.UpdateBoundingBoxSizes(ref bbs, p2);
-                BoundingBoxTools.UpdateBoundingBoxSizes(ref bbs, p3);
+                boundingBox = BoundingBoxTools.CalculateBoundingPlane(bbs);
             }
-            if (triangles > 0)
-                boundingBox = BoundingBoxTools.CalculateBoundingPlane(bbs);    
         }
 		
 		// This compares for sorting by sector
diff --git a/Source/Core/VisualModes/VisualMode.cs b/Source/Core/VisualModes/VisualMode.cs
index 7f6e858a5a56a2da57f76bda557ac03f9520d204..29f6b29c45f6e95e272c572fe9fbbfe22ddc12fa 100644
--- a/Source/Core/VisualModes/VisualMode.cs
+++ b/Source/Core/VisualModes/VisualMode.cs
@@ -70,6 +70,10 @@ namespace CodeImp.DoomBuilder.VisualModes
         private bool keyup;
         private bool keydown;
 
+        //mxd
+        private bool visibleThingsUpdated;
+        private List<VisualThing> selectedThings;
+
 		// Map
 		protected VisualBlockMap blockmap;
 		protected Dictionary<Thing, VisualThing> allthings;
@@ -78,6 +82,21 @@ namespace CodeImp.DoomBuilder.VisualModes
 		protected List<VisualThing> visiblethings;
 		protected Dictionary<Sector, VisualSector> visiblesectors;
 		protected List<VisualGeometry> visiblegeometry;
+
+        //mxd
+        public List<VisualThing> SelectedVisualThings { 
+            get {
+                if (visibleThingsUpdated) {
+                    visibleThingsUpdated = false;
+                    selectedThings = new List<VisualThing>();
+                    foreach (VisualThing t in visiblethings) {
+                        if (t.Selected)
+                            selectedThings.Add(t);
+                    }
+                }
+                return selectedThings;
+            } 
+        }
 		
 		#endregion
 
@@ -318,6 +337,9 @@ namespace CodeImp.DoomBuilder.VisualModes
 			visiblegeometry = new List<VisualGeometry>(visiblegeometry.Capacity);
 			visiblethings = new List<VisualThing>(visiblethings.Capacity);
 
+            //mxd
+            visibleThingsUpdated = true;
+
 			// Get the blocks within view range
 			visibleblocks = blockmap.GetFrustumRange(renderer.Frustum2D);
 			
diff --git a/Source/Core/VisualModes/VisualSector.cs b/Source/Core/VisualModes/VisualSector.cs
index 9cc152ec22018e2eaaebe96181453f8c82cf515a..ddfdf56691a5833174386de3b6d49446043708d4 100644
--- a/Source/Core/VisualModes/VisualSector.cs
+++ b/Source/Core/VisualModes/VisualSector.cs
@@ -129,6 +129,9 @@ namespace CodeImp.DoomBuilder.VisualModes
 			// Make new geometry
 			//Update();
 		}
+
+        //mxd
+        public virtual void UpdateSectorData() { }
 		
 		// This updates the visual sector
 		public void Update()
diff --git a/Source/Core/VisualModes/VisualThing.cs b/Source/Core/VisualModes/VisualThing.cs
index 66af9e76282bfb45e00607182d3d0c59840937da..09d6ee42602ce03859ee31d562cdfd11663ee361 100644
--- a/Source/Core/VisualModes/VisualThing.cs
+++ b/Source/Core/VisualModes/VisualThing.cs
@@ -88,8 +88,8 @@ namespace CodeImp.DoomBuilder.VisualModes
         private int lightRenderStyle;
         private Color4 lightColor;
         private float lightRadius; //current radius. used in light animation
-        private float lightRadiusMin;
-        private float lightRadiusMax;
+        private float lightPrimaryRadius;
+        private float lightSecondaryRadius;
         private Vector3 position_v3;
         private float lightDelta; //used in light animation
         private Vector3[] boundingBox;
@@ -172,8 +172,8 @@ namespace CodeImp.DoomBuilder.VisualModes
             //mxd
             lightType = -1;
             lightRenderStyle = -1;
-            lightRadiusMin = -1;
-            lightRadiusMax = -1;
+            lightPrimaryRadius = -1;
+            lightSecondaryRadius = -1;
             lightColor = new Color4();
             boundingBox = new Vector3[9];
 			
@@ -340,8 +340,8 @@ namespace CodeImp.DoomBuilder.VisualModes
                     }
                     lightType = -1;
                     lightRadius = -1;
-                    lightRadiusMin = -1;
-                    lightRadiusMax = -1;
+                    lightPrimaryRadius = -1;
+                    lightSecondaryRadius = -1;
                     lightRenderStyle = -1;
                 }
 
@@ -350,6 +350,17 @@ namespace CodeImp.DoomBuilder.VisualModes
 			}
 		}
 
+        //used in ColorPicker to update light 
+        public void UpdateLight() {
+            int light_id = Array.IndexOf(GZBuilder.GZGeneral.GZ_LIGHTS, thing.Type);
+            if (light_id != -1) {
+                updateLight(light_id);
+
+                //if (Array.IndexOf(GZBuilder.GZGeneral.GZ_ANIMATED_LIGHT_TYPES, lightType) != -1)
+                UpdateBoundingBox(lightRadius, lightRadius * 2);
+            }
+        }
+
         //mxd update light info
         private void updateLight(int light_id) {
             float scaled_intensity = 255.0f / General.Settings.GZDynamicLightIntensity;
@@ -376,18 +387,11 @@ namespace CodeImp.DoomBuilder.VisualModes
                     int scaler = 1;
                     if (thing.Sector != null)
                         scaler = thing.Sector.Brightness / 4;
-                    lightRadiusMin = (float)(thing.Args[3] * scaler) * General.Settings.GZDynamicLightRadius;
+                    lightPrimaryRadius = (float)(thing.Args[3] * scaler) * General.Settings.GZDynamicLightRadius;
                 } else {
-                    lightRadiusMin = (float)(thing.Args[3] * 2) * General.Settings.GZDynamicLightRadius; //works... that.. way in GZDoom
-                    if (lightType > 0) {
-                        lightRadiusMax = (float)(thing.Args[4] * 2) * General.Settings.GZDynamicLightRadius;
-
-                        if (lightRadiusMin > lightRadiusMax) { //swap them
-                            float lrm = lightRadiusMin;
-                            lightRadiusMin = lightRadiusMax;
-                            lightRadiusMax = lrm;
-                        }
-                    }
+                    lightPrimaryRadius = (float)(thing.Args[3] * 2) * General.Settings.GZDynamicLightRadius; //works... that.. way in GZDoom
+                    if (lightType > 0)
+                        lightSecondaryRadius = (float)(thing.Args[4] * 2) * General.Settings.GZDynamicLightRadius;
                 }
             } else { //it's one of vavoom lights
                 lightRenderStyle = (int)GZDoomLightRenderStyle.VAVOOM;
@@ -396,7 +400,7 @@ namespace CodeImp.DoomBuilder.VisualModes
                     lightColor = new Color4((float)lightRenderStyle / 100.0f, (float)thing.Args[1] / scaled_intensity, (float)thing.Args[2] / scaled_intensity, (float)thing.Args[3] / scaled_intensity);
                 else
                     lightColor = new Color4((float)lightRenderStyle / 100.0f, General.Settings.GZDynamicLightIntensity, General.Settings.GZDynamicLightIntensity, General.Settings.GZDynamicLightIntensity);
-                lightRadiusMin = (float)(thing.Args[0] * 8) * General.Settings.GZDynamicLightRadius;
+                lightPrimaryRadius = (float)(thing.Args[0] * 8) * General.Settings.GZDynamicLightRadius;
             }
             UpdateLightRadius();
         }
@@ -408,39 +412,45 @@ namespace CodeImp.DoomBuilder.VisualModes
                 return;
             }
 
-            if (!General.Settings.GZAnimateLights || lightType == (int)GZDoomLightType.NORMAL
-                                                  || lightType == (int)GZDoomLightType.SECTOR
-                                                  || lightType == (int)GZDoomLightType.VAVOOM
-                                                  || lightType == (int)GZDoomLightType.VAVOOM_COLORED) {
-                lightRadius = lightRadiusMin;
+            if (!General.Settings.GZAnimateLights || Array.IndexOf(GZBuilder.GZGeneral.GZ_ANIMATED_LIGHT_TYPES, lightType) == -1) {
+                lightRadius = lightPrimaryRadius;
                 return;
             }
 
             double time = General.Clock.GetCurrentTime();
-            float diff = lightRadiusMax - lightRadiusMin;
+            
+            float rMin, rMax;
+            if (lightPrimaryRadius > lightSecondaryRadius) {
+                rMax = lightPrimaryRadius;
+                rMin = lightSecondaryRadius;
+            } else {
+                rMin = lightPrimaryRadius;
+                rMax = lightSecondaryRadius;
+            }
+
+            float diff = rMax - rMin;
 
             //pulse
             if (lightType == (int)GZDoomLightType.PULSE) {
-                lightDelta = (float)Math.Sin(time / (100.0f * thing.Angle * 2.3f)); //just playing by the eye here...
-                lightRadius = Math.Abs((int)(lightRadiusMin + diff/2 + diff/2 * lightDelta));
-
+                lightDelta = ((float)Math.Sin(time / (thing.AngleDoom * 4.0f)) + 1.0f) / 2.0f; //just playing by the eye here... in [0.0 ... 1.0] interval
+                lightRadius = rMin + diff * lightDelta;
             //flicker
             } else if (lightType == (int)GZDoomLightType.FLICKER) {
-                float delta = (float)Math.Sin(time / (100.0f * thing.Angle * 0.02f)); //just playing by the eye here...
+                //float delta = (float)Math.Sin(time / thing.AngleDoom);
+                float delta = (float)Math.Sin(time / 0.1f); //just playing by the eye here...
                 if (Math.Sign(delta) != Math.Sign(lightDelta)) {
                     lightDelta = delta;
-                    int angle = (int)(thing.Angle * 180 / Math.PI);
-                    if (new Random().Next(0, 360) > angle) {
-                        lightRadius = lightRadiusMax;
-                    } else {
-                        lightRadius = lightRadiusMin;
-                    }
+                    if (new Random().Next(0, 359) < thing.AngleDoom) 
+                        lightRadius = rMax;
+                    else
+                        lightRadius = rMin;
                 }
             //random
             } else if (lightType == (int)GZDoomLightType.RANDOM) {
-                float delta = (float)Math.Sin(time / (100.0f * thing.Angle * 4.6f)); //just playing by the eye here...
+                //float delta = (float)Math.Sin(time / (thing.AngleDoom));
+                float delta = (float)Math.Sin(time / (thing.AngleDoom * 9.0f)); //just playing by the eye here...
                 if (Math.Sign(delta) != Math.Sign(lightDelta))
-                    lightRadius = lightRadiusMin + (float)(new Random().Next(0, (int)(diff * 10))) / 10.0f;
+                    lightRadius = rMin + (float)(new Random().Next(0, (int)(diff * 10))) / 10.0f;
                 lightDelta = delta;
             }
         }
diff --git a/Source/Core/Windows/MainForm.Designer.cs b/Source/Core/Windows/MainForm.Designer.cs
index 0c383a9d875d0b6cf198aa1f7d0aa442561e5902..2ed50e98dd95917ef67e1cf344346c9ea4fe7cb7 100644
--- a/Source/Core/Windows/MainForm.Designer.cs
+++ b/Source/Core/Windows/MainForm.Designer.cs
@@ -48,23 +48,49 @@ namespace CodeImp.DoomBuilder.Windows
             this.poscommalabel = new System.Windows.Forms.ToolStripStatusLabel();
             this.menumain = new System.Windows.Forms.MenuStrip();
             this.menufile = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemnewmap = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemopenmap = new System.Windows.Forms.ToolStripMenuItem();
             this.itemclosemap = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemsavemap = new System.Windows.Forms.ToolStripMenuItem();
             this.itemsavemapas = new System.Windows.Forms.ToolStripMenuItem();
             this.itemsavemapinto = new System.Windows.Forms.ToolStripMenuItem();
             this.seperatorfilesave = new System.Windows.Forms.ToolStripSeparator();
             this.itemnorecent = new System.Windows.Forms.ToolStripMenuItem();
             this.itemexit = new System.Windows.Forms.ToolStripMenuItem();
             this.menuedit = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemundo = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemredo = new System.Windows.Forms.ToolStripMenuItem();
             this.seperatoreditundo = new System.Windows.Forms.ToolStripSeparator();
+            this.itemcut = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemcopy = new System.Windows.Forms.ToolStripMenuItem();
+            this.itempaste = new System.Windows.Forms.ToolStripMenuItem();
+            this.itempastespecial = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemsnaptogrid = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemautomerge = new System.Windows.Forms.ToolStripMenuItem();
             this.seperatoreditgeometry = new System.Windows.Forms.ToolStripSeparator();
             this.itemgridinc = new System.Windows.Forms.ToolStripMenuItem();
             this.itemgriddec = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemgridsetup = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemmapoptions = new System.Windows.Forms.ToolStripMenuItem();
             this.menuview = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemthingsfilter = new System.Windows.Forms.ToolStripMenuItem();
             this.seperatorviewthings = new System.Windows.Forms.ToolStripSeparator();
+            this.itemviewnormal = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemviewbrightness = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemviewfloors = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemviewceilings = new System.Windows.Forms.ToolStripMenuItem();
             this.seperatorviewviews = new System.Windows.Forms.ToolStripSeparator();
+            this.menuzoom = new System.Windows.Forms.ToolStripMenuItem();
+            this.item2zoom200 = new System.Windows.Forms.ToolStripMenuItem();
+            this.item2zoom100 = new System.Windows.Forms.ToolStripMenuItem();
+            this.item2zoom50 = new System.Windows.Forms.ToolStripMenuItem();
+            this.item2zoom25 = new System.Windows.Forms.ToolStripMenuItem();
+            this.item2zoom10 = new System.Windows.Forms.ToolStripMenuItem();
+            this.item2zoom5 = new System.Windows.Forms.ToolStripMenuItem();
             this.itemfittoscreen = new System.Windows.Forms.ToolStripMenuItem();
             this.itemtoggleinfo = new System.Windows.Forms.ToolStripMenuItem();
             this.seperatorviewzoom = new System.Windows.Forms.ToolStripSeparator();
+            this.itemscripteditor = new System.Windows.Forms.ToolStripMenuItem();
             this.menumode = new System.Windows.Forms.ToolStripMenuItem();
             this.menuprefabs = new System.Windows.Forms.ToolStripMenuItem();
             this.iteminsertprefabfile = new System.Windows.Forms.ToolStripMenuItem();
@@ -73,23 +99,70 @@ namespace CodeImp.DoomBuilder.Windows
             this.itemcreateprefab = new System.Windows.Forms.ToolStripMenuItem();
             this.menutools = new System.Windows.Forms.ToolStripMenuItem();
             this.itemreloadresources = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemshowerrors = new System.Windows.Forms.ToolStripMenuItem();
             this.seperatortoolsresources = new System.Windows.Forms.ToolStripSeparator();
             this.configurationToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.preferencesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.seperatortoolsconfig = new System.Windows.Forms.ToolStripSeparator();
+            this.itemtestmap = new System.Windows.Forms.ToolStripMenuItem();
             this.menuhelp = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemhelprefmanual = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemhelpeditmode = new System.Windows.Forms.ToolStripMenuItem();
             this.seperatorhelpmanual = new System.Windows.Forms.ToolStripSeparator();
             this.itemhelpabout = new System.Windows.Forms.ToolStripMenuItem();
             this.toolbar = new System.Windows.Forms.ToolStrip();
+            this.buttonnewmap = new System.Windows.Forms.ToolStripButton();
+            this.buttonopenmap = new System.Windows.Forms.ToolStripButton();
+            this.buttonsavemap = new System.Windows.Forms.ToolStripButton();
+            this.buttonscripteditor = new System.Windows.Forms.ToolStripButton();
+            this.buttonundo = new System.Windows.Forms.ToolStripButton();
+            this.buttonredo = new System.Windows.Forms.ToolStripButton();
+            this.buttoncut = new System.Windows.Forms.ToolStripButton();
+            this.buttoncopy = new System.Windows.Forms.ToolStripButton();
+            this.buttonpaste = new System.Windows.Forms.ToolStripButton();
+            this.buttoninsertprefabfile = new System.Windows.Forms.ToolStripButton();
+            this.buttoninsertpreviousprefab = new System.Windows.Forms.ToolStripButton();
+            this.buttonthingsfilter = new System.Windows.Forms.ToolStripButton();
             this.thingfilters = new System.Windows.Forms.ToolStripComboBox();
+            this.buttonviewnormal = new System.Windows.Forms.ToolStripButton();
+            this.buttonviewbrightness = new System.Windows.Forms.ToolStripButton();
+            this.buttonviewfloors = new System.Windows.Forms.ToolStripButton();
+            this.buttonviewceilings = new System.Windows.Forms.ToolStripButton();
             this.seperatorviews = new System.Windows.Forms.ToolStripSeparator();
+            this.buttonsnaptogrid = new System.Windows.Forms.ToolStripButton();
+            this.buttonautomerge = new System.Windows.Forms.ToolStripButton();
             this.separatorgzmodes = new System.Windows.Forms.ToolStripSeparator();
+            this.buttontoggledynlight = new System.Windows.Forms.ToolStripButton();
+            this.buttontoggleanimatedlight = new System.Windows.Forms.ToolStripButton();
+            this.buttontogglemodels = new System.Windows.Forms.ToolStripButton();
+            this.buttonselectedmodelsonly = new System.Windows.Forms.ToolStripButton();
             this.seperatorgeometry = new System.Windows.Forms.ToolStripSeparator();
+            this.buttontest = new System.Windows.Forms.ToolStripSplitButton();
             this.seperatortesting = new System.Windows.Forms.ToolStripSeparator();
             this.statusbar = new System.Windows.Forms.StatusStrip();
+            this.statuslabel = new System.Windows.Forms.ToolStripStatusLabel();
             this.configlabel = new System.Windows.Forms.ToolStripStatusLabel();
             this.gridlabel = new System.Windows.Forms.ToolStripStatusLabel();
+            this.buttongrid = new System.Windows.Forms.ToolStripDropDownButton();
+            this.itemgrid1024 = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemgrid512 = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemgrid256 = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemgrid128 = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemgrid64 = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemgrid32 = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemgrid16 = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemgrid8 = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemgrid4 = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemgridcustom = new System.Windows.Forms.ToolStripMenuItem();
             this.zoomlabel = new System.Windows.Forms.ToolStripStatusLabel();
+            this.buttonzoom = new System.Windows.Forms.ToolStripDropDownButton();
+            this.itemzoom200 = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemzoom100 = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemzoom50 = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemzoom25 = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemzoom10 = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemzoom5 = new System.Windows.Forms.ToolStripMenuItem();
+            this.itemzoomfittoscreen = new System.Windows.Forms.ToolStripMenuItem();
             this.xposlabel = new System.Windows.Forms.ToolStripStatusLabel();
             this.yposlabel = new System.Windows.Forms.ToolStripStatusLabel();
             this.panelinfo = new System.Windows.Forms.Panel();
@@ -109,79 +182,6 @@ namespace CodeImp.DoomBuilder.Windows
             this.dockersspace = new System.Windows.Forms.Panel();
             this.dockerspanel = new CodeImp.DoomBuilder.Controls.DockersControl();
             this.dockerscollapser = new System.Windows.Forms.Timer(this.components);
-            this.statuslabel = new System.Windows.Forms.ToolStripStatusLabel();
-            this.buttongrid = new System.Windows.Forms.ToolStripDropDownButton();
-            this.itemgrid1024 = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemgrid512 = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemgrid256 = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemgrid128 = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemgrid64 = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemgrid32 = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemgrid16 = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemgrid8 = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemgrid4 = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemgridcustom = new System.Windows.Forms.ToolStripMenuItem();
-            this.buttonzoom = new System.Windows.Forms.ToolStripDropDownButton();
-            this.itemzoom200 = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemzoom100 = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemzoom50 = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemzoom25 = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemzoom10 = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemzoom5 = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemzoomfittoscreen = new System.Windows.Forms.ToolStripMenuItem();
-            this.buttonnewmap = new System.Windows.Forms.ToolStripButton();
-            this.buttonopenmap = new System.Windows.Forms.ToolStripButton();
-            this.buttonsavemap = new System.Windows.Forms.ToolStripButton();
-            this.buttonscripteditor = new System.Windows.Forms.ToolStripButton();
-            this.buttonundo = new System.Windows.Forms.ToolStripButton();
-            this.buttonredo = new System.Windows.Forms.ToolStripButton();
-            this.buttoncut = new System.Windows.Forms.ToolStripButton();
-            this.buttoncopy = new System.Windows.Forms.ToolStripButton();
-            this.buttonpaste = new System.Windows.Forms.ToolStripButton();
-            this.buttoninsertprefabfile = new System.Windows.Forms.ToolStripButton();
-            this.buttoninsertpreviousprefab = new System.Windows.Forms.ToolStripButton();
-            this.buttonthingsfilter = new System.Windows.Forms.ToolStripButton();
-            this.buttonviewnormal = new System.Windows.Forms.ToolStripButton();
-            this.buttonviewbrightness = new System.Windows.Forms.ToolStripButton();
-            this.buttonviewfloors = new System.Windows.Forms.ToolStripButton();
-            this.buttonviewceilings = new System.Windows.Forms.ToolStripButton();
-            this.buttonsnaptogrid = new System.Windows.Forms.ToolStripButton();
-            this.buttonautomerge = new System.Windows.Forms.ToolStripButton();
-            this.buttontoggledynlight = new System.Windows.Forms.ToolStripButton();
-            this.buttontoggleanimatedlight = new System.Windows.Forms.ToolStripButton();
-            this.buttontogglemodels = new System.Windows.Forms.ToolStripButton();
-            this.buttonselectedmodelsonly = new System.Windows.Forms.ToolStripButton();
-            this.buttontest = new System.Windows.Forms.ToolStripSplitButton();
-            this.itemnewmap = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemopenmap = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemsavemap = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemundo = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemredo = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemcut = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemcopy = new System.Windows.Forms.ToolStripMenuItem();
-            this.itempaste = new System.Windows.Forms.ToolStripMenuItem();
-            this.itempastespecial = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemsnaptogrid = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemautomerge = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemgridsetup = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemmapoptions = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemthingsfilter = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemviewnormal = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemviewbrightness = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemviewfloors = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemviewceilings = new System.Windows.Forms.ToolStripMenuItem();
-            this.menuzoom = new System.Windows.Forms.ToolStripMenuItem();
-            this.item2zoom200 = new System.Windows.Forms.ToolStripMenuItem();
-            this.item2zoom100 = new System.Windows.Forms.ToolStripMenuItem();
-            this.item2zoom50 = new System.Windows.Forms.ToolStripMenuItem();
-            this.item2zoom25 = new System.Windows.Forms.ToolStripMenuItem();
-            this.item2zoom10 = new System.Windows.Forms.ToolStripMenuItem();
-            this.item2zoom5 = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemscripteditor = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemshowerrors = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemtestmap = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemhelprefmanual = new System.Windows.Forms.ToolStripMenuItem();
-            this.itemhelpeditmode = new System.Windows.Forms.ToolStripMenuItem();
             toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
             toolStripSeparator9 = new System.Windows.Forms.ToolStripSeparator();
             toolStripSeparator12 = new System.Windows.Forms.ToolStripSeparator();
@@ -211,6 +211,16 @@ namespace CodeImp.DoomBuilder.Windows
             toolStripSeparator12.Name = "toolStripSeparator12";
             toolStripSeparator12.Size = new System.Drawing.Size(6, 23);
             // 
+            // toolStripMenuItem4
+            // 
+            toolStripMenuItem4.Name = "toolStripMenuItem4";
+            toolStripMenuItem4.Size = new System.Drawing.Size(150, 6);
+            // 
+            // toolStripSeparator2
+            // 
+            toolStripSeparator2.Name = "toolStripSeparator2";
+            toolStripSeparator2.Size = new System.Drawing.Size(153, 6);
+            // 
             // seperatorfileopen
             // 
             this.seperatorfileopen.Margin = new System.Windows.Forms.Padding(0, 3, 0, 3);
@@ -312,6 +322,25 @@ namespace CodeImp.DoomBuilder.Windows
             this.menufile.Size = new System.Drawing.Size(37, 20);
             this.menufile.Text = "&File";
             // 
+            // itemnewmap
+            // 
+            this.itemnewmap.Image = global::CodeImp.DoomBuilder.Properties.Resources.File;
+            this.itemnewmap.Name = "itemnewmap";
+            this.itemnewmap.ShortcutKeyDisplayString = "";
+            this.itemnewmap.Size = new System.Drawing.Size(202, 22);
+            this.itemnewmap.Tag = "builder_newmap";
+            this.itemnewmap.Text = "&New Map";
+            this.itemnewmap.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
+            // itemopenmap
+            // 
+            this.itemopenmap.Image = global::CodeImp.DoomBuilder.Properties.Resources.OpenMap;
+            this.itemopenmap.Name = "itemopenmap";
+            this.itemopenmap.Size = new System.Drawing.Size(202, 22);
+            this.itemopenmap.Tag = "builder_openmap";
+            this.itemopenmap.Text = "&Open Map...";
+            this.itemopenmap.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
             // itemclosemap
             // 
             this.itemclosemap.Name = "itemclosemap";
@@ -320,6 +349,15 @@ namespace CodeImp.DoomBuilder.Windows
             this.itemclosemap.Text = "&Close Map";
             this.itemclosemap.Click += new System.EventHandler(this.InvokeTaggedAction);
             // 
+            // itemsavemap
+            // 
+            this.itemsavemap.Image = global::CodeImp.DoomBuilder.Properties.Resources.SaveMap;
+            this.itemsavemap.Name = "itemsavemap";
+            this.itemsavemap.Size = new System.Drawing.Size(202, 22);
+            this.itemsavemap.Tag = "builder_savemap";
+            this.itemsavemap.Text = "&Save Map";
+            this.itemsavemap.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
             // itemsavemapas
             // 
             this.itemsavemapas.Name = "itemsavemapas";
@@ -379,64 +417,265 @@ namespace CodeImp.DoomBuilder.Windows
             this.menuedit.Size = new System.Drawing.Size(39, 20);
             this.menuedit.Text = "&Edit";
             // 
+            // itemundo
+            // 
+            this.itemundo.Image = global::CodeImp.DoomBuilder.Properties.Resources.Undo;
+            this.itemundo.Name = "itemundo";
+            this.itemundo.Size = new System.Drawing.Size(163, 22);
+            this.itemundo.Tag = "builder_undo";
+            this.itemundo.Text = "&Undo";
+            this.itemundo.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
+            // itemredo
+            // 
+            this.itemredo.Image = global::CodeImp.DoomBuilder.Properties.Resources.Redo;
+            this.itemredo.Name = "itemredo";
+            this.itemredo.Size = new System.Drawing.Size(163, 22);
+            this.itemredo.Tag = "builder_redo";
+            this.itemredo.Text = "&Redo";
+            this.itemredo.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
             // seperatoreditundo
             // 
             this.seperatoreditundo.Margin = new System.Windows.Forms.Padding(0, 3, 0, 3);
             this.seperatoreditundo.Name = "seperatoreditundo";
             this.seperatoreditundo.Size = new System.Drawing.Size(160, 6);
             // 
-            // seperatoreditgeometry
+            // itemcut
             // 
-            this.seperatoreditgeometry.Margin = new System.Windows.Forms.Padding(0, 3, 0, 3);
-            this.seperatoreditgeometry.Name = "seperatoreditgeometry";
-            this.seperatoreditgeometry.Size = new System.Drawing.Size(160, 6);
+            this.itemcut.Image = global::CodeImp.DoomBuilder.Properties.Resources.Cut;
+            this.itemcut.Name = "itemcut";
+            this.itemcut.Size = new System.Drawing.Size(163, 22);
+            this.itemcut.Tag = "builder_cutselection";
+            this.itemcut.Text = "Cu&t";
+            this.itemcut.Click += new System.EventHandler(this.InvokeTaggedAction);
             // 
-            // itemgridinc
+            // itemcopy
             // 
-            this.itemgridinc.Name = "itemgridinc";
-            this.itemgridinc.Size = new System.Drawing.Size(163, 22);
-            this.itemgridinc.Tag = "builder_griddec";
-            this.itemgridinc.Text = "&Increase Grid";
-            this.itemgridinc.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.itemcopy.Image = global::CodeImp.DoomBuilder.Properties.Resources.Copy;
+            this.itemcopy.Name = "itemcopy";
+            this.itemcopy.Size = new System.Drawing.Size(163, 22);
+            this.itemcopy.Tag = "builder_copyselection";
+            this.itemcopy.Text = "&Copy";
+            this.itemcopy.Click += new System.EventHandler(this.InvokeTaggedAction);
             // 
-            // itemgriddec
+            // itempaste
             // 
-            this.itemgriddec.Name = "itemgriddec";
-            this.itemgriddec.Size = new System.Drawing.Size(163, 22);
-            this.itemgriddec.Tag = "builder_gridinc";
-            this.itemgriddec.Text = "&Decrease Grid";
-            this.itemgriddec.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.itempaste.Image = global::CodeImp.DoomBuilder.Properties.Resources.Paste;
+            this.itempaste.Name = "itempaste";
+            this.itempaste.Size = new System.Drawing.Size(163, 22);
+            this.itempaste.Tag = "builder_pasteselection";
+            this.itempaste.Text = "&Paste";
+            this.itempaste.Click += new System.EventHandler(this.InvokeTaggedAction);
             // 
-            // menuview
+            // itempastespecial
             // 
-            this.menuview.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
-            this.itemthingsfilter,
-            this.seperatorviewthings,
-            this.itemviewnormal,
-            this.itemviewbrightness,
-            this.itemviewfloors,
-            this.itemviewceilings,
-            this.seperatorviewviews,
-            this.menuzoom,
-            this.itemfittoscreen,
-            this.itemtoggleinfo,
-            this.seperatorviewzoom,
-            this.itemscripteditor});
-            this.menuview.Name = "menuview";
-            this.menuview.Size = new System.Drawing.Size(44, 20);
+            this.itempastespecial.Image = global::CodeImp.DoomBuilder.Properties.Resources.PasteSpecial;
+            this.itempastespecial.Name = "itempastespecial";
+            this.itempastespecial.Size = new System.Drawing.Size(163, 22);
+            this.itempastespecial.Tag = "builder_pasteselectionspecial";
+            this.itempastespecial.Text = "Paste Special...";
+            this.itempastespecial.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
+            // itemsnaptogrid
+            // 
+            this.itemsnaptogrid.Checked = true;
+            this.itemsnaptogrid.CheckState = System.Windows.Forms.CheckState.Checked;
+            this.itemsnaptogrid.Image = global::CodeImp.DoomBuilder.Properties.Resources.Grid4;
+            this.itemsnaptogrid.Name = "itemsnaptogrid";
+            this.itemsnaptogrid.Size = new System.Drawing.Size(163, 22);
+            this.itemsnaptogrid.Tag = "builder_togglesnap";
+            this.itemsnaptogrid.Text = "&Snap to Grid";
+            this.itemsnaptogrid.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
+            // itemautomerge
+            // 
+            this.itemautomerge.Checked = true;
+            this.itemautomerge.CheckState = System.Windows.Forms.CheckState.Checked;
+            this.itemautomerge.Image = global::CodeImp.DoomBuilder.Properties.Resources.mergegeometry2;
+            this.itemautomerge.Name = "itemautomerge";
+            this.itemautomerge.Size = new System.Drawing.Size(163, 22);
+            this.itemautomerge.Tag = "builder_toggleautomerge";
+            this.itemautomerge.Text = "&Merge Geometry";
+            this.itemautomerge.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
+            // seperatoreditgeometry
+            // 
+            this.seperatoreditgeometry.Margin = new System.Windows.Forms.Padding(0, 3, 0, 3);
+            this.seperatoreditgeometry.Name = "seperatoreditgeometry";
+            this.seperatoreditgeometry.Size = new System.Drawing.Size(160, 6);
+            // 
+            // itemgridinc
+            // 
+            this.itemgridinc.Name = "itemgridinc";
+            this.itemgridinc.Size = new System.Drawing.Size(163, 22);
+            this.itemgridinc.Tag = "builder_griddec";
+            this.itemgridinc.Text = "&Increase Grid";
+            this.itemgridinc.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
+            // itemgriddec
+            // 
+            this.itemgriddec.Name = "itemgriddec";
+            this.itemgriddec.Size = new System.Drawing.Size(163, 22);
+            this.itemgriddec.Tag = "builder_gridinc";
+            this.itemgriddec.Text = "&Decrease Grid";
+            this.itemgriddec.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
+            // itemgridsetup
+            // 
+            this.itemgridsetup.Image = global::CodeImp.DoomBuilder.Properties.Resources.Grid2;
+            this.itemgridsetup.Name = "itemgridsetup";
+            this.itemgridsetup.Size = new System.Drawing.Size(163, 22);
+            this.itemgridsetup.Tag = "builder_gridsetup";
+            this.itemgridsetup.Text = "&Grid Setup...";
+            this.itemgridsetup.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
+            // itemmapoptions
+            // 
+            this.itemmapoptions.Image = global::CodeImp.DoomBuilder.Properties.Resources.Properties;
+            this.itemmapoptions.Name = "itemmapoptions";
+            this.itemmapoptions.Size = new System.Drawing.Size(163, 22);
+            this.itemmapoptions.Tag = "builder_mapoptions";
+            this.itemmapoptions.Text = "Map &Options....";
+            this.itemmapoptions.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
+            // menuview
+            // 
+            this.menuview.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.itemthingsfilter,
+            this.seperatorviewthings,
+            this.itemviewnormal,
+            this.itemviewbrightness,
+            this.itemviewfloors,
+            this.itemviewceilings,
+            this.seperatorviewviews,
+            this.menuzoom,
+            this.itemfittoscreen,
+            this.itemtoggleinfo,
+            this.seperatorviewzoom,
+            this.itemscripteditor});
+            this.menuview.Name = "menuview";
+            this.menuview.Size = new System.Drawing.Size(44, 20);
             this.menuview.Text = "&View";
             // 
+            // itemthingsfilter
+            // 
+            this.itemthingsfilter.Image = global::CodeImp.DoomBuilder.Properties.Resources.Filter;
+            this.itemthingsfilter.Name = "itemthingsfilter";
+            this.itemthingsfilter.Size = new System.Drawing.Size(209, 22);
+            this.itemthingsfilter.Tag = "builder_thingsfilterssetup";
+            this.itemthingsfilter.Text = "Configure &Things Filters...";
+            this.itemthingsfilter.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
             // seperatorviewthings
             // 
             this.seperatorviewthings.Margin = new System.Windows.Forms.Padding(0, 3, 0, 3);
             this.seperatorviewthings.Name = "seperatorviewthings";
             this.seperatorviewthings.Size = new System.Drawing.Size(206, 6);
             // 
+            // itemviewnormal
+            // 
+            this.itemviewnormal.Image = global::CodeImp.DoomBuilder.Properties.Resources.ViewNormal;
+            this.itemviewnormal.Name = "itemviewnormal";
+            this.itemviewnormal.Size = new System.Drawing.Size(209, 22);
+            this.itemviewnormal.Tag = "builder_viewmodenormal";
+            this.itemviewnormal.Text = "&Wireframe";
+            this.itemviewnormal.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
+            // itemviewbrightness
+            // 
+            this.itemviewbrightness.Image = global::CodeImp.DoomBuilder.Properties.Resources.ViewBrightness;
+            this.itemviewbrightness.Name = "itemviewbrightness";
+            this.itemviewbrightness.Size = new System.Drawing.Size(209, 22);
+            this.itemviewbrightness.Tag = "builder_viewmodebrightness";
+            this.itemviewbrightness.Text = "&Brightness Levels";
+            this.itemviewbrightness.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
+            // itemviewfloors
+            // 
+            this.itemviewfloors.Image = global::CodeImp.DoomBuilder.Properties.Resources.ViewTextureFloor;
+            this.itemviewfloors.Name = "itemviewfloors";
+            this.itemviewfloors.Size = new System.Drawing.Size(209, 22);
+            this.itemviewfloors.Tag = "builder_viewmodefloors";
+            this.itemviewfloors.Text = "&Floor Textures";
+            this.itemviewfloors.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
+            // itemviewceilings
+            // 
+            this.itemviewceilings.Image = global::CodeImp.DoomBuilder.Properties.Resources.ViewTextureCeiling;
+            this.itemviewceilings.Name = "itemviewceilings";
+            this.itemviewceilings.Size = new System.Drawing.Size(209, 22);
+            this.itemviewceilings.Tag = "builder_viewmodeceilings";
+            this.itemviewceilings.Text = "&Ceiling Textures";
+            this.itemviewceilings.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
             // seperatorviewviews
             // 
             this.seperatorviewviews.Name = "seperatorviewviews";
             this.seperatorviewviews.Size = new System.Drawing.Size(206, 6);
             // 
+            // menuzoom
+            // 
+            this.menuzoom.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.item2zoom200,
+            this.item2zoom100,
+            this.item2zoom50,
+            this.item2zoom25,
+            this.item2zoom10,
+            this.item2zoom5});
+            this.menuzoom.Image = global::CodeImp.DoomBuilder.Properties.Resources.Zoom;
+            this.menuzoom.Name = "menuzoom";
+            this.menuzoom.Size = new System.Drawing.Size(209, 22);
+            this.menuzoom.Text = "&Zoom";
+            // 
+            // item2zoom200
+            // 
+            this.item2zoom200.Name = "item2zoom200";
+            this.item2zoom200.Size = new System.Drawing.Size(102, 22);
+            this.item2zoom200.Tag = "200";
+            this.item2zoom200.Text = "200%";
+            this.item2zoom200.Click += new System.EventHandler(this.itemzoomto_Click);
+            // 
+            // item2zoom100
+            // 
+            this.item2zoom100.Name = "item2zoom100";
+            this.item2zoom100.Size = new System.Drawing.Size(102, 22);
+            this.item2zoom100.Tag = "100";
+            this.item2zoom100.Text = "100%";
+            this.item2zoom100.Click += new System.EventHandler(this.itemzoomto_Click);
+            // 
+            // item2zoom50
+            // 
+            this.item2zoom50.Name = "item2zoom50";
+            this.item2zoom50.Size = new System.Drawing.Size(102, 22);
+            this.item2zoom50.Tag = "50";
+            this.item2zoom50.Text = "50%";
+            this.item2zoom50.Click += new System.EventHandler(this.itemzoomto_Click);
+            // 
+            // item2zoom25
+            // 
+            this.item2zoom25.Name = "item2zoom25";
+            this.item2zoom25.Size = new System.Drawing.Size(102, 22);
+            this.item2zoom25.Tag = "25";
+            this.item2zoom25.Text = "25%";
+            this.item2zoom25.Click += new System.EventHandler(this.itemzoomto_Click);
+            // 
+            // item2zoom10
+            // 
+            this.item2zoom10.Name = "item2zoom10";
+            this.item2zoom10.Size = new System.Drawing.Size(102, 22);
+            this.item2zoom10.Tag = "10";
+            this.item2zoom10.Text = "10%";
+            this.item2zoom10.Click += new System.EventHandler(this.itemzoomto_Click);
+            // 
+            // item2zoom5
+            // 
+            this.item2zoom5.Name = "item2zoom5";
+            this.item2zoom5.Size = new System.Drawing.Size(102, 22);
+            this.item2zoom5.Tag = "5";
+            this.item2zoom5.Text = "5%";
+            this.item2zoom5.Click += new System.EventHandler(this.itemzoomto_Click);
+            // 
             // itemfittoscreen
             // 
             this.itemfittoscreen.Name = "itemfittoscreen";
@@ -459,6 +698,15 @@ namespace CodeImp.DoomBuilder.Windows
             this.seperatorviewzoom.Name = "seperatorviewzoom";
             this.seperatorviewzoom.Size = new System.Drawing.Size(206, 6);
             // 
+            // itemscripteditor
+            // 
+            this.itemscripteditor.Image = global::CodeImp.DoomBuilder.Properties.Resources.Script2;
+            this.itemscripteditor.Name = "itemscripteditor";
+            this.itemscripteditor.Size = new System.Drawing.Size(209, 22);
+            this.itemscripteditor.Tag = "builder_openscripteditor";
+            this.itemscripteditor.Text = "&Script Editor...";
+            this.itemscripteditor.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
             // menumode
             // 
             this.menumode.Name = "menumode";
@@ -528,6 +776,15 @@ namespace CodeImp.DoomBuilder.Windows
             this.itemreloadresources.Text = "&Reload Resources";
             this.itemreloadresources.Click += new System.EventHandler(this.InvokeTaggedAction);
             // 
+            // itemshowerrors
+            // 
+            this.itemshowerrors.Image = global::CodeImp.DoomBuilder.Properties.Resources.Warning;
+            this.itemshowerrors.Name = "itemshowerrors";
+            this.itemshowerrors.Size = new System.Drawing.Size(196, 22);
+            this.itemshowerrors.Tag = "builder_showerrors";
+            this.itemshowerrors.Text = "&Errors and Warnings...";
+            this.itemshowerrors.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
             // seperatortoolsresources
             // 
             this.seperatortoolsresources.Margin = new System.Windows.Forms.Padding(0, 3, 0, 3);
@@ -556,6 +813,15 @@ namespace CodeImp.DoomBuilder.Windows
             this.seperatortoolsconfig.Name = "seperatortoolsconfig";
             this.seperatortoolsconfig.Size = new System.Drawing.Size(193, 6);
             // 
+            // itemtestmap
+            // 
+            this.itemtestmap.Image = global::CodeImp.DoomBuilder.Properties.Resources.Test;
+            this.itemtestmap.Name = "itemtestmap";
+            this.itemtestmap.Size = new System.Drawing.Size(196, 22);
+            this.itemtestmap.Tag = "builder_testmap";
+            this.itemtestmap.Text = "&Test Map";
+            this.itemtestmap.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
             // menuhelp
             // 
             this.menuhelp.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
@@ -567,6 +833,22 @@ namespace CodeImp.DoomBuilder.Windows
             this.menuhelp.Size = new System.Drawing.Size(44, 20);
             this.menuhelp.Text = "&Help";
             // 
+            // itemhelprefmanual
+            // 
+            this.itemhelprefmanual.Image = global::CodeImp.DoomBuilder.Properties.Resources.Help;
+            this.itemhelprefmanual.Name = "itemhelprefmanual";
+            this.itemhelprefmanual.Size = new System.Drawing.Size(203, 22);
+            this.itemhelprefmanual.Text = "Reference &Manual";
+            this.itemhelprefmanual.Click += new System.EventHandler(this.itemhelprefmanual_Click);
+            // 
+            // itemhelpeditmode
+            // 
+            this.itemhelpeditmode.Image = global::CodeImp.DoomBuilder.Properties.Resources.Question;
+            this.itemhelpeditmode.Name = "itemhelpeditmode";
+            this.itemhelpeditmode.Size = new System.Drawing.Size(203, 22);
+            this.itemhelpeditmode.Text = "About this &Editing Mode";
+            this.itemhelpeditmode.Click += new System.EventHandler(this.itemhelpeditmode_Click);
+            // 
             // seperatorhelpmanual
             // 
             this.seperatorhelpmanual.Margin = new System.Windows.Forms.Padding(0, 3, 0, 3);
@@ -624,492 +906,7 @@ namespace CodeImp.DoomBuilder.Windows
             this.toolbar.Size = new System.Drawing.Size(1012, 25);
             this.toolbar.TabIndex = 1;
             // 
-            // thingfilters
-            // 
-            this.thingfilters.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-            this.thingfilters.Enabled = false;
-            this.thingfilters.Items.AddRange(new object[] {
-            "(none)",
-            "(custom)",
-            "Easy skill items only",
-            "Medium skill items only",
-            "Hard skill items only"});
-            this.thingfilters.Margin = new System.Windows.Forms.Padding(1, 0, 6, 0);
-            this.thingfilters.Name = "thingfilters";
-            this.thingfilters.Size = new System.Drawing.Size(130, 25);
-            this.thingfilters.ToolTipText = "Things Filter";
-            this.thingfilters.SelectedIndexChanged += new System.EventHandler(this.thingfilters_SelectedIndexChanged);
-            this.thingfilters.DropDownClosed += new System.EventHandler(this.LoseFocus);
-            // 
-            // seperatorviews
-            // 
-            this.seperatorviews.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0);
-            this.seperatorviews.Name = "seperatorviews";
-            this.seperatorviews.Size = new System.Drawing.Size(6, 25);
-            // 
-            // separatorgzmodes
-            // 
-            this.separatorgzmodes.Name = "separatorgzmodes";
-            this.separatorgzmodes.Size = new System.Drawing.Size(6, 25);
-            // 
-            // seperatorgeometry
-            // 
-            this.seperatorgeometry.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0);
-            this.seperatorgeometry.Name = "seperatorgeometry";
-            this.seperatorgeometry.Size = new System.Drawing.Size(6, 25);
-            // 
-            // seperatortesting
-            // 
-            this.seperatortesting.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0);
-            this.seperatortesting.Name = "seperatortesting";
-            this.seperatortesting.Size = new System.Drawing.Size(6, 25);
-            // 
-            // statusbar
-            // 
-            this.statusbar.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-            this.statusbar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
-            this.statuslabel,
-            this.configlabel,
-            toolStripSeparator12,
-            this.gridlabel,
-            this.buttongrid,
-            toolStripSeparator1,
-            this.zoomlabel,
-            this.buttonzoom,
-            toolStripSeparator9,
-            this.xposlabel,
-            this.poscommalabel,
-            this.yposlabel});
-            this.statusbar.Location = new System.Drawing.Point(0, 670);
-            this.statusbar.Name = "statusbar";
-            this.statusbar.ShowItemToolTips = true;
-            this.statusbar.Size = new System.Drawing.Size(1012, 23);
-            this.statusbar.TabIndex = 2;
-            // 
-            // configlabel
-            // 
-            this.configlabel.AutoSize = false;
-            this.configlabel.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-            this.configlabel.Name = "configlabel";
-            this.configlabel.Size = new System.Drawing.Size(280, 18);
-            this.configlabel.Text = "ZDoom (Doom in Hexen Format)";
-            this.configlabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
-            this.configlabel.ToolTipText = "Current Game Configuration";
-            // 
-            // gridlabel
-            // 
-            this.gridlabel.AutoSize = false;
-            this.gridlabel.AutoToolTip = true;
-            this.gridlabel.Name = "gridlabel";
-            this.gridlabel.Size = new System.Drawing.Size(62, 18);
-            this.gridlabel.Text = "32 mp";
-            this.gridlabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
-            this.gridlabel.TextImageRelation = System.Windows.Forms.TextImageRelation.Overlay;
-            this.gridlabel.ToolTipText = "Grid size";
-            // 
-            // zoomlabel
-            // 
-            this.zoomlabel.AutoSize = false;
-            this.zoomlabel.AutoToolTip = true;
-            this.zoomlabel.Name = "zoomlabel";
-            this.zoomlabel.Size = new System.Drawing.Size(54, 18);
-            this.zoomlabel.Text = "50%";
-            this.zoomlabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
-            this.zoomlabel.TextImageRelation = System.Windows.Forms.TextImageRelation.Overlay;
-            this.zoomlabel.ToolTipText = "Zoom level";
-            // 
-            // xposlabel
-            // 
-            this.xposlabel.AutoSize = false;
-            this.xposlabel.Name = "xposlabel";
-            this.xposlabel.Size = new System.Drawing.Size(50, 18);
-            this.xposlabel.Text = "0";
-            this.xposlabel.ToolTipText = "Current X, Y coordinates on map";
-            // 
-            // yposlabel
-            // 
-            this.yposlabel.AutoSize = false;
-            this.yposlabel.Name = "yposlabel";
-            this.yposlabel.Size = new System.Drawing.Size(50, 18);
-            this.yposlabel.Text = "0";
-            this.yposlabel.ToolTipText = "Current X, Y coordinates on map";
-            // 
-            // panelinfo
-            // 
-            this.panelinfo.Controls.Add(this.heightpanel1);
-            this.panelinfo.Controls.Add(this.vertexinfo);
-            this.panelinfo.Controls.Add(this.labelcollapsedinfo);
-            this.panelinfo.Controls.Add(this.buttontoggleinfo);
-            this.panelinfo.Controls.Add(this.modename);
-            this.panelinfo.Controls.Add(this.linedefinfo);
-            this.panelinfo.Controls.Add(this.thinginfo);
-            this.panelinfo.Controls.Add(this.sectorinfo);
-            this.panelinfo.Dock = System.Windows.Forms.DockStyle.Bottom;
-            this.panelinfo.Location = new System.Drawing.Point(26, 564);
-            this.panelinfo.Name = "panelinfo";
-            this.panelinfo.Size = new System.Drawing.Size(986, 106);
-            this.panelinfo.TabIndex = 4;
-            // 
-            // heightpanel1
-            // 
-            this.heightpanel1.BackColor = System.Drawing.Color.Navy;
-            this.heightpanel1.ForeColor = System.Drawing.SystemColors.ControlText;
-            this.heightpanel1.Location = new System.Drawing.Point(0, 0);
-            this.heightpanel1.Name = "heightpanel1";
-            this.heightpanel1.Size = new System.Drawing.Size(29, 106);
-            this.heightpanel1.TabIndex = 7;
-            this.heightpanel1.Visible = false;
-            // 
-            // vertexinfo
-            // 
-            this.vertexinfo.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-            this.vertexinfo.Location = new System.Drawing.Point(3, 3);
-            this.vertexinfo.MaximumSize = new System.Drawing.Size(10000, 100);
-            this.vertexinfo.MinimumSize = new System.Drawing.Size(100, 100);
-            this.vertexinfo.Name = "vertexinfo";
-            this.vertexinfo.Size = new System.Drawing.Size(310, 100);
-            this.vertexinfo.TabIndex = 1;
-            this.vertexinfo.Visible = false;
-            // 
-            // labelcollapsedinfo
-            // 
-            this.labelcollapsedinfo.AutoSize = true;
-            this.labelcollapsedinfo.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-            this.labelcollapsedinfo.Location = new System.Drawing.Point(2, 2);
-            this.labelcollapsedinfo.Name = "labelcollapsedinfo";
-            this.labelcollapsedinfo.Size = new System.Drawing.Size(137, 13);
-            this.labelcollapsedinfo.TabIndex = 6;
-            this.labelcollapsedinfo.Text = "Collapsed Descriptions";
-            this.labelcollapsedinfo.Visible = false;
-            // 
-            // buttontoggleinfo
-            // 
-            this.buttontoggleinfo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
-            this.buttontoggleinfo.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
-            this.buttontoggleinfo.Font = new System.Drawing.Font("Marlett", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(2)));
-            this.buttontoggleinfo.Location = new System.Drawing.Point(962, 1);
-            this.buttontoggleinfo.Name = "buttontoggleinfo";
-            this.buttontoggleinfo.Size = new System.Drawing.Size(22, 19);
-            this.buttontoggleinfo.TabIndex = 5;
-            this.buttontoggleinfo.TabStop = false;
-            this.buttontoggleinfo.Tag = "builder_toggleinfopanel";
-            this.buttontoggleinfo.Text = "6";
-            this.buttontoggleinfo.UseVisualStyleBackColor = true;
-            this.buttontoggleinfo.Click += new System.EventHandler(this.InvokeTaggedAction);
-            this.buttontoggleinfo.MouseUp += new System.Windows.Forms.MouseEventHandler(this.buttontoggleinfo_MouseUp);
-            // 
-            // modename
-            // 
-            this.modename.AutoSize = true;
-            this.modename.Font = new System.Drawing.Font("Verdana", 36F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-            this.modename.ForeColor = System.Drawing.SystemColors.GrayText;
-            this.modename.Location = new System.Drawing.Point(12, 20);
-            this.modename.Name = "modename";
-            this.modename.Size = new System.Drawing.Size(244, 59);
-            this.modename.TabIndex = 4;
-            this.modename.Text = "Vertices";
-            this.modename.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
-            this.modename.UseMnemonic = false;
-            this.modename.Visible = false;
-            // 
-            // linedefinfo
-            // 
-            this.linedefinfo.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-            this.linedefinfo.Location = new System.Drawing.Point(3, 3);
-            this.linedefinfo.MaximumSize = new System.Drawing.Size(10000, 100);
-            this.linedefinfo.MinimumSize = new System.Drawing.Size(100, 100);
-            this.linedefinfo.Name = "linedefinfo";
-            this.linedefinfo.Size = new System.Drawing.Size(1039, 100);
-            this.linedefinfo.TabIndex = 0;
-            this.linedefinfo.Visible = false;
-            // 
-            // thinginfo
-            // 
-            this.thinginfo.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-            this.thinginfo.Location = new System.Drawing.Point(3, 3);
-            this.thinginfo.MaximumSize = new System.Drawing.Size(10000, 100);
-            this.thinginfo.MinimumSize = new System.Drawing.Size(100, 100);
-            this.thinginfo.Name = "thinginfo";
-            this.thinginfo.Size = new System.Drawing.Size(639, 100);
-            this.thinginfo.TabIndex = 3;
-            this.thinginfo.Visible = false;
-            // 
-            // sectorinfo
-            // 
-            this.sectorinfo.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-            this.sectorinfo.Location = new System.Drawing.Point(3, 3);
-            this.sectorinfo.MaximumSize = new System.Drawing.Size(10000, 100);
-            this.sectorinfo.MinimumSize = new System.Drawing.Size(100, 100);
-            this.sectorinfo.Name = "sectorinfo";
-            this.sectorinfo.Size = new System.Drawing.Size(522, 100);
-            this.sectorinfo.TabIndex = 2;
-            this.sectorinfo.Visible = false;
-            // 
-            // redrawtimer
-            // 
-            this.redrawtimer.Interval = 1;
-            this.redrawtimer.Tick += new System.EventHandler(this.redrawtimer_Tick);
-            // 
-            // display
-            // 
-            this.display.BackColor = System.Drawing.SystemColors.AppWorkspace;
-            this.display.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
-            this.display.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
-            this.display.CausesValidation = false;
-            this.display.Location = new System.Drawing.Point(373, 141);
-            this.display.Name = "display";
-            this.display.Size = new System.Drawing.Size(542, 307);
-            this.display.TabIndex = 5;
-            this.display.MouseLeave += new System.EventHandler(this.display_MouseLeave);
-            this.display.Paint += new System.Windows.Forms.PaintEventHandler(this.display_Paint);
-            this.display.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(this.display_PreviewKeyDown);
-            this.display.MouseMove += new System.Windows.Forms.MouseEventHandler(this.display_MouseMove);
-            this.display.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.display_MouseDoubleClick);
-            this.display.MouseClick += new System.Windows.Forms.MouseEventHandler(this.display_MouseClick);
-            this.display.MouseDown += new System.Windows.Forms.MouseEventHandler(this.display_MouseDown);
-            this.display.Resize += new System.EventHandler(this.display_Resize);
-            this.display.MouseUp += new System.Windows.Forms.MouseEventHandler(this.display_MouseUp);
-            this.display.MouseEnter += new System.EventHandler(this.display_MouseEnter);
-            // 
-            // processor
-            // 
-            this.processor.Interval = 10;
-            this.processor.Tick += new System.EventHandler(this.processor_Tick);
-            // 
-            // statusflasher
-            // 
-            this.statusflasher.Tick += new System.EventHandler(this.statusflasher_Tick);
-            // 
-            // statusresetter
-            // 
-            this.statusresetter.Tick += new System.EventHandler(this.statusresetter_Tick);
-            // 
-            // dockersspace
-            // 
-            this.dockersspace.Dock = System.Windows.Forms.DockStyle.Left;
-            this.dockersspace.Location = new System.Drawing.Point(0, 49);
-            this.dockersspace.Name = "dockersspace";
-            this.dockersspace.Size = new System.Drawing.Size(26, 621);
-            this.dockersspace.TabIndex = 6;
-            // 
-            // dockerspanel
-            // 
-            this.dockerspanel.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-            this.dockerspanel.Location = new System.Drawing.Point(62, 67);
-            this.dockerspanel.Name = "dockerspanel";
-            this.dockerspanel.Size = new System.Drawing.Size(236, 467);
-            this.dockerspanel.TabIndex = 7;
-            this.dockerspanel.TabStop = false;
-            this.dockerspanel.UserResize += new System.EventHandler(this.dockerspanel_UserResize);
-            this.dockerspanel.Collapsed += new System.EventHandler(this.LoseFocus);
-            this.dockerspanel.MouseContainerEnter += new System.EventHandler(this.dockerspanel_MouseContainerEnter);
-            // 
-            // dockerscollapser
-            // 
-            this.dockerscollapser.Interval = 200;
-            this.dockerscollapser.Tick += new System.EventHandler(this.dockerscollapser_Tick);
-            // 
-            // statuslabel
-            // 
-            this.statuslabel.Image = global::CodeImp.DoomBuilder.Properties.Resources.Status2;
-            this.statuslabel.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
-            this.statuslabel.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
-            this.statuslabel.Name = "statuslabel";
-            this.statuslabel.Size = new System.Drawing.Size(201, 16);
-            this.statuslabel.Spring = true;
-            this.statuslabel.Text = "Initializing user interface...";
-            this.statuslabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
-            // 
-            // buttongrid
-            // 
-            this.buttongrid.AutoToolTip = false;
-            this.buttongrid.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
-            this.buttongrid.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
-            this.itemgrid1024,
-            this.itemgrid512,
-            this.itemgrid256,
-            this.itemgrid128,
-            this.itemgrid64,
-            this.itemgrid32,
-            this.itemgrid16,
-            this.itemgrid8,
-            this.itemgrid4,
-            toolStripMenuItem4,
-            this.itemgridcustom});
-            this.buttongrid.Image = global::CodeImp.DoomBuilder.Properties.Resources.Grid2_arrowup;
-            this.buttongrid.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
-            this.buttongrid.ImageTransparentColor = System.Drawing.Color.Transparent;
-            this.buttongrid.Name = "buttongrid";
-            this.buttongrid.ShowDropDownArrow = false;
-            this.buttongrid.Size = new System.Drawing.Size(29, 20);
-            this.buttongrid.Text = "Grid";
-            // 
-            // itemgrid1024
-            // 
-            this.itemgrid1024.Name = "itemgrid1024";
-            this.itemgrid1024.Size = new System.Drawing.Size(153, 22);
-            this.itemgrid1024.Tag = "1024";
-            this.itemgrid1024.Text = "1024 mp";
-            this.itemgrid1024.Click += new System.EventHandler(this.itemgridsize_Click);
-            // 
-            // itemgrid512
-            // 
-            this.itemgrid512.Name = "itemgrid512";
-            this.itemgrid512.Size = new System.Drawing.Size(153, 22);
-            this.itemgrid512.Tag = "512";
-            this.itemgrid512.Text = "512 mp";
-            this.itemgrid512.Click += new System.EventHandler(this.itemgridsize_Click);
-            // 
-            // itemgrid256
-            // 
-            this.itemgrid256.Name = "itemgrid256";
-            this.itemgrid256.Size = new System.Drawing.Size(153, 22);
-            this.itemgrid256.Tag = "256";
-            this.itemgrid256.Text = "256 mp";
-            this.itemgrid256.Click += new System.EventHandler(this.itemgridsize_Click);
-            // 
-            // itemgrid128
-            // 
-            this.itemgrid128.Name = "itemgrid128";
-            this.itemgrid128.Size = new System.Drawing.Size(153, 22);
-            this.itemgrid128.Tag = "128";
-            this.itemgrid128.Text = "128 mp";
-            this.itemgrid128.Click += new System.EventHandler(this.itemgridsize_Click);
-            // 
-            // itemgrid64
-            // 
-            this.itemgrid64.Name = "itemgrid64";
-            this.itemgrid64.Size = new System.Drawing.Size(153, 22);
-            this.itemgrid64.Tag = "64";
-            this.itemgrid64.Text = "64 mp";
-            this.itemgrid64.Click += new System.EventHandler(this.itemgridsize_Click);
-            // 
-            // itemgrid32
-            // 
-            this.itemgrid32.Name = "itemgrid32";
-            this.itemgrid32.Size = new System.Drawing.Size(153, 22);
-            this.itemgrid32.Tag = "32";
-            this.itemgrid32.Text = "32 mp";
-            this.itemgrid32.Click += new System.EventHandler(this.itemgridsize_Click);
-            // 
-            // itemgrid16
-            // 
-            this.itemgrid16.Name = "itemgrid16";
-            this.itemgrid16.Size = new System.Drawing.Size(153, 22);
-            this.itemgrid16.Tag = "16";
-            this.itemgrid16.Text = "16 mp";
-            this.itemgrid16.Click += new System.EventHandler(this.itemgridsize_Click);
-            // 
-            // itemgrid8
-            // 
-            this.itemgrid8.Name = "itemgrid8";
-            this.itemgrid8.Size = new System.Drawing.Size(153, 22);
-            this.itemgrid8.Tag = "8";
-            this.itemgrid8.Text = "8 mp";
-            this.itemgrid8.Click += new System.EventHandler(this.itemgridsize_Click);
-            // 
-            // itemgrid4
-            // 
-            this.itemgrid4.Name = "itemgrid4";
-            this.itemgrid4.Size = new System.Drawing.Size(153, 22);
-            this.itemgrid4.Tag = "4";
-            this.itemgrid4.Text = "4 mp";
-            this.itemgrid4.Click += new System.EventHandler(this.itemgridsize_Click);
-            // 
-            // toolStripMenuItem4
-            // 
-            toolStripMenuItem4.Name = "toolStripMenuItem4";
-            toolStripMenuItem4.Size = new System.Drawing.Size(150, 6);
-            // 
-            // itemgridcustom
-            // 
-            this.itemgridcustom.Name = "itemgridcustom";
-            this.itemgridcustom.Size = new System.Drawing.Size(153, 22);
-            this.itemgridcustom.Text = "Customize...";
-            this.itemgridcustom.Click += new System.EventHandler(this.itemgridcustom_Click);
-            // 
-            // buttonzoom
-            // 
-            this.buttonzoom.AutoToolTip = false;
-            this.buttonzoom.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
-            this.buttonzoom.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
-            this.itemzoom200,
-            this.itemzoom100,
-            this.itemzoom50,
-            this.itemzoom25,
-            this.itemzoom10,
-            this.itemzoom5,
-            toolStripSeparator2,
-            this.itemzoomfittoscreen});
-            this.buttonzoom.Image = global::CodeImp.DoomBuilder.Properties.Resources.Zoom_arrowup;
-            this.buttonzoom.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
-            this.buttonzoom.ImageTransparentColor = System.Drawing.Color.Transparent;
-            this.buttonzoom.Name = "buttonzoom";
-            this.buttonzoom.ShowDropDownArrow = false;
-            this.buttonzoom.Size = new System.Drawing.Size(29, 20);
-            this.buttonzoom.Text = "Zoom";
-            // 
-            // itemzoom200
-            // 
-            this.itemzoom200.Name = "itemzoom200";
-            this.itemzoom200.Size = new System.Drawing.Size(156, 22);
-            this.itemzoom200.Tag = "200";
-            this.itemzoom200.Text = "200%";
-            this.itemzoom200.Click += new System.EventHandler(this.itemzoomto_Click);
-            // 
-            // itemzoom100
-            // 
-            this.itemzoom100.Name = "itemzoom100";
-            this.itemzoom100.Size = new System.Drawing.Size(156, 22);
-            this.itemzoom100.Tag = "100";
-            this.itemzoom100.Text = "100%";
-            this.itemzoom100.Click += new System.EventHandler(this.itemzoomto_Click);
-            // 
-            // itemzoom50
-            // 
-            this.itemzoom50.Name = "itemzoom50";
-            this.itemzoom50.Size = new System.Drawing.Size(156, 22);
-            this.itemzoom50.Tag = "50";
-            this.itemzoom50.Text = "50%";
-            this.itemzoom50.Click += new System.EventHandler(this.itemzoomto_Click);
-            // 
-            // itemzoom25
-            // 
-            this.itemzoom25.Name = "itemzoom25";
-            this.itemzoom25.Size = new System.Drawing.Size(156, 22);
-            this.itemzoom25.Tag = "25";
-            this.itemzoom25.Text = "25%";
-            this.itemzoom25.Click += new System.EventHandler(this.itemzoomto_Click);
-            // 
-            // itemzoom10
-            // 
-            this.itemzoom10.Name = "itemzoom10";
-            this.itemzoom10.Size = new System.Drawing.Size(156, 22);
-            this.itemzoom10.Tag = "10";
-            this.itemzoom10.Text = "10%";
-            this.itemzoom10.Click += new System.EventHandler(this.itemzoomto_Click);
-            // 
-            // itemzoom5
-            // 
-            this.itemzoom5.Name = "itemzoom5";
-            this.itemzoom5.Size = new System.Drawing.Size(156, 22);
-            this.itemzoom5.Tag = "5";
-            this.itemzoom5.Text = "5%";
-            this.itemzoom5.Click += new System.EventHandler(this.itemzoomto_Click);
-            // 
-            // toolStripSeparator2
-            // 
-            toolStripSeparator2.Name = "toolStripSeparator2";
-            toolStripSeparator2.Size = new System.Drawing.Size(153, 6);
-            // 
-            // itemzoomfittoscreen
-            // 
-            this.itemzoomfittoscreen.Name = "itemzoomfittoscreen";
-            this.itemzoomfittoscreen.Size = new System.Drawing.Size(156, 22);
-            this.itemzoomfittoscreen.Text = "Fit to screen";
-            this.itemzoomfittoscreen.Click += new System.EventHandler(this.itemzoomfittoscreen_Click);
-            // 
-            // buttonnewmap
+            // buttonnewmap
             // 
             this.buttonnewmap.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
             this.buttonnewmap.Image = global::CodeImp.DoomBuilder.Properties.Resources.NewMap;
@@ -1243,6 +1040,23 @@ namespace CodeImp.DoomBuilder.Windows
             this.buttonthingsfilter.Text = "Configure Things Filters";
             this.buttonthingsfilter.Click += new System.EventHandler(this.InvokeTaggedAction);
             // 
+            // thingfilters
+            // 
+            this.thingfilters.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.thingfilters.Enabled = false;
+            this.thingfilters.Items.AddRange(new object[] {
+            "(none)",
+            "(custom)",
+            "Easy skill items only",
+            "Medium skill items only",
+            "Hard skill items only"});
+            this.thingfilters.Margin = new System.Windows.Forms.Padding(1, 0, 6, 0);
+            this.thingfilters.Name = "thingfilters";
+            this.thingfilters.Size = new System.Drawing.Size(130, 25);
+            this.thingfilters.ToolTipText = "Things Filter";
+            this.thingfilters.SelectedIndexChanged += new System.EventHandler(this.thingfilters_SelectedIndexChanged);
+            this.thingfilters.DropDownClosed += new System.EventHandler(this.LoseFocus);
+            // 
             // buttonviewnormal
             // 
             this.buttonviewnormal.CheckOnClick = true;
@@ -1291,6 +1105,12 @@ namespace CodeImp.DoomBuilder.Windows
             this.buttonviewceilings.Text = "View Ceiling Textures";
             this.buttonviewceilings.Click += new System.EventHandler(this.InvokeTaggedAction);
             // 
+            // seperatorviews
+            // 
+            this.seperatorviews.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0);
+            this.seperatorviews.Name = "seperatorviews";
+            this.seperatorviews.Size = new System.Drawing.Size(6, 25);
+            // 
             // buttonsnaptogrid
             // 
             this.buttonsnaptogrid.Checked = true;
@@ -1317,337 +1137,525 @@ namespace CodeImp.DoomBuilder.Windows
             this.buttonautomerge.Text = "Merge Geometry";
             this.buttonautomerge.Click += new System.EventHandler(this.InvokeTaggedAction);
             // 
+            // separatorgzmodes
+            // 
+            this.separatorgzmodes.Name = "separatorgzmodes";
+            this.separatorgzmodes.Size = new System.Drawing.Size(6, 25);
+            // 
             // buttontoggledynlight
             // 
             this.buttontoggledynlight.Checked = true;
             this.buttontoggledynlight.CheckOnClick = true;
             this.buttontoggledynlight.CheckState = System.Windows.Forms.CheckState.Checked;
             this.buttontoggledynlight.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this.buttontoggledynlight.Enabled = false;
             this.buttontoggledynlight.Image = global::CodeImp.DoomBuilder.Properties.Resources.Light;
             this.buttontoggledynlight.ImageTransparentColor = System.Drawing.Color.Magenta;
             this.buttontoggledynlight.Name = "buttontoggledynlight";
             this.buttontoggledynlight.Size = new System.Drawing.Size(23, 22);
+            this.buttontoggledynlight.Tag = "builder_gztogglelights";
             this.buttontoggledynlight.Text = "Toggle Dynamic Lights";
-            this.buttontoggledynlight.Click += new System.EventHandler(this.buttontoggledynlight_Click);
+            this.buttontoggledynlight.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
+            // buttontoggleanimatedlight
+            // 
+            this.buttontoggleanimatedlight.CheckOnClick = true;
+            this.buttontoggleanimatedlight.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this.buttontoggleanimatedlight.Enabled = false;
+            this.buttontoggleanimatedlight.Image = global::CodeImp.DoomBuilder.Properties.Resources.Light_animate;
+            this.buttontoggleanimatedlight.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.buttontoggleanimatedlight.Name = "buttontoggleanimatedlight";
+            this.buttontoggleanimatedlight.Size = new System.Drawing.Size(23, 22);
+            this.buttontoggleanimatedlight.Tag = "builder_gztogglelightsanimation";
+            this.buttontoggleanimatedlight.Text = "Toggle Dynamic Light Animation";
+            this.buttontoggleanimatedlight.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
+            // buttontogglemodels
+            // 
+            this.buttontogglemodels.Checked = true;
+            this.buttontogglemodels.CheckOnClick = true;
+            this.buttontogglemodels.CheckState = System.Windows.Forms.CheckState.Checked;
+            this.buttontogglemodels.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this.buttontogglemodels.Enabled = false;
+            this.buttontogglemodels.Image = ((System.Drawing.Image)(resources.GetObject("buttontogglemodels.Image")));
+            this.buttontogglemodels.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.buttontogglemodels.Name = "buttontogglemodels";
+            this.buttontogglemodels.Size = new System.Drawing.Size(23, 22);
+            this.buttontogglemodels.Tag = "builder_gztogglemodels";
+            this.buttontogglemodels.Text = "Toggle Models Rendering";
+            this.buttontogglemodels.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
+            // buttonselectedmodelsonly
+            // 
+            this.buttonselectedmodelsonly.CheckOnClick = true;
+            this.buttonselectedmodelsonly.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this.buttonselectedmodelsonly.Enabled = false;
+            this.buttonselectedmodelsonly.Image = ((System.Drawing.Image)(resources.GetObject("buttonselectedmodelsonly.Image")));
+            this.buttonselectedmodelsonly.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.buttonselectedmodelsonly.Name = "buttonselectedmodelsonly";
+            this.buttonselectedmodelsonly.Size = new System.Drawing.Size(23, 22);
+            this.buttonselectedmodelsonly.Tag = "builder_gzdrawselectedmodelsonly";
+            this.buttonselectedmodelsonly.Text = "Render models for selected things only";
+            this.buttonselectedmodelsonly.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
+            // seperatorgeometry
+            // 
+            this.seperatorgeometry.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0);
+            this.seperatorgeometry.Name = "seperatorgeometry";
+            this.seperatorgeometry.Size = new System.Drawing.Size(6, 25);
+            // 
+            // buttontest
+            // 
+            this.buttontest.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this.buttontest.Image = global::CodeImp.DoomBuilder.Properties.Resources.Test;
+            this.buttontest.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
+            this.buttontest.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.buttontest.Name = "buttontest";
+            this.buttontest.Size = new System.Drawing.Size(32, 22);
+            this.buttontest.Tag = "builder_testmap";
+            this.buttontest.Text = "Test Map";
+            this.buttontest.ButtonClick += new System.EventHandler(this.InvokeTaggedAction);
+            // 
+            // seperatortesting
+            // 
+            this.seperatortesting.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0);
+            this.seperatortesting.Name = "seperatortesting";
+            this.seperatortesting.Size = new System.Drawing.Size(6, 25);
+            // 
+            // statusbar
+            // 
+            this.statusbar.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.statusbar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.statuslabel,
+            this.configlabel,
+            toolStripSeparator12,
+            this.gridlabel,
+            this.buttongrid,
+            toolStripSeparator1,
+            this.zoomlabel,
+            this.buttonzoom,
+            toolStripSeparator9,
+            this.xposlabel,
+            this.poscommalabel,
+            this.yposlabel});
+            this.statusbar.Location = new System.Drawing.Point(0, 670);
+            this.statusbar.Name = "statusbar";
+            this.statusbar.ShowItemToolTips = true;
+            this.statusbar.Size = new System.Drawing.Size(1012, 23);
+            this.statusbar.TabIndex = 2;
+            // 
+            // statuslabel
+            // 
+            this.statuslabel.Image = global::CodeImp.DoomBuilder.Properties.Resources.Status2;
+            this.statuslabel.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            this.statuslabel.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
+            this.statuslabel.Name = "statuslabel";
+            this.statuslabel.Size = new System.Drawing.Size(396, 18);
+            this.statuslabel.Spring = true;
+            this.statuslabel.Text = "Initializing user interface...";
+            this.statuslabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // configlabel
+            // 
+            this.configlabel.AutoSize = false;
+            this.configlabel.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.configlabel.Name = "configlabel";
+            this.configlabel.Size = new System.Drawing.Size(280, 18);
+            this.configlabel.Text = "ZDoom (Doom in Hexen Format)";
+            this.configlabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            this.configlabel.ToolTipText = "Current Game Configuration";
+            // 
+            // gridlabel
+            // 
+            this.gridlabel.AutoSize = false;
+            this.gridlabel.AutoToolTip = true;
+            this.gridlabel.Name = "gridlabel";
+            this.gridlabel.Size = new System.Drawing.Size(62, 18);
+            this.gridlabel.Text = "32 mp";
+            this.gridlabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            this.gridlabel.TextImageRelation = System.Windows.Forms.TextImageRelation.Overlay;
+            this.gridlabel.ToolTipText = "Grid size";
+            // 
+            // buttongrid
+            // 
+            this.buttongrid.AutoToolTip = false;
+            this.buttongrid.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this.buttongrid.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.itemgrid1024,
+            this.itemgrid512,
+            this.itemgrid256,
+            this.itemgrid128,
+            this.itemgrid64,
+            this.itemgrid32,
+            this.itemgrid16,
+            this.itemgrid8,
+            this.itemgrid4,
+            toolStripMenuItem4,
+            this.itemgridcustom});
+            this.buttongrid.Image = global::CodeImp.DoomBuilder.Properties.Resources.Grid2_arrowup;
+            this.buttongrid.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
+            this.buttongrid.ImageTransparentColor = System.Drawing.Color.Transparent;
+            this.buttongrid.Name = "buttongrid";
+            this.buttongrid.ShowDropDownArrow = false;
+            this.buttongrid.Size = new System.Drawing.Size(29, 21);
+            this.buttongrid.Text = "Grid";
+            // 
+            // itemgrid1024
+            // 
+            this.itemgrid1024.Name = "itemgrid1024";
+            this.itemgrid1024.Size = new System.Drawing.Size(153, 22);
+            this.itemgrid1024.Tag = "1024";
+            this.itemgrid1024.Text = "1024 mp";
+            this.itemgrid1024.Click += new System.EventHandler(this.itemgridsize_Click);
+            // 
+            // itemgrid512
+            // 
+            this.itemgrid512.Name = "itemgrid512";
+            this.itemgrid512.Size = new System.Drawing.Size(153, 22);
+            this.itemgrid512.Tag = "512";
+            this.itemgrid512.Text = "512 mp";
+            this.itemgrid512.Click += new System.EventHandler(this.itemgridsize_Click);
+            // 
+            // itemgrid256
+            // 
+            this.itemgrid256.Name = "itemgrid256";
+            this.itemgrid256.Size = new System.Drawing.Size(153, 22);
+            this.itemgrid256.Tag = "256";
+            this.itemgrid256.Text = "256 mp";
+            this.itemgrid256.Click += new System.EventHandler(this.itemgridsize_Click);
             // 
-            // buttontoggleanimatedlight
+            // itemgrid128
             // 
-            this.buttontoggleanimatedlight.CheckOnClick = true;
-            this.buttontoggleanimatedlight.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
-            this.buttontoggleanimatedlight.Image = global::CodeImp.DoomBuilder.Properties.Resources.Light_animate;
-            this.buttontoggleanimatedlight.ImageTransparentColor = System.Drawing.Color.Magenta;
-            this.buttontoggleanimatedlight.Name = "buttontoggleanimatedlight";
-            this.buttontoggleanimatedlight.Size = new System.Drawing.Size(23, 22);
-            this.buttontoggleanimatedlight.Text = "Toggle Dynamic Light Animation";
-            this.buttontoggleanimatedlight.Click += new System.EventHandler(this.buttontoggleanimatedlight_Click);
+            this.itemgrid128.Name = "itemgrid128";
+            this.itemgrid128.Size = new System.Drawing.Size(153, 22);
+            this.itemgrid128.Tag = "128";
+            this.itemgrid128.Text = "128 mp";
+            this.itemgrid128.Click += new System.EventHandler(this.itemgridsize_Click);
             // 
-            // buttontogglemodels
+            // itemgrid64
             // 
-            this.buttontogglemodels.Checked = true;
-            this.buttontogglemodels.CheckOnClick = true;
-            this.buttontogglemodels.CheckState = System.Windows.Forms.CheckState.Checked;
-            this.buttontogglemodels.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
-            this.buttontogglemodels.Image = ((System.Drawing.Image)(resources.GetObject("buttontogglemodels.Image")));
-            this.buttontogglemodels.ImageTransparentColor = System.Drawing.Color.Magenta;
-            this.buttontogglemodels.Name = "buttontogglemodels";
-            this.buttontogglemodels.Size = new System.Drawing.Size(23, 22);
-            this.buttontogglemodels.Text = "Toggle Models Rendering";
-            this.buttontogglemodels.Click += new System.EventHandler(this.buttontogglemodels_Click);
+            this.itemgrid64.Name = "itemgrid64";
+            this.itemgrid64.Size = new System.Drawing.Size(153, 22);
+            this.itemgrid64.Tag = "64";
+            this.itemgrid64.Text = "64 mp";
+            this.itemgrid64.Click += new System.EventHandler(this.itemgridsize_Click);
             // 
-            // buttonselectedmodelsonly
+            // itemgrid32
             // 
-            this.buttonselectedmodelsonly.CheckOnClick = true;
-            this.buttonselectedmodelsonly.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
-            this.buttonselectedmodelsonly.Image = ((System.Drawing.Image)(resources.GetObject("buttonselectedmodelsonly.Image")));
-            this.buttonselectedmodelsonly.ImageTransparentColor = System.Drawing.Color.Magenta;
-            this.buttonselectedmodelsonly.Name = "buttonselectedmodelsonly";
-            this.buttonselectedmodelsonly.Size = new System.Drawing.Size(23, 22);
-            this.buttonselectedmodelsonly.Text = "Render models for selected things only";
-            this.buttonselectedmodelsonly.Click += new System.EventHandler(this.buttonselectedmodelsonly_Click);
+            this.itemgrid32.Name = "itemgrid32";
+            this.itemgrid32.Size = new System.Drawing.Size(153, 22);
+            this.itemgrid32.Tag = "32";
+            this.itemgrid32.Text = "32 mp";
+            this.itemgrid32.Click += new System.EventHandler(this.itemgridsize_Click);
             // 
-            // buttontest
+            // itemgrid16
             // 
-            this.buttontest.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
-            this.buttontest.Image = global::CodeImp.DoomBuilder.Properties.Resources.Test;
-            this.buttontest.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
-            this.buttontest.ImageTransparentColor = System.Drawing.Color.Magenta;
-            this.buttontest.Name = "buttontest";
-            this.buttontest.Size = new System.Drawing.Size(32, 22);
-            this.buttontest.Tag = "builder_testmap";
-            this.buttontest.Text = "Test Map";
-            this.buttontest.ButtonClick += new System.EventHandler(this.InvokeTaggedAction);
+            this.itemgrid16.Name = "itemgrid16";
+            this.itemgrid16.Size = new System.Drawing.Size(153, 22);
+            this.itemgrid16.Tag = "16";
+            this.itemgrid16.Text = "16 mp";
+            this.itemgrid16.Click += new System.EventHandler(this.itemgridsize_Click);
             // 
-            // itemnewmap
+            // itemgrid8
             // 
-            this.itemnewmap.Image = global::CodeImp.DoomBuilder.Properties.Resources.File;
-            this.itemnewmap.Name = "itemnewmap";
-            this.itemnewmap.ShortcutKeyDisplayString = "";
-            this.itemnewmap.Size = new System.Drawing.Size(202, 22);
-            this.itemnewmap.Tag = "builder_newmap";
-            this.itemnewmap.Text = "&New Map";
-            this.itemnewmap.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.itemgrid8.Name = "itemgrid8";
+            this.itemgrid8.Size = new System.Drawing.Size(153, 22);
+            this.itemgrid8.Tag = "8";
+            this.itemgrid8.Text = "8 mp";
+            this.itemgrid8.Click += new System.EventHandler(this.itemgridsize_Click);
             // 
-            // itemopenmap
+            // itemgrid4
             // 
-            this.itemopenmap.Image = global::CodeImp.DoomBuilder.Properties.Resources.OpenMap;
-            this.itemopenmap.Name = "itemopenmap";
-            this.itemopenmap.Size = new System.Drawing.Size(202, 22);
-            this.itemopenmap.Tag = "builder_openmap";
-            this.itemopenmap.Text = "&Open Map...";
-            this.itemopenmap.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.itemgrid4.Name = "itemgrid4";
+            this.itemgrid4.Size = new System.Drawing.Size(153, 22);
+            this.itemgrid4.Tag = "4";
+            this.itemgrid4.Text = "4 mp";
+            this.itemgrid4.Click += new System.EventHandler(this.itemgridsize_Click);
             // 
-            // itemsavemap
+            // itemgridcustom
             // 
-            this.itemsavemap.Image = global::CodeImp.DoomBuilder.Properties.Resources.SaveMap;
-            this.itemsavemap.Name = "itemsavemap";
-            this.itemsavemap.Size = new System.Drawing.Size(202, 22);
-            this.itemsavemap.Tag = "builder_savemap";
-            this.itemsavemap.Text = "&Save Map";
-            this.itemsavemap.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.itemgridcustom.Name = "itemgridcustom";
+            this.itemgridcustom.Size = new System.Drawing.Size(153, 22);
+            this.itemgridcustom.Text = "Customize...";
+            this.itemgridcustom.Click += new System.EventHandler(this.itemgridcustom_Click);
             // 
-            // itemundo
+            // zoomlabel
             // 
-            this.itemundo.Image = global::CodeImp.DoomBuilder.Properties.Resources.Undo;
-            this.itemundo.Name = "itemundo";
-            this.itemundo.Size = new System.Drawing.Size(163, 22);
-            this.itemundo.Tag = "builder_undo";
-            this.itemundo.Text = "&Undo";
-            this.itemundo.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.zoomlabel.AutoSize = false;
+            this.zoomlabel.AutoToolTip = true;
+            this.zoomlabel.Name = "zoomlabel";
+            this.zoomlabel.Size = new System.Drawing.Size(54, 18);
+            this.zoomlabel.Text = "50%";
+            this.zoomlabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            this.zoomlabel.TextImageRelation = System.Windows.Forms.TextImageRelation.Overlay;
+            this.zoomlabel.ToolTipText = "Zoom level";
             // 
-            // itemredo
+            // buttonzoom
             // 
-            this.itemredo.Image = global::CodeImp.DoomBuilder.Properties.Resources.Redo;
-            this.itemredo.Name = "itemredo";
-            this.itemredo.Size = new System.Drawing.Size(163, 22);
-            this.itemredo.Tag = "builder_redo";
-            this.itemredo.Text = "&Redo";
-            this.itemredo.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.buttonzoom.AutoToolTip = false;
+            this.buttonzoom.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this.buttonzoom.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.itemzoom200,
+            this.itemzoom100,
+            this.itemzoom50,
+            this.itemzoom25,
+            this.itemzoom10,
+            this.itemzoom5,
+            toolStripSeparator2,
+            this.itemzoomfittoscreen});
+            this.buttonzoom.Image = global::CodeImp.DoomBuilder.Properties.Resources.Zoom_arrowup;
+            this.buttonzoom.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
+            this.buttonzoom.ImageTransparentColor = System.Drawing.Color.Transparent;
+            this.buttonzoom.Name = "buttonzoom";
+            this.buttonzoom.ShowDropDownArrow = false;
+            this.buttonzoom.Size = new System.Drawing.Size(29, 21);
+            this.buttonzoom.Text = "Zoom";
             // 
-            // itemcut
+            // itemzoom200
             // 
-            this.itemcut.Image = global::CodeImp.DoomBuilder.Properties.Resources.Cut;
-            this.itemcut.Name = "itemcut";
-            this.itemcut.Size = new System.Drawing.Size(163, 22);
-            this.itemcut.Tag = "builder_cutselection";
-            this.itemcut.Text = "Cu&t";
-            this.itemcut.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.itemzoom200.Name = "itemzoom200";
+            this.itemzoom200.Size = new System.Drawing.Size(156, 22);
+            this.itemzoom200.Tag = "200";
+            this.itemzoom200.Text = "200%";
+            this.itemzoom200.Click += new System.EventHandler(this.itemzoomto_Click);
             // 
-            // itemcopy
+            // itemzoom100
             // 
-            this.itemcopy.Image = global::CodeImp.DoomBuilder.Properties.Resources.Copy;
-            this.itemcopy.Name = "itemcopy";
-            this.itemcopy.Size = new System.Drawing.Size(163, 22);
-            this.itemcopy.Tag = "builder_copyselection";
-            this.itemcopy.Text = "&Copy";
-            this.itemcopy.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.itemzoom100.Name = "itemzoom100";
+            this.itemzoom100.Size = new System.Drawing.Size(156, 22);
+            this.itemzoom100.Tag = "100";
+            this.itemzoom100.Text = "100%";
+            this.itemzoom100.Click += new System.EventHandler(this.itemzoomto_Click);
             // 
-            // itempaste
+            // itemzoom50
             // 
-            this.itempaste.Image = global::CodeImp.DoomBuilder.Properties.Resources.Paste;
-            this.itempaste.Name = "itempaste";
-            this.itempaste.Size = new System.Drawing.Size(163, 22);
-            this.itempaste.Tag = "builder_pasteselection";
-            this.itempaste.Text = "&Paste";
-            this.itempaste.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.itemzoom50.Name = "itemzoom50";
+            this.itemzoom50.Size = new System.Drawing.Size(156, 22);
+            this.itemzoom50.Tag = "50";
+            this.itemzoom50.Text = "50%";
+            this.itemzoom50.Click += new System.EventHandler(this.itemzoomto_Click);
             // 
-            // itempastespecial
+            // itemzoom25
             // 
-            this.itempastespecial.Image = global::CodeImp.DoomBuilder.Properties.Resources.PasteSpecial;
-            this.itempastespecial.Name = "itempastespecial";
-            this.itempastespecial.Size = new System.Drawing.Size(163, 22);
-            this.itempastespecial.Tag = "builder_pasteselectionspecial";
-            this.itempastespecial.Text = "Paste Special...";
-            this.itempastespecial.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.itemzoom25.Name = "itemzoom25";
+            this.itemzoom25.Size = new System.Drawing.Size(156, 22);
+            this.itemzoom25.Tag = "25";
+            this.itemzoom25.Text = "25%";
+            this.itemzoom25.Click += new System.EventHandler(this.itemzoomto_Click);
             // 
-            // itemsnaptogrid
+            // itemzoom10
             // 
-            this.itemsnaptogrid.Checked = true;
-            this.itemsnaptogrid.CheckState = System.Windows.Forms.CheckState.Checked;
-            this.itemsnaptogrid.Image = global::CodeImp.DoomBuilder.Properties.Resources.Grid4;
-            this.itemsnaptogrid.Name = "itemsnaptogrid";
-            this.itemsnaptogrid.Size = new System.Drawing.Size(163, 22);
-            this.itemsnaptogrid.Tag = "builder_togglesnap";
-            this.itemsnaptogrid.Text = "&Snap to Grid";
-            this.itemsnaptogrid.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.itemzoom10.Name = "itemzoom10";
+            this.itemzoom10.Size = new System.Drawing.Size(156, 22);
+            this.itemzoom10.Tag = "10";
+            this.itemzoom10.Text = "10%";
+            this.itemzoom10.Click += new System.EventHandler(this.itemzoomto_Click);
             // 
-            // itemautomerge
+            // itemzoom5
             // 
-            this.itemautomerge.Checked = true;
-            this.itemautomerge.CheckState = System.Windows.Forms.CheckState.Checked;
-            this.itemautomerge.Image = global::CodeImp.DoomBuilder.Properties.Resources.mergegeometry2;
-            this.itemautomerge.Name = "itemautomerge";
-            this.itemautomerge.Size = new System.Drawing.Size(163, 22);
-            this.itemautomerge.Tag = "builder_toggleautomerge";
-            this.itemautomerge.Text = "&Merge Geometry";
-            this.itemautomerge.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.itemzoom5.Name = "itemzoom5";
+            this.itemzoom5.Size = new System.Drawing.Size(156, 22);
+            this.itemzoom5.Tag = "5";
+            this.itemzoom5.Text = "5%";
+            this.itemzoom5.Click += new System.EventHandler(this.itemzoomto_Click);
             // 
-            // itemgridsetup
+            // itemzoomfittoscreen
             // 
-            this.itemgridsetup.Image = global::CodeImp.DoomBuilder.Properties.Resources.Grid2;
-            this.itemgridsetup.Name = "itemgridsetup";
-            this.itemgridsetup.Size = new System.Drawing.Size(163, 22);
-            this.itemgridsetup.Tag = "builder_gridsetup";
-            this.itemgridsetup.Text = "&Grid Setup...";
-            this.itemgridsetup.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.itemzoomfittoscreen.Name = "itemzoomfittoscreen";
+            this.itemzoomfittoscreen.Size = new System.Drawing.Size(156, 22);
+            this.itemzoomfittoscreen.Text = "Fit to screen";
+            this.itemzoomfittoscreen.Click += new System.EventHandler(this.itemzoomfittoscreen_Click);
             // 
-            // itemmapoptions
+            // xposlabel
             // 
-            this.itemmapoptions.Image = global::CodeImp.DoomBuilder.Properties.Resources.Properties;
-            this.itemmapoptions.Name = "itemmapoptions";
-            this.itemmapoptions.Size = new System.Drawing.Size(163, 22);
-            this.itemmapoptions.Tag = "builder_mapoptions";
-            this.itemmapoptions.Text = "Map &Options....";
-            this.itemmapoptions.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.xposlabel.AutoSize = false;
+            this.xposlabel.Name = "xposlabel";
+            this.xposlabel.Size = new System.Drawing.Size(50, 18);
+            this.xposlabel.Text = "0";
+            this.xposlabel.ToolTipText = "Current X, Y coordinates on map";
             // 
-            // itemthingsfilter
+            // yposlabel
+            // 
+            this.yposlabel.AutoSize = false;
+            this.yposlabel.Name = "yposlabel";
+            this.yposlabel.Size = new System.Drawing.Size(50, 18);
+            this.yposlabel.Text = "0";
+            this.yposlabel.ToolTipText = "Current X, Y coordinates on map";
+            // 
+            // panelinfo
             // 
-            this.itemthingsfilter.Image = global::CodeImp.DoomBuilder.Properties.Resources.Filter;
-            this.itemthingsfilter.Name = "itemthingsfilter";
-            this.itemthingsfilter.Size = new System.Drawing.Size(209, 22);
-            this.itemthingsfilter.Tag = "builder_thingsfilterssetup";
-            this.itemthingsfilter.Text = "Configure &Things Filters...";
-            this.itemthingsfilter.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.panelinfo.Controls.Add(this.heightpanel1);
+            this.panelinfo.Controls.Add(this.vertexinfo);
+            this.panelinfo.Controls.Add(this.labelcollapsedinfo);
+            this.panelinfo.Controls.Add(this.buttontoggleinfo);
+            this.panelinfo.Controls.Add(this.modename);
+            this.panelinfo.Controls.Add(this.linedefinfo);
+            this.panelinfo.Controls.Add(this.thinginfo);
+            this.panelinfo.Controls.Add(this.sectorinfo);
+            this.panelinfo.Dock = System.Windows.Forms.DockStyle.Bottom;
+            this.panelinfo.Location = new System.Drawing.Point(26, 564);
+            this.panelinfo.Name = "panelinfo";
+            this.panelinfo.Size = new System.Drawing.Size(986, 106);
+            this.panelinfo.TabIndex = 4;
             // 
-            // itemviewnormal
+            // heightpanel1
             // 
-            this.itemviewnormal.Image = global::CodeImp.DoomBuilder.Properties.Resources.ViewNormal;
-            this.itemviewnormal.Name = "itemviewnormal";
-            this.itemviewnormal.Size = new System.Drawing.Size(209, 22);
-            this.itemviewnormal.Tag = "builder_viewmodenormal";
-            this.itemviewnormal.Text = "&Wireframe";
-            this.itemviewnormal.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.heightpanel1.BackColor = System.Drawing.Color.Navy;
+            this.heightpanel1.ForeColor = System.Drawing.SystemColors.ControlText;
+            this.heightpanel1.Location = new System.Drawing.Point(0, 0);
+            this.heightpanel1.Name = "heightpanel1";
+            this.heightpanel1.Size = new System.Drawing.Size(29, 106);
+            this.heightpanel1.TabIndex = 7;
+            this.heightpanel1.Visible = false;
             // 
-            // itemviewbrightness
+            // vertexinfo
             // 
-            this.itemviewbrightness.Image = global::CodeImp.DoomBuilder.Properties.Resources.ViewBrightness;
-            this.itemviewbrightness.Name = "itemviewbrightness";
-            this.itemviewbrightness.Size = new System.Drawing.Size(209, 22);
-            this.itemviewbrightness.Tag = "builder_viewmodebrightness";
-            this.itemviewbrightness.Text = "&Brightness Levels";
-            this.itemviewbrightness.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.vertexinfo.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.vertexinfo.Location = new System.Drawing.Point(3, 3);
+            this.vertexinfo.MaximumSize = new System.Drawing.Size(10000, 100);
+            this.vertexinfo.MinimumSize = new System.Drawing.Size(100, 100);
+            this.vertexinfo.Name = "vertexinfo";
+            this.vertexinfo.Size = new System.Drawing.Size(310, 100);
+            this.vertexinfo.TabIndex = 1;
+            this.vertexinfo.Visible = false;
             // 
-            // itemviewfloors
+            // labelcollapsedinfo
             // 
-            this.itemviewfloors.Image = global::CodeImp.DoomBuilder.Properties.Resources.ViewTextureFloor;
-            this.itemviewfloors.Name = "itemviewfloors";
-            this.itemviewfloors.Size = new System.Drawing.Size(209, 22);
-            this.itemviewfloors.Tag = "builder_viewmodefloors";
-            this.itemviewfloors.Text = "&Floor Textures";
-            this.itemviewfloors.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.labelcollapsedinfo.AutoSize = true;
+            this.labelcollapsedinfo.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.labelcollapsedinfo.Location = new System.Drawing.Point(2, 2);
+            this.labelcollapsedinfo.Name = "labelcollapsedinfo";
+            this.labelcollapsedinfo.Size = new System.Drawing.Size(137, 13);
+            this.labelcollapsedinfo.TabIndex = 6;
+            this.labelcollapsedinfo.Text = "Collapsed Descriptions";
+            this.labelcollapsedinfo.Visible = false;
             // 
-            // itemviewceilings
+            // buttontoggleinfo
             // 
-            this.itemviewceilings.Image = global::CodeImp.DoomBuilder.Properties.Resources.ViewTextureCeiling;
-            this.itemviewceilings.Name = "itemviewceilings";
-            this.itemviewceilings.Size = new System.Drawing.Size(209, 22);
-            this.itemviewceilings.Tag = "builder_viewmodeceilings";
-            this.itemviewceilings.Text = "&Ceiling Textures";
-            this.itemviewceilings.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.buttontoggleinfo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.buttontoggleinfo.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
+            this.buttontoggleinfo.Font = new System.Drawing.Font("Marlett", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(2)));
+            this.buttontoggleinfo.Location = new System.Drawing.Point(962, 1);
+            this.buttontoggleinfo.Name = "buttontoggleinfo";
+            this.buttontoggleinfo.Size = new System.Drawing.Size(22, 19);
+            this.buttontoggleinfo.TabIndex = 5;
+            this.buttontoggleinfo.TabStop = false;
+            this.buttontoggleinfo.Tag = "builder_toggleinfopanel";
+            this.buttontoggleinfo.Text = "6";
+            this.buttontoggleinfo.UseVisualStyleBackColor = true;
+            this.buttontoggleinfo.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.buttontoggleinfo.MouseUp += new System.Windows.Forms.MouseEventHandler(this.buttontoggleinfo_MouseUp);
             // 
-            // menuzoom
+            // modename
             // 
-            this.menuzoom.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
-            this.item2zoom200,
-            this.item2zoom100,
-            this.item2zoom50,
-            this.item2zoom25,
-            this.item2zoom10,
-            this.item2zoom5});
-            this.menuzoom.Image = global::CodeImp.DoomBuilder.Properties.Resources.Zoom;
-            this.menuzoom.Name = "menuzoom";
-            this.menuzoom.Size = new System.Drawing.Size(209, 22);
-            this.menuzoom.Text = "&Zoom";
+            this.modename.AutoSize = true;
+            this.modename.Font = new System.Drawing.Font("Verdana", 36F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.modename.ForeColor = System.Drawing.SystemColors.GrayText;
+            this.modename.Location = new System.Drawing.Point(12, 20);
+            this.modename.Name = "modename";
+            this.modename.Size = new System.Drawing.Size(244, 59);
+            this.modename.TabIndex = 4;
+            this.modename.Text = "Vertices";
+            this.modename.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            this.modename.UseMnemonic = false;
+            this.modename.Visible = false;
             // 
-            // item2zoom200
+            // linedefinfo
             // 
-            this.item2zoom200.Name = "item2zoom200";
-            this.item2zoom200.Size = new System.Drawing.Size(102, 22);
-            this.item2zoom200.Tag = "200";
-            this.item2zoom200.Text = "200%";
-            this.item2zoom200.Click += new System.EventHandler(this.itemzoomto_Click);
+            this.linedefinfo.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.linedefinfo.Location = new System.Drawing.Point(3, 3);
+            this.linedefinfo.MaximumSize = new System.Drawing.Size(10000, 100);
+            this.linedefinfo.MinimumSize = new System.Drawing.Size(100, 100);
+            this.linedefinfo.Name = "linedefinfo";
+            this.linedefinfo.Size = new System.Drawing.Size(1039, 100);
+            this.linedefinfo.TabIndex = 0;
+            this.linedefinfo.Visible = false;
             // 
-            // item2zoom100
+            // thinginfo
             // 
-            this.item2zoom100.Name = "item2zoom100";
-            this.item2zoom100.Size = new System.Drawing.Size(102, 22);
-            this.item2zoom100.Tag = "100";
-            this.item2zoom100.Text = "100%";
-            this.item2zoom100.Click += new System.EventHandler(this.itemzoomto_Click);
+            this.thinginfo.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.thinginfo.Location = new System.Drawing.Point(3, 3);
+            this.thinginfo.MaximumSize = new System.Drawing.Size(10000, 100);
+            this.thinginfo.MinimumSize = new System.Drawing.Size(100, 100);
+            this.thinginfo.Name = "thinginfo";
+            this.thinginfo.Size = new System.Drawing.Size(639, 100);
+            this.thinginfo.TabIndex = 3;
+            this.thinginfo.Visible = false;
             // 
-            // item2zoom50
+            // sectorinfo
             // 
-            this.item2zoom50.Name = "item2zoom50";
-            this.item2zoom50.Size = new System.Drawing.Size(102, 22);
-            this.item2zoom50.Tag = "50";
-            this.item2zoom50.Text = "50%";
-            this.item2zoom50.Click += new System.EventHandler(this.itemzoomto_Click);
+            this.sectorinfo.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.sectorinfo.Location = new System.Drawing.Point(3, 3);
+            this.sectorinfo.MaximumSize = new System.Drawing.Size(10000, 100);
+            this.sectorinfo.MinimumSize = new System.Drawing.Size(100, 100);
+            this.sectorinfo.Name = "sectorinfo";
+            this.sectorinfo.Size = new System.Drawing.Size(522, 100);
+            this.sectorinfo.TabIndex = 2;
+            this.sectorinfo.Visible = false;
             // 
-            // item2zoom25
+            // redrawtimer
             // 
-            this.item2zoom25.Name = "item2zoom25";
-            this.item2zoom25.Size = new System.Drawing.Size(102, 22);
-            this.item2zoom25.Tag = "25";
-            this.item2zoom25.Text = "25%";
-            this.item2zoom25.Click += new System.EventHandler(this.itemzoomto_Click);
+            this.redrawtimer.Interval = 1;
+            this.redrawtimer.Tick += new System.EventHandler(this.redrawtimer_Tick);
             // 
-            // item2zoom10
+            // display
             // 
-            this.item2zoom10.Name = "item2zoom10";
-            this.item2zoom10.Size = new System.Drawing.Size(102, 22);
-            this.item2zoom10.Tag = "10";
-            this.item2zoom10.Text = "10%";
-            this.item2zoom10.Click += new System.EventHandler(this.itemzoomto_Click);
+            this.display.BackColor = System.Drawing.SystemColors.AppWorkspace;
+            this.display.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
+            this.display.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
+            this.display.CausesValidation = false;
+            this.display.Location = new System.Drawing.Point(373, 141);
+            this.display.Name = "display";
+            this.display.Size = new System.Drawing.Size(542, 307);
+            this.display.TabIndex = 5;
+            this.display.MouseLeave += new System.EventHandler(this.display_MouseLeave);
+            this.display.Paint += new System.Windows.Forms.PaintEventHandler(this.display_Paint);
+            this.display.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(this.display_PreviewKeyDown);
+            this.display.MouseMove += new System.Windows.Forms.MouseEventHandler(this.display_MouseMove);
+            this.display.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.display_MouseDoubleClick);
+            this.display.MouseClick += new System.Windows.Forms.MouseEventHandler(this.display_MouseClick);
+            this.display.MouseDown += new System.Windows.Forms.MouseEventHandler(this.display_MouseDown);
+            this.display.Resize += new System.EventHandler(this.display_Resize);
+            this.display.MouseUp += new System.Windows.Forms.MouseEventHandler(this.display_MouseUp);
+            this.display.MouseEnter += new System.EventHandler(this.display_MouseEnter);
             // 
-            // item2zoom5
+            // processor
             // 
-            this.item2zoom5.Name = "item2zoom5";
-            this.item2zoom5.Size = new System.Drawing.Size(102, 22);
-            this.item2zoom5.Tag = "5";
-            this.item2zoom5.Text = "5%";
-            this.item2zoom5.Click += new System.EventHandler(this.itemzoomto_Click);
+            this.processor.Interval = 10;
+            this.processor.Tick += new System.EventHandler(this.processor_Tick);
             // 
-            // itemscripteditor
+            // statusflasher
             // 
-            this.itemscripteditor.Image = global::CodeImp.DoomBuilder.Properties.Resources.Script2;
-            this.itemscripteditor.Name = "itemscripteditor";
-            this.itemscripteditor.Size = new System.Drawing.Size(209, 22);
-            this.itemscripteditor.Tag = "builder_openscripteditor";
-            this.itemscripteditor.Text = "&Script Editor...";
-            this.itemscripteditor.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.statusflasher.Tick += new System.EventHandler(this.statusflasher_Tick);
             // 
-            // itemshowerrors
+            // statusresetter
             // 
-            this.itemshowerrors.Image = global::CodeImp.DoomBuilder.Properties.Resources.Warning;
-            this.itemshowerrors.Name = "itemshowerrors";
-            this.itemshowerrors.Size = new System.Drawing.Size(196, 22);
-            this.itemshowerrors.Tag = "builder_showerrors";
-            this.itemshowerrors.Text = "&Errors and Warnings...";
-            this.itemshowerrors.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.statusresetter.Tick += new System.EventHandler(this.statusresetter_Tick);
             // 
-            // itemtestmap
+            // dockersspace
             // 
-            this.itemtestmap.Image = global::CodeImp.DoomBuilder.Properties.Resources.Test;
-            this.itemtestmap.Name = "itemtestmap";
-            this.itemtestmap.Size = new System.Drawing.Size(196, 22);
-            this.itemtestmap.Tag = "builder_testmap";
-            this.itemtestmap.Text = "&Test Map";
-            this.itemtestmap.Click += new System.EventHandler(this.InvokeTaggedAction);
+            this.dockersspace.Dock = System.Windows.Forms.DockStyle.Left;
+            this.dockersspace.Location = new System.Drawing.Point(0, 49);
+            this.dockersspace.Name = "dockersspace";
+            this.dockersspace.Size = new System.Drawing.Size(26, 621);
+            this.dockersspace.TabIndex = 6;
             // 
-            // itemhelprefmanual
+            // dockerspanel
             // 
-            this.itemhelprefmanual.Image = global::CodeImp.DoomBuilder.Properties.Resources.Help;
-            this.itemhelprefmanual.Name = "itemhelprefmanual";
-            this.itemhelprefmanual.Size = new System.Drawing.Size(203, 22);
-            this.itemhelprefmanual.Text = "Reference &Manual";
-            this.itemhelprefmanual.Click += new System.EventHandler(this.itemhelprefmanual_Click);
+            this.dockerspanel.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.dockerspanel.Location = new System.Drawing.Point(62, 67);
+            this.dockerspanel.Name = "dockerspanel";
+            this.dockerspanel.Size = new System.Drawing.Size(236, 467);
+            this.dockerspanel.TabIndex = 7;
+            this.dockerspanel.TabStop = false;
+            this.dockerspanel.UserResize += new System.EventHandler(this.dockerspanel_UserResize);
+            this.dockerspanel.Collapsed += new System.EventHandler(this.LoseFocus);
+            this.dockerspanel.MouseContainerEnter += new System.EventHandler(this.dockerspanel_MouseContainerEnter);
             // 
-            // itemhelpeditmode
+            // dockerscollapser
             // 
-            this.itemhelpeditmode.Image = global::CodeImp.DoomBuilder.Properties.Resources.Question;
-            this.itemhelpeditmode.Name = "itemhelpeditmode";
-            this.itemhelpeditmode.Size = new System.Drawing.Size(203, 22);
-            this.itemhelpeditmode.Text = "About this &Editing Mode";
-            this.itemhelpeditmode.Click += new System.EventHandler(this.itemhelpeditmode_Click);
+            this.dockerscollapser.Interval = 200;
+            this.dockerscollapser.Tick += new System.EventHandler(this.dockerscollapser_Tick);
             // 
             // MainForm
             // 
diff --git a/Source/Core/Windows/MainForm.cs b/Source/Core/Windows/MainForm.cs
index ad12e9ef64815ea8ce923261ca29fbac114dac0b..0a8632073186876dd265dc20c3be7b7959b5caba 100644
--- a/Source/Core/Windows/MainForm.cs
+++ b/Source/Core/Windows/MainForm.cs
@@ -1778,30 +1778,26 @@ namespace CodeImp.DoomBuilder.Windows
 
         //mxd
         public void UpdateGZDoomPannel() {
-            if (General.Settings.GZToolbarGZDoom) {
-                buttontogglemodels.Checked = General.Settings.GZDrawModels;
-                buttonselectedmodelsonly.Checked = General.Settings.GZDrawSelectedModelsOnly;
-                buttontoggledynlight.Checked = General.Settings.GZDrawLights;
-                buttontoggleanimatedlight.Checked = General.Settings.GZAnimateLights;
+            if (General.Map != null) {
+                buttontogglemodels.Enabled = true;
+                buttonselectedmodelsonly.Enabled = true;
+                buttontoggledynlight.Enabled = true;
+                buttontoggleanimatedlight.Enabled = true;
+
+                if (General.Settings.GZToolbarGZDoom) {
+                    buttontogglemodels.Checked = General.Settings.GZDrawModels;
+                    buttonselectedmodelsonly.Checked = General.Settings.GZDrawSelectedModelsOnly;
+                    buttontoggledynlight.Checked = General.Settings.GZDrawLights;
+                    buttontoggleanimatedlight.Checked = General.Settings.GZAnimateLights;
+                }
+            } else {
+                buttontogglemodels.Enabled = false;
+                buttonselectedmodelsonly.Enabled = false;
+                buttontoggledynlight.Enabled = false;
+                buttontoggleanimatedlight.Enabled = false;
             }
         }
 
-        private void buttontoggledynlight_Click(object sender, EventArgs e) {
-            GZBuilder.GZGeneral.ToggleLights();
-        }
-
-        private void buttontoggleanimatedlight_Click(object sender, EventArgs e) {
-            GZBuilder.GZGeneral.ToggleLightsAnimation();
-        }
-
-        private void buttontogglemodels_Click(object sender, EventArgs e) {
-            GZBuilder.GZGeneral.ToggleModels();
-        }
-
-        private void buttonselectedmodelsonly_Click(object sender, EventArgs e) {
-            GZBuilder.GZGeneral.ToggleDrawSelectedModelsOnly();
-        }
-
 		#endregion
 
 		#region ================== Menus
@@ -2762,6 +2758,11 @@ namespace CodeImp.DoomBuilder.Windows
 		#endregion
 
 		#region ================== Dockers
+        //mxd. used to add a docker from DoomBuilder's core code. 
+        internal void addDocker(Docker d) {
+            d.MakeFullName("gzdoombuilder");
+            dockerspanel.Add(d);
+        }
 		
 		// This adds a docker
 		public void AddDocker(Docker d)
@@ -2786,6 +2787,13 @@ namespace CodeImp.DoomBuilder.Windows
 			
 			return dockerspanel.Remove(d);
 		}
+
+        //mxd
+        internal bool selectDocker(Docker d) {
+            d.MakeFullName("gzdoombuilder");
+            ReleaseAllKeys();
+            return dockerspanel.SelectDocker(d);
+        }
 		
 		// This selects a docker
 		public bool SelectDocker(Docker d)
diff --git a/Source/Core/Windows/MainForm.resx b/Source/Core/Windows/MainForm.resx
index 43630aafcf0c255ccc6852cb3f4680ca30593aef..44cd10d30d8ea8fdb02ad1e7a95f681bc615606e 100644
--- a/Source/Core/Windows/MainForm.resx
+++ b/Source/Core/Windows/MainForm.resx
@@ -126,6 +126,12 @@
   <metadata name="toolStripSeparator12.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>False</value>
   </metadata>
+  <metadata name="toolStripMenuItem4.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </metadata>
+  <metadata name="toolStripSeparator2.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </metadata>
   <metadata name="menumain.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
@@ -151,22 +157,16 @@
     <value>
         iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
         YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAClSURBVDhPY2CgJnjdLnGRFIxiN0wjMQ7CUAsSAGmE0fgM
-        wVD7rkP6KykYZjjcMpBmDEEcTsCqllgD5igq/gepBdEo3iXFgOfNkr9ABuQXljeR7AWQRrwGgBQgY1gw
+        wVD7rkP6KykYZjjcMpBmDEEcTsCqllgD5igq/gepBdEo3iXFgKf1kr9ABuQXljeR7AWQRrwGgBQgY1gw
         IIvhNADmLGw0yCCQk/G6AJ8BIM0gQwgasLzG/wW6QTCNMG/AvACLCbA3QbEAClGYTeg0zAsgcZABMLUw
-        dWADSMHE5BWS1AAAQvokPWS9KEkAAAAASUVORK5CYII=
+        dWADSMHE5BWS1AAACnwkE01c7eYAAAAASUVORK5CYII=
 </value>
   </data>
-  <metadata name="statusbar.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
-    <value>218, 17</value>
-  </metadata>
   <metadata name="statusbar.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="toolStripMenuItem4.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
-    <value>False</value>
-  </metadata>
-  <metadata name="toolStripSeparator2.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
-    <value>False</value>
+  <metadata name="statusbar.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>218, 17</value>
   </metadata>
   <metadata name="panelinfo.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs
index f3e60497523ce6aeacd071b2f931fce327f80b3f..af33cf6365ea111c4457fdb6e49978ba4351ec2d 100644
--- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs
@@ -240,7 +240,16 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		// This forces to rebuild the whole thing
 		public void Rebuild()
 		{
-			// Setup visual thing
+            // Find thing information //mxd. I think it should be here
+            info = General.Map.Data.GetThingInfo(Thing.Type);
+
+            // Find sprite texture //mxd. and this 
+            if (info.Sprite.Length > 0) {
+                sprite = General.Map.Data.GetSpriteImage(info.Sprite);
+                if (sprite != null) sprite.AddReference();
+            }
+            
+            // Setup visual thing
 			Setup();
 		}
 		
diff --git a/Source/Plugins/ColorPicker/BuilderPlug.cs b/Source/Plugins/ColorPicker/BuilderPlug.cs
new file mode 100644
index 0000000000000000000000000000000000000000..be19928d89abd04d069738e5f4c0011c92d4766c
--- /dev/null
+++ b/Source/Plugins/ColorPicker/BuilderPlug.cs
@@ -0,0 +1,143 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+
+using CodeImp.DoomBuilder;
+using CodeImp.DoomBuilder.Editing;
+using CodeImp.DoomBuilder.Map;
+using CodeImp.DoomBuilder.Windows;
+using CodeImp.DoomBuilder.Plugins;
+using CodeImp.DoomBuilder.Actions;
+using CodeImp.DoomBuilder.VisualModes;
+
+using CodeImp.DoomBuilder.ColorPicker.Windows;
+
+namespace CodeImp.DoomBuilder.ColorPicker
+{
+    public class BuilderPlug : Plug
+    {
+        private static BuilderPlug me;
+        public static BuilderPlug Me { get { return me; } }
+
+        public override string Name { get { return "Color Picker"; } }
+
+        private IColorPicker form;
+        private ToolsForm toolsform;
+
+        private string currentModeName = "";
+
+        private Point formLocation; //used to keep forms location constant
+
+        public override void OnInitialize() {
+            //yeeees, I used string to store version number before 1.05...
+            if (GZBuilder.GZGeneral.Version.GetType().Name != "Single") {
+                General.ErrorLogger.Add(ErrorType.Error, "ColorPicker plugin: GZDoomBuilder 1.05 or later required!");
+                return;
+            }
+            
+            base.OnInitialize();
+            me = this;
+
+            General.Actions.BindMethods(this);
+        }
+
+        public override void OnMapOpenEnd() {
+            if (toolsform == null)
+                toolsform = new ToolsForm();
+
+            //dbg
+            /*CodeImp.DoomBuilder.Rendering.PixelColor c = new CodeImp.DoomBuilder.Rendering.PixelColor(255, 255, 64, 3);
+            int ic = c.ToColorRef();
+
+            CodeImp.DoomBuilder.Rendering.PixelColor c2 = CodeImp.DoomBuilder.Rendering.PixelColor.FromInt(ic);
+
+            GZBuilder.GZGeneral.Trace("c: "+c.r+","+c.g+","+c.b);
+            GZBuilder.GZGeneral.Trace("ic: " + ic);
+            GZBuilder.GZGeneral.Trace("c2: " + c2.r + "," + c2.g + "," + c2.b);*/
+        }
+
+        public override void OnMapNewEnd() {
+            OnMapOpenEnd();
+        }
+
+        public override void Dispose() {
+            base.Dispose();
+            General.Actions.UnbindMethods(this);
+
+            if (form != null) form.Close();
+            form = null;
+
+            if (toolsform != null) toolsform.Dispose();
+            toolsform = null;
+        }
+
+        [BeginAction("togglelightpannel")]
+        private void toggleLightPannel() {
+            if (General.Editing.Mode == null)
+                return;
+
+            currentModeName = General.Editing.Mode.GetType().Name;
+            bool udmf = General.Map.Config.FormatInterface == "UniversalMapSetIO";
+
+            //display one of colorPickers or tell the user why we can't do that
+            if (currentModeName == "ThingsMode") {
+                if(General.Map.Map.SelectedThingsCount == 0){
+                    Plug.DisplayStatus(StatusType.Warning, "Select some lights first!");
+                    return;
+                }
+                form = new LightColorPicker();
+
+            } else if (currentModeName == "SectorsMode") {
+                if (udmf) {
+                    if (General.Map.Map.SelectedSectorsCount == 0) {
+                        Plug.DisplayStatus(StatusType.Warning, "Select some sectors first!");
+                        return;
+                    }
+                    form = new SectorColorPicker();
+                } else {
+                    Plug.DisplayStatus(StatusType.Warning, "Sector colors can only be set if map is in UDMF format!");
+                    return;
+                }
+
+            } else if (currentModeName == "BaseVisualMode") {
+                //nothing selected in visual mode?
+                if ( ((VisualMode)General.Editing.Mode).SelectedVisualThings.Count == 0 ) {
+                    //check sectors
+                    if (udmf && General.Map.Map.SelectedSectorsCount > 0) {
+                        form = new SectorColorPicker();
+                    } else {
+                        Plug.DisplayStatus(StatusType.Warning, "Select some lights " + (udmf ? "or sectors " : "") + "first!");
+                        return;
+                    }
+                } else {
+                    form = new LightColorPicker();
+                }
+            } else { //wrong mode
+                Plug.DisplayStatus(StatusType.Warning, "Switch to" + (udmf ? " Sectors," : "") + " Things or GZDoom Visual Mode first!");
+                return;
+            }
+
+            if (form.Setup(currentModeName)) {
+                if (formLocation.X == 0 && formLocation.Y == 0) {
+                    Size displaySize = Plug.DisplaySize;
+                    Point displayLocation = Plug.DisplayLocationAbs;
+                    formLocation = new Point(displayLocation.X + displaySize.Width - form.Width - 16, displayLocation.Y + 32);
+                } 
+                form.Location = formLocation;
+                form.FormClosed += new FormClosedEventHandler(form_FormClosed);
+                form.ShowDialog(Form.ActiveForm);
+            } else {
+                form.Dispose();
+                form = null;
+            }
+        }
+
+        private void form_FormClosed(object sender, FormClosedEventArgs e) {
+            formLocation = form.Location;
+            form.Dispose();
+            form = null;
+        }
+    }
+}
diff --git a/Source/Plugins/ColorPicker/ColorChangedEventArgs.cs b/Source/Plugins/ColorPicker/ColorChangedEventArgs.cs
new file mode 100644
index 0000000000000000000000000000000000000000..8f9320661b008760dd9e8eab36a7724f49223204
--- /dev/null
+++ b/Source/Plugins/ColorPicker/ColorChangedEventArgs.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace CodeImp.DoomBuilder.ColorPicker
+{
+    public class ColorChangedEventArgs : EventArgs {
+        private ColorHandler.RGB mRGB;
+        private ColorHandler.HSV mHSV;
+
+        public ColorChangedEventArgs(ColorHandler.RGB RGB, ColorHandler.HSV HSV) {
+            mRGB = RGB;
+            mHSV = HSV;
+        }
+
+        public ColorHandler.RGB RGB { get { return mRGB; } }
+        public ColorHandler.HSV HSV { get { return mHSV; } }
+    }
+}
\ No newline at end of file
diff --git a/Source/Plugins/ColorPicker/ColorHandler.cs b/Source/Plugins/ColorPicker/ColorHandler.cs
new file mode 100644
index 0000000000000000000000000000000000000000..5fcd0243354e98d08c27fdbf62fbb33f13c63e86
--- /dev/null
+++ b/Source/Plugins/ColorPicker/ColorHandler.cs
@@ -0,0 +1,211 @@
+using System;
+using System.Drawing;
+
+namespace CodeImp.DoomBuilder.ColorPicker
+{
+    public class ColorHandler {
+        // Handle conversions between RGB and HSV    
+        // (and Color types, as well).
+        public struct RGB {
+            // All values are between 0 and 255.
+            public int Red;
+            public int Green;
+            public int Blue;
+
+            public RGB(int R, int G, int B) {
+                Red = R;
+                Green = G;
+                Blue = B;
+            }
+
+        }
+
+        public struct HSV {
+            // All values are between 0 and 255.
+            public int Hue;
+            public int Saturation;
+            public int value;
+
+            public HSV(int H, int S, int V) {
+                Hue = H;
+                Saturation = S;
+                value = V;
+            }
+
+            public override string ToString() {
+                return String.Format("({0}, {1}, {2})", Hue, Saturation, value);
+            }
+        }
+
+        public static RGB HSVtoRGB(int H, int S, int V) {
+            // H, S, and V must all be between 0 and 255.
+            return HSVtoRGB(new HSV(H, S, V));
+        }
+
+        public static Color HSVtoColor(HSV hsv) {
+            RGB RGB = HSVtoRGB(hsv);
+            return Color.FromArgb(RGB.Red, RGB.Green, RGB.Blue);
+        }
+
+        public static Color HSVtoColor(int H, int S, int V) {
+            return HSVtoColor(new HSV(H, S, V));
+        }
+
+        public static Color RGBtoColor(RGB rgb) {
+            return Color.FromArgb(rgb.Red, rgb.Green, rgb.Blue);
+        }
+
+        public static RGB HSVtoRGB(HSV HSV) {
+            // HSV contains values scaled as in the color wheel:
+            // that is, all from 0 to 255. 
+
+            // for ( this code to work, HSV.Hue needs
+            // to be scaled from 0 to 360 (it//s the angle of the selected
+            // point within the circle). HSV.Saturation and HSV.value must be 
+            // scaled to be between 0 and 1.
+
+            double h;
+            double s;
+            double v;
+
+            double r = 0;
+            double g = 0;
+            double b = 0;
+
+            // Scale Hue to be between 0 and 360. Saturation
+            // and value scale to be between 0 and 1.
+            h = ((double)HSV.Hue / 255 * 360) % 360;
+            s = (double)HSV.Saturation / 255;
+            v = (double)HSV.value / 255;
+
+            if (s == 0) {
+                // If s is 0, all colors are the same.
+                // This is some flavor of gray.
+                r = v;
+                g = v;
+                b = v;
+            } else {
+                double p;
+                double q;
+                double t;
+
+                double fractionalSector;
+                int sectorNumber;
+                double sectorPos;
+
+                // The color wheel consists of 6 sectors.
+                // Figure out which sector you//re in.
+                sectorPos = h / 60;
+                sectorNumber = (int)(Math.Floor(sectorPos));
+
+                // get the fractional part of the sector.
+                // That is, how many degrees into the sector
+                // are you?
+                fractionalSector = sectorPos - sectorNumber;
+
+                // Calculate values for the three axes
+                // of the color. 
+                p = v * (1 - s);
+                q = v * (1 - (s * fractionalSector));
+                t = v * (1 - (s * (1 - fractionalSector)));
+
+                // Assign the fractional colors to r, g, and b
+                // based on the sector the angle is in.
+                switch (sectorNumber) {
+                    case 0:
+                        r = v;
+                        g = t;
+                        b = p;
+                        break;
+
+                    case 1:
+                        r = q;
+                        g = v;
+                        b = p;
+                        break;
+
+                    case 2:
+                        r = p;
+                        g = v;
+                        b = t;
+                        break;
+
+                    case 3:
+                        r = p;
+                        g = q;
+                        b = v;
+                        break;
+
+                    case 4:
+                        r = t;
+                        g = p;
+                        b = v;
+                        break;
+
+                    case 5:
+                        r = v;
+                        g = p;
+                        b = q;
+                        break;
+                }
+            }
+            // return an RGB structure, with values scaled
+            // to be between 0 and 255.
+            return new RGB((int)(r * 255), (int)(g * 255), (int)(b * 255));
+        }
+
+        public static HSV RGBtoHSV(RGB RGB) {
+            // In this function, R, G, and B values must be scaled 
+            // to be between 0 and 1.
+            // HSV.Hue will be a value between 0 and 360, and 
+            // HSV.Saturation and value are between 0 and 1.
+            // The code must scale these to be between 0 and 255 for
+            // the purposes of this application.
+
+            double min;
+            double max;
+            double delta;
+
+            double r = (double)RGB.Red / 255;
+            double g = (double)RGB.Green / 255;
+            double b = (double)RGB.Blue / 255;
+
+            double h;
+            double s;
+            double v;
+
+            min = Math.Min(Math.Min(r, g), b);
+            max = Math.Max(Math.Max(r, g), b);
+            v = max;
+            delta = max - min;
+            if (max == 0 || delta == 0) {
+                // R, G, and B must be 0, or all the same. In this case, S is 0, and H is undefined.
+                // Using H = 0 is as good as any...
+                s = 0;
+                h = 0;
+            } else {
+                s = delta / max;
+                if (r == max) {
+                    // Between Yellow and Magenta
+                    h = (g - b) / delta;
+                } else if (g == max) {
+                    // Between Cyan and Yellow
+                    h = 2 + (b - r) / delta;
+                } else {
+                    // Between Magenta and Cyan
+                    h = 4 + (r - g) / delta;
+                }
+
+            }
+            // Scale h to be between 0 and 360. 
+            // This may require adding 360, if the value is negative.
+            h *= 60;
+            if (h < 0) {
+                h += 360;
+            }
+
+            // Scale to the requirements of this application. All values are between 0 and 255.
+            return new HSV((int)(h / 360 * 255), (int)(s * 255), (int)(v * 255));
+        }
+    }
+}
diff --git a/Source/Plugins/ColorPicker/ColorPicker.csproj b/Source/Plugins/ColorPicker/ColorPicker.csproj
new file mode 100644
index 0000000000000000000000000000000000000000..cb0dee549db1ff9328dc617df6e85906fb93925f
--- /dev/null
+++ b/Source/Plugins/ColorPicker/ColorPicker.csproj
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{A4761900-0EA3-4FE4-A919-847FD5080EFC}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>CodeImp.DoomBuilder.ColorPicker</RootNamespace>
+    <AssemblyName>ColorPicker</AssemblyName>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\..\..\Build\Plugins\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>
+    </DocumentationFile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>..\..\..\Build\Plugins\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="Trackbar, Version=1.0.2486.37933, Culture=neutral, PublicKeyToken=503bf28f63ad27b4">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\Build\Trackbar.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="BuilderPlug.cs" />
+    <Compile Include="ColorChangedEventArgs.cs" />
+    <Compile Include="ColorHandler.cs" />
+    <Compile Include="ColorPickerType.cs" />
+    <Compile Include="ColorWheel.cs" />
+    <Compile Include="Controls\ColorPickerControl.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="Controls\ColorPickerControl.designer.cs">
+      <DependentUpon>ColorPickerControl.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Controls\ColorPickerSlider.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="Controls\ColorPickerSlider.Designer.cs">
+      <DependentUpon>ColorPickerSlider.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Controls\ColorPickerSliderEventArgs.cs" />
+    <Compile Include="IColorPicker.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs">
+    </Compile>
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+    <Compile Include="Windows\LightColorPicker.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Windows\LightColorPicker.Designer.cs">
+      <DependentUpon>LightColorPicker.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Windows\SectorColorPicker.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Windows\SectorColorPicker.Designer.cs">
+      <DependentUpon>SectorColorPicker.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Windows\ToolForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Windows\ToolForm.Designer.cs">
+      <DependentUpon>ToolForm.cs</DependentUpon>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Controls\ColorPickerControl.resx">
+      <DependentUpon>ColorPickerControl.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Windows\LightColorPicker.resx">
+      <DependentUpon>LightColorPicker.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Windows\ToolForm.resx">
+      <DependentUpon>ToolForm.cs</DependentUpon>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\Core\Builder.csproj">
+      <Project>{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}</Project>
+      <Name>Builder</Name>
+      <Private>False</Private>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Controls\ColorPickerSlider.resx">
+      <DependentUpon>ColorPickerSlider.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Resources\Actions.cfg" />
+    <EmbeddedResource Include="Windows\SectorColorPicker.resx">
+      <DependentUpon>SectorColorPicker.cs</DependentUpon>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\cp.png" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/Source/Plugins/ColorPicker/ColorPicker.suo b/Source/Plugins/ColorPicker/ColorPicker.suo
new file mode 100644
index 0000000000000000000000000000000000000000..755f472b6f79c01dfdcda32f0cd5383d157ada20
Binary files /dev/null and b/Source/Plugins/ColorPicker/ColorPicker.suo differ
diff --git a/Source/Plugins/ColorPicker/ColorPickerType.cs b/Source/Plugins/ColorPicker/ColorPickerType.cs
new file mode 100644
index 0000000000000000000000000000000000000000..bd31b8e811e7f69602f6c0e6354062b91780ae7b
--- /dev/null
+++ b/Source/Plugins/ColorPicker/ColorPickerType.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace CodeImp.DoomBuilder.ColorPicker {
+    public enum ColorPickerType : int {
+        CP_LIGHT = 1,
+        CP_SECTOR = 2
+    }
+}
diff --git a/Source/Plugins/ColorPicker/ColorWheel.cs b/Source/Plugins/ColorPicker/ColorWheel.cs
new file mode 100644
index 0000000000000000000000000000000000000000..8eb5a4a01d74ff860d123d66b7675e9b7f71cc35
--- /dev/null
+++ b/Source/Plugins/ColorPicker/ColorWheel.cs
@@ -0,0 +1,468 @@
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+
+namespace CodeImp.DoomBuilder.ColorPicker {
+    public class ColorWheel : IDisposable {
+
+        // These resources should be disposed
+        // of when you're done with them.
+        private Graphics g;
+        private Region colorRegion;
+        private Region brightnessRegion;
+        private Bitmap colorImage;
+
+        public delegate void ColorChangedEventHandler(object sender, ColorChangedEventArgs e);
+        public ColorChangedEventHandler ColorChanged;
+
+        // Keep track of the current mouse state. 
+        public enum MouseState {
+            MouseUp,
+            ClickOnColor,
+            DragInColor,
+            ClickOnBrightness,
+            DragInBrightness,
+            ClickOutsideRegion,
+            DragOutsideRegion,
+        }
+        private MouseState currentState = MouseState.MouseUp;
+
+        // The code needs to convert back and forth between 
+        // degrees and radians. There are 2*PI radians in a 
+        // full circle, and 360 degrees. This constant allows
+        // you to convert back and forth.
+        private const double DEGREES_PER_RADIAN = 180.0 / Math.PI;
+
+        // COLOR_COUNT represents the number of distinct colors
+        // used to create the circular gradient. Its value 
+        // is somewhat arbitrary -- change this to 6, for 
+        // example, to see what happens. 1536 (6 * 256) seems 
+        // a good compromise -- it's enough to get a full 
+        // range of colors, but it doesn't overwhelm the processor
+        // attempting to generate the image. The color wheel
+        // contains 6 sections, and each section displays 
+        // 256 colors. Seems like a reasonable compromise.
+        private const int COLOR_COUNT = 6 * 256;
+
+        private Point centerPoint;
+        private int radius;
+
+        private Rectangle colorRectangle;
+        private Rectangle brightnessRectangle;
+        private int brightnessX;
+        private double brightnessScaling;
+
+        // selectedColor is the actual value selected by the user. fullColor is the same color, 
+        // with its brightness set to 255.
+        private Color selectedColor = Color.White;
+        private Color fullColor;
+
+        private ColorHandler.RGB RGB;
+        private ColorHandler.HSV HSV;
+
+        // Locations for the two "pointers" on the form.
+        private Point colorPoint;
+        private Point brightnessPoint;
+
+        private int brightness;
+        private int brightnessMin;
+        private int brightnessMax;
+
+        public Color Color { get { return selectedColor; } }
+
+        public ColorWheel(Rectangle colorRectangle, Rectangle brightnessRectangle) {
+
+            // Caller must provide locations for color wheel
+            // (colorRectangle), brightness "strip" (brightnessRectangle)
+            // and location to display selected color (selectedColorRectangle).
+
+            using (GraphicsPath path = new GraphicsPath()) {
+                // Store away locations for later use. 
+                this.colorRectangle = colorRectangle;
+                this.brightnessRectangle = brightnessRectangle;
+                //this.selectedColorRectangle = selectedColorRectangle;
+
+                // Calculate the center of the circle.
+                // Start with the location, then offset
+                // the point by the radius.
+                // Use the smaller of the width and height of
+                // the colorRectangle value.
+                this.radius = (int)Math.Min(colorRectangle.Width, colorRectangle.Height) / 2;
+                this.centerPoint = colorRectangle.Location;
+                this.centerPoint.Offset(radius, radius);
+
+                // Start the pointer in the center.
+                this.colorPoint = this.centerPoint;
+
+                // Create a region corresponding to the color circle.
+                // Code uses this later to determine if a specified
+                // point is within the region, using the IsVisible 
+                // method.
+                path.AddEllipse(colorRectangle);
+                colorRegion = new Region(path);
+
+                // set { the range for the brightness selector.
+                this.brightnessMin = this.brightnessRectangle.Top;
+                this.brightnessMax = this.brightnessRectangle.Bottom;
+
+                // Create a region corresponding to the
+                // brightness rectangle, with a little extra 
+                // "breathing room". 
+
+                path.AddRectangle(new Rectangle(brightnessRectangle.Left, brightnessRectangle.Top - 10, brightnessRectangle.Width + 10, brightnessRectangle.Height + 20));
+                // Create region corresponding to brightness
+                // rectangle. Later code uses this to 
+                // determine if a specified point is within
+                // the region, using the IsVisible method.
+                brightnessRegion = new Region(path);
+
+                // Set the location for the brightness indicator "marker".
+                // Also calculate the scaling factor, scaling the height
+                // to be between 0 and 255. 
+                brightnessX = brightnessRectangle.Left + brightnessRectangle.Width;
+                brightnessScaling = (double)255 / (brightnessMax - brightnessMin);
+
+                // Calculate the location of the brightness
+                // pointer. Assume it's at the highest position.
+                brightnessPoint = new Point(brightnessX, brightnessMax);
+
+                // Create the bitmap that contains the circular gradient.
+                CreateGradient();
+            }
+        }
+
+        protected void OnColorChanged(ColorHandler.RGB RGB, ColorHandler.HSV HSV) {
+            ColorChangedEventArgs e = new ColorChangedEventArgs(RGB, HSV);
+            ColorChanged(this, e);
+        }
+
+        void IDisposable.Dispose() {
+            // Dispose of graphic resources
+            if (colorImage != null)
+                colorImage.Dispose();
+            if (colorRegion != null)
+                colorRegion.Dispose();
+            if (brightnessRegion != null)
+                brightnessRegion.Dispose();
+            if (g != null)
+                g.Dispose();
+        }
+
+        public void SetMouseUp() {
+            // Indicate that the user has
+            // released the mouse.
+            currentState = MouseState.MouseUp;
+        }
+
+        public void Draw(Graphics g, ColorHandler.RGB RGB) {
+            // Given RGB values, calculate HSV and then update the screen.
+            this.g = g;
+            this.HSV = ColorHandler.RGBtoHSV(RGB);
+            CalcCoordsAndUpdate(this.HSV);
+            UpdateDisplay();
+        }
+
+        public void Draw(Graphics g, Point mousePoint) {
+            // You've moved the mouse. 
+            // Now update the screen to match.
+            double distance;
+            int degrees;
+            Point delta;
+            Point newColorPoint;
+            Point newBrightnessPoint;
+            Point newPoint;
+
+            // Keep track of the previous color pointer point, 
+            // so you can put the mouse there in case the 
+            // user has clicked outside the circle.
+            newColorPoint = colorPoint;
+            newBrightnessPoint = brightnessPoint;
+
+            // Store this away for later use.
+            this.g = g;
+
+            if (currentState == MouseState.MouseUp) {
+                if (!mousePoint.IsEmpty) {
+                    if (colorRegion.IsVisible(mousePoint)) {
+                        // Is the mouse point within the color circle?
+                        // If so, you just clicked on the color wheel.
+                        currentState = MouseState.ClickOnColor;
+                    } else if (brightnessRegion.IsVisible(mousePoint)) {
+                        // Is the mouse point within the brightness area?
+                        // You clicked on the brightness area.
+                        currentState = MouseState.ClickOnBrightness;
+                    } else {
+                        // Clicked outside the color and the brightness
+                        // regions. In that case, just put the 
+                        // pointers back where they were.
+                        currentState = MouseState.ClickOutsideRegion;
+                    }
+                }
+            }
+
+            switch (currentState) {
+                case MouseState.ClickOnBrightness:
+                case MouseState.DragInBrightness:
+                    // Calculate new color information
+                    // based on the brightness, which may have changed.
+                    newPoint = mousePoint;
+                    if (newPoint.Y < brightnessMin) {
+                        newPoint.Y = brightnessMin;
+                    } else if (newPoint.Y > brightnessMax) {
+                        newPoint.Y = brightnessMax;
+                    }
+                    newBrightnessPoint = new Point(brightnessX, newPoint.Y);
+                    brightness = (int)((brightnessMax - newPoint.Y) * brightnessScaling);
+                    HSV.value = brightness;
+                    RGB = ColorHandler.HSVtoRGB(HSV);
+                    break;
+
+                case MouseState.ClickOnColor:
+                case MouseState.DragInColor:
+                    // Calculate new color information
+                    // based on selected color, which may have changed.
+                    newColorPoint = mousePoint;
+
+                    // Calculate x and y distance from the center,
+                    // and then calculate the angle corresponding to the
+                    // new location.
+                    delta = new Point(
+                        mousePoint.X - centerPoint.X, mousePoint.Y - centerPoint.Y);
+                    degrees = CalcDegrees(delta);
+
+                    // Calculate distance from the center to the new point 
+                    // as a fraction of the radius. Use your old friend, 
+                    // the Pythagorean theorem, to calculate this value.
+                    distance = Math.Sqrt(delta.X * delta.X + delta.Y * delta.Y) / radius;
+
+                    if (currentState == MouseState.DragInColor) {
+                        if (distance > 1) {
+                            // Mouse is down, and outside the circle, but you 
+                            // were previously dragging in the color circle. 
+                            // What to do?
+                            // In that case, move the point to the edge of the 
+                            // circle at the correct angle.
+                            distance = 1;
+                            newColorPoint = GetPoint(degrees, radius, centerPoint);
+                        }
+                    }
+
+                    // Calculate the new HSV and RGB values.
+                    HSV.Hue = (int)(degrees * 255 / 360);
+                    HSV.Saturation = (int)(distance * 255);
+                    HSV.value = brightness;
+                    RGB = ColorHandler.HSVtoRGB(HSV);
+                    fullColor = ColorHandler.HSVtoColor(HSV.Hue, HSV.Saturation, 255);
+                    break;
+            }
+            selectedColor = ColorHandler.HSVtoColor(HSV);
+
+            // Raise an event back to the parent form,
+            // so the form can update any UI it's using 
+            // to display selected color values.
+            OnColorChanged(RGB, HSV);
+
+            // On the way out, set the new state.
+            switch (currentState) {
+                case MouseState.ClickOnBrightness:
+                    currentState = MouseState.DragInBrightness;
+                    break;
+                case MouseState.ClickOnColor:
+                    currentState = MouseState.DragInColor;
+                    break;
+                case MouseState.ClickOutsideRegion:
+                    currentState = MouseState.DragOutsideRegion;
+                    break;
+            }
+
+            // Store away the current points for next time.
+            colorPoint = newColorPoint;
+            brightnessPoint = newBrightnessPoint;
+
+            // Draw the gradients and points. 
+            UpdateDisplay();
+        }
+
+        private Point CalcBrightnessPoint(int brightness) {
+            // Take the value for brightness (0 to 255), scale to the 
+            // scaling used in the brightness bar, then add the value 
+            // to the bottom of the bar. return the correct point at which 
+            // to display the brightness pointer.
+            return new Point(brightnessX, (int)(brightnessMax - brightness / brightnessScaling));
+        }
+
+        /*public void SetColor(Color c) {
+            fullColor = c;
+            UpdateDisplay();
+        }*/
+
+        private void UpdateDisplay() {
+            // Update the gradients, and place the pointers correctly based on colors and 
+            // brightness.
+            CreateGradient();
+
+            using (Brush selectedBrush = new SolidBrush(selectedColor)) {
+                // Draw the saved color wheel image.
+                g.DrawImage(colorImage, colorRectangle);
+
+                // Draw the "brightness" rectangle.
+                DrawLinearGradient(fullColor);
+                // Draw the two pointers.
+                DrawColorPointer(colorPoint);
+                DrawBrightnessPointer(brightnessPoint);
+            }
+        }
+
+        private void CalcCoordsAndUpdate(ColorHandler.HSV HSV) {
+            // Convert color to real-world coordinates and then calculate
+            // the various points. HSV.Hue represents the degrees (0 to 360), 
+            // HSV.Saturation represents the radius. 
+            // This procedure doesn't draw anything--it simply 
+            // updates class-level variables. The UpdateDisplay
+            // procedure uses these values to update the screen.
+
+            // Given the angle (HSV.Hue), and distance from 
+            // the center (HSV.Saturation), and the center, 
+            // calculate the point corresponding to 
+            // the selected color, on the color wheel.
+            colorPoint = GetPoint((double)HSV.Hue / 255 * 360,
+                (double)HSV.Saturation / 255 * radius,
+                centerPoint);
+
+            // Given the brightness (HSV.value), calculate the 
+            // point corresponding to the brightness indicator.
+            brightnessPoint = CalcBrightnessPoint(HSV.value);
+
+            // Store information about the selected color.
+            brightness = HSV.value;
+            selectedColor = ColorHandler.HSVtoColor(HSV);
+            RGB = ColorHandler.HSVtoRGB(HSV);
+
+            // The full color is the same as HSV, except that the 
+            // brightness is set to full (255). This is the top-most
+            // color in the brightness gradient.
+            fullColor = ColorHandler.HSVtoColor(HSV.Hue, HSV.Saturation, 255);
+        }
+
+        private void DrawLinearGradient(Color TopColor) {
+            // Given the top color, draw a linear gradient
+            // ranging from black to the top color. Use the 
+            // brightness rectangle as the area to fill.
+            using (LinearGradientBrush lgb =
+                             new LinearGradientBrush(brightnessRectangle, TopColor,
+                             Color.Black, LinearGradientMode.Vertical)) {
+                g.FillRectangle(lgb, brightnessRectangle);
+            }
+        }
+
+        private int CalcDegrees(Point pt) {
+            int degrees;
+
+            if (pt.X == 0) {
+                // The point is on the y-axis. Determine whether it's above or below the x-axis, and return the 
+                // corresponding angle. Note that the orientation of the y-coordinate is backwards. That is, 
+                // A positive Y value indicates a point BELOW the x-axis.
+                if (pt.Y > 0) {
+                    degrees = 270;
+                } else {
+                    degrees = 90;
+                }
+            } else {
+                // This value needs to be multiplied by -1 because the y-coordinate
+                // is opposite from the normal direction here.
+                // That is, a y-coordinate that's "higher" on the form has a lower y-value, in this coordinate
+                // system. So everything's off by a factor of -1 when performing the ratio calculations.
+                degrees = (int)(-Math.Atan((double)pt.Y / pt.X) * DEGREES_PER_RADIAN);
+
+                // If the x-coordinate of the selected point is to the left of the center of the circle, you 
+                // need to add 180 degrees to the angle. ArcTan only gives you a value on the right-hand side 
+                // of the circle.
+                if (pt.X < 0) {
+                    degrees += 180;
+                }
+
+                // Ensure that the return value is between 0 and 360.
+                degrees = (degrees + 360) % 360;
+            }
+            return degrees;
+        }
+
+        private void CreateGradient() {
+            // Create a new PathGradientBrush, supplying an array of points created by calling
+            // the GetPoints method.
+            using (PathGradientBrush pgb =
+                new PathGradientBrush(GetPoints(radius, new Point(radius, radius)))) {
+                // Set the various properties. Note the SurroundColors property, which contains an array of points, 
+                // in a one-to-one relationship with the points that created the gradient.
+                pgb.CenterColor = Color.White;
+                pgb.CenterPoint = new PointF(radius, radius);
+                pgb.SurroundColors = GetColors();
+
+                // Create a new bitmap containing the color wheel gradient, so the 
+                // code only needs to do all this work once. Later code uses the bitmap
+                // rather than recreating the gradient.
+                colorImage = new Bitmap(
+                    colorRectangle.Width, colorRectangle.Height,
+                    PixelFormat.Format32bppArgb);
+
+                using (Graphics newGraphics =
+                                 Graphics.FromImage(colorImage)) {
+                    newGraphics.FillEllipse(pgb, 0, 0,
+                        colorRectangle.Width, colorRectangle.Height);
+                }
+            }
+        }
+
+        private Color[] GetColors() {
+            // Create an array of COLOR_COUNT colors, looping through all the hues between 0 and 255, broken
+            // into COLOR_COUNT intervals. HSV is particularly well-suited for this, because the only value 
+            // that changes as you create colors is the Hue.
+            Color[] Colors = new Color[COLOR_COUNT];
+
+            for (int i = 0; i < COLOR_COUNT; i++)
+                Colors[i] = ColorHandler.HSVtoColor((int)((double)(i * 255) / COLOR_COUNT), 255, HSV.value);
+            return Colors;
+        }
+
+        private Point[] GetPoints(double radius, Point centerPoint) {
+            // Generate the array of points that describe the locations of the COLOR_COUNT colors to be 
+            // displayed on the color wheel.
+            Point[] Points = new Point[COLOR_COUNT];
+
+            for (int i = 0; i < COLOR_COUNT; i++)
+                Points[i] = GetPoint((double)(i * 360) / COLOR_COUNT, radius, centerPoint);
+            return Points;
+        }
+
+        private Point GetPoint(double degrees, double radius, Point centerPoint) {
+            // Given the center of a circle and its radius, along
+            // with the angle corresponding to the point, find the coordinates. 
+            // In other words, conver  t from polar to rectangular coordinates.
+            double radians = degrees / DEGREES_PER_RADIAN;
+
+            return new Point((int)(centerPoint.X + Math.Floor(radius * Math.Cos(radians))),
+                (int)(centerPoint.Y - Math.Floor(radius * Math.Sin(radians))));
+        }
+
+        private void DrawColorPointer(Point pt) {
+            // Given a point, draw the color selector. The constant SIZE represents half
+            // the width -- the square will be twice this value in width and height.
+            const int SIZE = 3;
+            g.DrawRectangle(Pens.Black,
+                pt.X - SIZE, pt.Y - SIZE, SIZE * 2, SIZE * 2);
+        }
+
+        private void DrawBrightnessPointer(Point pt) {
+            // Draw a triangle for the brightness indicator that "points" at the provided point.
+            const int HEIGHT = 10;
+            const int WIDTH = 7;
+
+            Point[] Points = new Point[3];
+            Points[0] = pt;
+            Points[1] = new Point(pt.X + WIDTH, pt.Y + HEIGHT / 2);
+            Points[2] = new Point(pt.X + WIDTH, pt.Y - HEIGHT / 2);
+            g.FillPolygon(Brushes.Black, Points);
+        }
+    }
+}
diff --git a/Source/Plugins/ColorPicker/Controls/ColorPickerControl.cs b/Source/Plugins/ColorPicker/Controls/ColorPickerControl.cs
new file mode 100644
index 0000000000000000000000000000000000000000..ec73290533a5703611a11bdf7e274d7222ef96ca
--- /dev/null
+++ b/Source/Plugins/ColorPicker/Controls/ColorPickerControl.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Text;
+using System.Windows.Forms;
+
+namespace CodeImp.DoomBuilder.ColorPicker.Controls {
+    public partial class ColorPickerControl : UserControl {
+        
+        private enum ChangeStyle {
+            MouseMove,
+            RGB,
+            None
+        }
+        
+        private ChangeStyle changeType = ChangeStyle.None;
+        private Point selectedPoint;
+
+        private ColorWheel colorWheel;
+        private ColorHandler.RGB RGB;
+
+        public ColorHandler.RGB CurrentColor { 
+            get 
+            {
+                //GZBuilder.GZGeneral.Trace("get CurrentColor: " + RGB.Red + "," + RGB.Green + "," + RGB.Blue);
+                return RGB; 
+            } 
+        }
+
+        private bool isInUpdate = false;
+        private Color startColor;
+
+        //events
+        public event EventHandler<ColorChangedEventArgs> ColorChanged;
+        public event EventHandler OnOkPressed;
+        public event EventHandler OnCancelPressed;
+
+        public Button OkButton { get { return btnOK; } }
+        public Button CancelButton { get { return btnCancel; } }
+
+        public void Initialize(Color startColor){
+            this.startColor = startColor;
+            InitializeComponent();
+        }
+
+        private void nudValueChanged(object sender, System.EventArgs e) {
+            // If the R, G, or B values change, use this code to update the HSV values and invalidate
+            // the color wheel (so it updates the pointers).
+            // Check the isInUpdate flag to avoid recursive events when you update the NumericUpdownControls.
+            if (!isInUpdate) {
+                changeType = ChangeStyle.RGB;
+                RGB = new ColorHandler.RGB((int)nudRed.Value, (int)nudGreen.Value, (int)nudBlue.Value);
+                updateOKButton(RGB);
+                this.Invalidate();
+            }
+        }
+
+        private void setRGB(ColorHandler.RGB RGB) {
+            // Update the RGB values on the form, but don't trigger the ValueChanged event of the form. The isInUpdate
+            // variable ensures that the event procedures exit without doing anything.
+            isInUpdate = true;
+            refreshNudValue(nudRed, RGB.Red);
+            refreshNudValue(nudBlue, RGB.Blue);
+            refreshNudValue(nudGreen, RGB.Green);
+            updateOKButton(RGB);
+            isInUpdate = false;
+        }
+
+        private void updateOKButton(ColorHandler.RGB RGB) {
+            this.RGB = RGB;
+            btnOK.BackColor = ColorHandler.RGBtoColor(RGB);
+            btnOK.ForeColor = (RGB.Red < 180 && RGB.Green < 180) ? Color.White : Color.Black;
+
+            //dispatch event further
+            EventHandler<ColorChangedEventArgs> handler = ColorChanged;
+            if (handler != null)
+                handler(this, new ColorChangedEventArgs(RGB, ColorHandler.RGBtoHSV(RGB)));
+        }
+
+        private void updateCancelButton(ColorHandler.RGB RGB) {
+            btnCancel.BackColor = ColorHandler.RGBtoColor(RGB);
+            btnCancel.ForeColor = (RGB.Red < 180 && RGB.Green < 180) ? Color.White : Color.Black;
+        }
+
+        private void refreshNudValue(NumericUpDown nud, int value) {
+            // Update the value of the NumericUpDown control, if the value is different than the current value.
+            // Refresh the control, causing an immediate repaint.
+            if (nud.Value != value) {
+                nud.Value = value;
+                nud.Refresh();
+            }
+        }
+
+        public void SetCurrentColor(Color c) {
+            isInUpdate = true;
+            changeType = ChangeStyle.RGB;
+            RGB = new ColorHandler.RGB(c.R, c.G, c.B);
+
+            refreshNudValue(nudRed, RGB.Red);
+            refreshNudValue(nudBlue, RGB.Blue);
+            refreshNudValue(nudGreen, RGB.Green);
+            updateOKButton(RGB);
+            isInUpdate = false;
+            this.Invalidate();
+        }
+
+        public void SetInitialColor(Color c) {
+            updateCancelButton(new ColorHandler.RGB(c.R, c.G, c.B));
+        }
+
+        //events
+        private void ColorPickerControl_Load(object sender, EventArgs e) {
+            // Turn on double-buffering, so the form looks better. 
+            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
+            this.SetStyle(ControlStyles.UserPaint, true);
+            this.SetStyle(ControlStyles.DoubleBuffer, true);
+
+            Rectangle BrightnessRectangle = new Rectangle(pnlBrightness.Location, pnlBrightness.Size);
+            Rectangle ColorRectangle = new Rectangle(pnlColor.Location, pnlColor.Size);
+
+            // Create the new ColorWheel class, indicating the locations of the color wheel itself, the
+            // brightness area, and the position of the selected color.
+            colorWheel = new ColorWheel(ColorRectangle, BrightnessRectangle);
+            colorWheel.ColorChanged += new ColorWheel.ColorChangedEventHandler(this.colorChanged);
+
+            //set initial colors
+            SetCurrentColor(startColor);
+            updateCancelButton(RGB);
+        }
+
+        private void ColorPickerControl_MouseDown(object sender, MouseEventArgs e) {
+            if (e.Button == MouseButtons.Left) {
+                changeType = ChangeStyle.MouseMove;
+                selectedPoint = new Point(e.X, e.Y);
+                this.Invalidate();
+            }
+        }
+
+        private void colorChanged(object sender, ColorChangedEventArgs e) {
+            setRGB(e.RGB);
+        }
+
+        private void onPaint(object sender, System.Windows.Forms.PaintEventArgs e) {
+            // Depending on the circumstances, force a repaint
+            // of the color wheel passing different information.
+            switch (changeType) {
+                case ChangeStyle.MouseMove:
+                case ChangeStyle.None:
+                    colorWheel.Draw(e.Graphics, selectedPoint);
+                    break;
+                case ChangeStyle.RGB:
+                    colorWheel.Draw(e.Graphics, RGB);
+                    break;
+            }
+        }
+
+        private void handleMouse(object sender, MouseEventArgs e) {
+            if (e.Button == MouseButtons.Left) {
+                changeType = ChangeStyle.MouseMove;
+                selectedPoint = new Point(e.X, e.Y);
+                this.Invalidate();
+            }
+        }
+
+        private void onMouseUp(object sender, MouseEventArgs e) {
+            colorWheel.SetMouseUp();
+            changeType = ChangeStyle.None;
+        }
+
+        private void onMouseUp(object sender, EventArgs e) {
+            colorWheel.SetMouseUp();
+            changeType = ChangeStyle.None;
+        }
+
+        private void btnOK_Click(object sender, EventArgs e) {
+            //dispatch event further
+            EventHandler handler = OnOkPressed;
+            if (handler != null)
+                handler(this, e);
+        }
+
+        private void btnCancel_Click(object sender, EventArgs e) {
+            //dispatch event further
+            EventHandler handler = OnCancelPressed;
+            if (handler != null)
+                handler(this, e);
+        }
+    }
+}
diff --git a/Source/Plugins/ColorPicker/Controls/ColorPickerControl.designer.cs b/Source/Plugins/ColorPicker/Controls/ColorPickerControl.designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..f74c725b24ddd2dffd2c7df8feecab3664e6c154
--- /dev/null
+++ b/Source/Plugins/ColorPicker/Controls/ColorPickerControl.designer.cs
@@ -0,0 +1,198 @@
+namespace CodeImp.DoomBuilder.ColorPicker.Controls {
+    partial class ColorPickerControl {
+        /// <summary> 
+        /// Требуется переменная конструктора.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Освободить все используемые ресурсы.
+        /// </summary>
+        /// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
+        protected override void Dispose(bool disposing) {
+            if (disposing && (components != null)) {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Код, автоматически созданный конструктором компонентов
+
+        /// <summary> 
+        /// Обязательный метод для поддержки конструктора - не изменяйте 
+        /// содержимое данного метода при помощи редактора кода.
+        /// </summary>
+        private void InitializeComponent() {
+            this.btnCancel = new System.Windows.Forms.Button();
+            this.btnOK = new System.Windows.Forms.Button();
+            this.Label3 = new System.Windows.Forms.Label();
+            this.nudRed = new System.Windows.Forms.NumericUpDown();
+            this.pnlColor = new System.Windows.Forms.Panel();
+            this.Label1 = new System.Windows.Forms.Label();
+            this.pnlBrightness = new System.Windows.Forms.Panel();
+            this.nudBlue = new System.Windows.Forms.NumericUpDown();
+            this.nudGreen = new System.Windows.Forms.NumericUpDown();
+            this.Label2 = new System.Windows.Forms.Label();
+            ((System.ComponentModel.ISupportInitialize)(this.nudRed)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.nudBlue)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.nudGreen)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // btnCancel
+            // 
+            this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+            this.btnCancel.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
+            this.btnCancel.Font = new System.Drawing.Font("Arial", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.btnCancel.Location = new System.Drawing.Point(214, 44);
+            this.btnCancel.Name = "btnCancel";
+            this.btnCancel.Size = new System.Drawing.Size(94, 42);
+            this.btnCancel.TabIndex = 54;
+            this.btnCancel.Text = "Cancel";
+            this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
+            // 
+            // btnOK
+            // 
+            this.btnOK.BackColor = System.Drawing.SystemColors.Control;
+            this.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK;
+            this.btnOK.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
+            this.btnOK.Font = new System.Drawing.Font("Arial", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.btnOK.ForeColor = System.Drawing.SystemColors.ControlText;
+            this.btnOK.Location = new System.Drawing.Point(214, 3);
+            this.btnOK.Name = "btnOK";
+            this.btnOK.Size = new System.Drawing.Size(94, 42);
+            this.btnOK.TabIndex = 53;
+            this.btnOK.Text = "OK";
+            this.btnOK.UseVisualStyleBackColor = true;
+            this.btnOK.Click += new System.EventHandler(this.btnOK_Click);
+            // 
+            // Label3
+            // 
+            this.Label3.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.Label3.Location = new System.Drawing.Point(214, 147);
+            this.Label3.Name = "Label3";
+            this.Label3.Size = new System.Drawing.Size(40, 23);
+            this.Label3.TabIndex = 60;
+            this.Label3.Text = "Blue:";
+            this.Label3.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            // 
+            // nudRed
+            // 
+            this.nudRed.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.nudRed.Location = new System.Drawing.Point(260, 101);
+            this.nudRed.Maximum = new decimal(new int[] {
+            255,
+            0,
+            0,
+            0});
+            this.nudRed.Name = "nudRed";
+            this.nudRed.Size = new System.Drawing.Size(48, 20);
+            this.nudRed.TabIndex = 55;
+            this.nudRed.ValueChanged += new System.EventHandler(this.nudValueChanged);
+            // 
+            // pnlColor
+            // 
+            this.pnlColor.Location = new System.Drawing.Point(3, 3);
+            this.pnlColor.Name = "pnlColor";
+            this.pnlColor.Size = new System.Drawing.Size(176, 176);
+            this.pnlColor.TabIndex = 61;
+            this.pnlColor.Visible = false;
+            // 
+            // Label1
+            // 
+            this.Label1.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.Label1.Location = new System.Drawing.Point(214, 99);
+            this.Label1.Name = "Label1";
+            this.Label1.Size = new System.Drawing.Size(40, 23);
+            this.Label1.TabIndex = 58;
+            this.Label1.Text = "Red:";
+            this.Label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            // 
+            // pnlBrightness
+            // 
+            this.pnlBrightness.Location = new System.Drawing.Point(185, 3);
+            this.pnlBrightness.Name = "pnlBrightness";
+            this.pnlBrightness.Size = new System.Drawing.Size(16, 176);
+            this.pnlBrightness.TabIndex = 62;
+            this.pnlBrightness.Visible = false;
+            // 
+            // nudBlue
+            // 
+            this.nudBlue.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.nudBlue.Location = new System.Drawing.Point(260, 149);
+            this.nudBlue.Maximum = new decimal(new int[] {
+            255,
+            0,
+            0,
+            0});
+            this.nudBlue.Name = "nudBlue";
+            this.nudBlue.Size = new System.Drawing.Size(48, 20);
+            this.nudBlue.TabIndex = 57;
+            this.nudBlue.ValueChanged += new System.EventHandler(this.nudValueChanged);
+            // 
+            // nudGreen
+            // 
+            this.nudGreen.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.nudGreen.Location = new System.Drawing.Point(260, 125);
+            this.nudGreen.Maximum = new decimal(new int[] {
+            255,
+            0,
+            0,
+            0});
+            this.nudGreen.Name = "nudGreen";
+            this.nudGreen.Size = new System.Drawing.Size(48, 20);
+            this.nudGreen.TabIndex = 56;
+            this.nudGreen.ValueChanged += new System.EventHandler(this.nudValueChanged);
+            // 
+            // Label2
+            // 
+            this.Label2.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.Label2.Location = new System.Drawing.Point(214, 123);
+            this.Label2.Name = "Label2";
+            this.Label2.Size = new System.Drawing.Size(40, 23);
+            this.Label2.TabIndex = 59;
+            this.Label2.Text = "Green:";
+            this.Label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            // 
+            // ColorPickerControl
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.btnCancel);
+            this.Controls.Add(this.btnOK);
+            this.Controls.Add(this.Label3);
+            this.Controls.Add(this.nudRed);
+            this.Controls.Add(this.pnlColor);
+            this.Controls.Add(this.Label1);
+            this.Controls.Add(this.pnlBrightness);
+            this.Controls.Add(this.nudBlue);
+            this.Controls.Add(this.nudGreen);
+            this.Controls.Add(this.Label2);
+            this.Name = "ColorPickerControl";
+            this.Size = new System.Drawing.Size(311, 183);
+            this.Load += new System.EventHandler(this.ColorPickerControl_Load);
+            this.MouseLeave += new System.EventHandler(this.onMouseUp);
+            this.Paint += new System.Windows.Forms.PaintEventHandler(this.onPaint);
+            this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.handleMouse);
+            this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.ColorPickerControl_MouseDown);
+            this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.onMouseUp);
+            ((System.ComponentModel.ISupportInitialize)(this.nudRed)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.nudBlue)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.nudGreen)).EndInit();
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        internal System.Windows.Forms.Button btnCancel;
+        internal System.Windows.Forms.Button btnOK;
+        internal System.Windows.Forms.Label Label3;
+        internal System.Windows.Forms.NumericUpDown nudRed;
+        internal System.Windows.Forms.Panel pnlColor;
+        internal System.Windows.Forms.Label Label1;
+        internal System.Windows.Forms.Panel pnlBrightness;
+        internal System.Windows.Forms.NumericUpDown nudBlue;
+        internal System.Windows.Forms.NumericUpDown nudGreen;
+        internal System.Windows.Forms.Label Label2;
+    }
+}
diff --git a/Source/Plugins/ColorPicker/Controls/ColorPickerControl.resx b/Source/Plugins/ColorPicker/Controls/ColorPickerControl.resx
new file mode 100644
index 0000000000000000000000000000000000000000..ff31a6db56e23b5a334f34387830ba5b4bd33eb8
--- /dev/null
+++ b/Source/Plugins/ColorPicker/Controls/ColorPickerControl.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
diff --git a/Source/Plugins/ColorPicker/Controls/ColorPickerSlider.Designer.cs b/Source/Plugins/ColorPicker/Controls/ColorPickerSlider.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..8272939ec63548e8abff42fe6f447288c34bfaee
--- /dev/null
+++ b/Source/Plugins/ColorPicker/Controls/ColorPickerSlider.Designer.cs
@@ -0,0 +1,109 @@
+namespace CodeImp.DoomBuilder.ColorPicker.Controls {
+    partial class ColorPickerSlider {
+        /// <summary> 
+        /// Требуется переменная конструктора.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Освободить все используемые ресурсы.
+        /// </summary>
+        /// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
+        protected override void Dispose(bool disposing) {
+            if (disposing && (components != null)) {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Код, автоматически созданный конструктором компонентов
+
+        /// <summary> 
+        /// Обязательный метод для поддержки конструктора - не изменяйте 
+        /// содержимое данного метода при помощи редактора кода.
+        /// </summary>
+        private void InitializeComponent() {
+            this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
+            this.trackBar1 = new Dotnetrix.Controls.TrackBar();
+            this.label1 = new System.Windows.Forms.Label();
+            this.labelMin = new System.Windows.Forms.Label();
+            this.labelMax = new System.Windows.Forms.Label();
+            ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // numericUpDown1
+            // 
+            this.numericUpDown1.Location = new System.Drawing.Point(263, 16);
+            this.numericUpDown1.Name = "numericUpDown1";
+            this.numericUpDown1.Size = new System.Drawing.Size(44, 20);
+            this.numericUpDown1.TabIndex = 5;
+            this.numericUpDown1.ValueChanged += new System.EventHandler(this.numericUpDown1_ValueChanged);
+            // 
+            // trackBar1
+            // 
+            this.trackBar1.LargeChange = 32;
+            this.trackBar1.Location = new System.Drawing.Point(115, 7);
+            this.trackBar1.Maximum = 512;
+            this.trackBar1.Name = "trackBar1";
+            this.trackBar1.Size = new System.Drawing.Size(142, 45);
+            this.trackBar1.SmallChange = 4;
+            this.trackBar1.TabIndex = 4;
+            this.trackBar1.TickFrequency = 16;
+            this.trackBar1.TickStyle = System.Windows.Forms.TickStyle.Both;
+            this.trackBar1.ValueChanged += new System.EventHandler(this.trackBar1_ValueChanged);
+            // 
+            // label1
+            // 
+            this.label1.Location = new System.Drawing.Point(3, 15);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(106, 14);
+            this.label1.TabIndex = 3;
+            this.label1.Text = "Secondary intensity:";
+            this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            // 
+            // labelMin
+            // 
+            this.labelMin.Location = new System.Drawing.Point(111, -1);
+            this.labelMin.Name = "labelMin";
+            this.labelMin.Size = new System.Drawing.Size(36, 15);
+            this.labelMin.TabIndex = 6;
+            this.labelMin.Text = "0";
+            this.labelMin.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            // 
+            // labelMax
+            // 
+            this.labelMax.Location = new System.Drawing.Point(231, -1);
+            this.labelMax.Name = "labelMax";
+            this.labelMax.Size = new System.Drawing.Size(36, 15);
+            this.labelMax.TabIndex = 7;
+            this.labelMax.Text = "512";
+            this.labelMax.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            // 
+            // ColorPickerSlider
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.labelMax);
+            this.Controls.Add(this.labelMin);
+            this.Controls.Add(this.numericUpDown1);
+            this.Controls.Add(this.trackBar1);
+            this.Controls.Add(this.label1);
+            this.Name = "ColorPickerSlider";
+            this.Size = new System.Drawing.Size(311, 45);
+            ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.NumericUpDown numericUpDown1;
+        private Dotnetrix.Controls.TrackBar trackBar1;
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.Label labelMin;
+        private System.Windows.Forms.Label labelMax;
+    }
+}
diff --git a/Source/Plugins/ColorPicker/Controls/ColorPickerSlider.cs b/Source/Plugins/ColorPicker/Controls/ColorPickerSlider.cs
new file mode 100644
index 0000000000000000000000000000000000000000..4cb5d3c886b9da92c25ddc391f3a45ea976f3426
--- /dev/null
+++ b/Source/Plugins/ColorPicker/Controls/ColorPickerSlider.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace CodeImp.DoomBuilder.ColorPicker.Controls {
+    public partial class ColorPickerSlider : UserControl {
+
+        private bool blockEvents;
+        public event EventHandler<ColorPickerSliderEventArgs> OnValueChanged;
+
+        public int Value { 
+            get 
+            { 
+                return (int)numericUpDown1.Value; 
+            }
+            set 
+            {
+                blockEvents = true;
+                numericUpDown1.Value = General.Clamp(value, (int)numericUpDown1.Minimum, (int)numericUpDown1.Maximum);
+                blockEvents = false;
+            }
+        }
+
+        private bool showLimits;
+        public bool ShowLimits { 
+            get 
+            { 
+                return showLimits; 
+            }
+            set 
+            {
+                showLimits = value;
+                labelMin.Visible = showLimits;
+                labelMax.Visible = showLimits;
+            }
+        }
+
+        public string Label { set { label1.Text = value; } }
+        
+        public ColorPickerSlider() {
+            InitializeComponent();
+        }
+
+        public void SetLimits(int tbMin, int tbMax, int nudMin, int nudMax) {
+            bool blockEventsStatus = blockEvents;
+            blockEvents = true;
+
+            trackBar1.Value = General.Clamp(trackBar1.Value, tbMin, tbMax);
+            trackBar1.Minimum = tbMin;
+            trackBar1.Maximum = tbMax;
+
+            labelMin.Text = tbMin.ToString();
+            labelMax.Text = tbMax.ToString();
+
+            numericUpDown1.Value = General.Clamp((int)numericUpDown1.Value, nudMin, nudMax);
+            numericUpDown1.Minimum = nudMin;
+            numericUpDown1.Maximum = nudMax;
+
+            blockEvents = blockEventsStatus;
+        }
+
+//events
+        private void trackBar1_ValueChanged(object sender, EventArgs e) {
+            numericUpDown1.Value = ((TrackBar)sender).Value;
+        }
+
+        private void numericUpDown1_ValueChanged(object sender, EventArgs e) {
+            bool blockEventsStatus = blockEvents;
+            
+            int val = (int)((NumericUpDown)sender).Value;
+
+            if (!blockEventsStatus) {
+                EventHandler<ColorPickerSliderEventArgs> handler = OnValueChanged;
+                if (handler != null)
+                    handler(this, new ColorPickerSliderEventArgs(val));
+            }
+
+            blockEvents = true;
+            trackBar1.Value = General.Clamp(val, trackBar1.Minimum, trackBar1.Maximum); //clamp it!
+            blockEvents = blockEventsStatus;
+        }
+    }
+}
diff --git a/Source/Plugins/ColorPicker/Controls/ColorPickerSlider.resx b/Source/Plugins/ColorPicker/Controls/ColorPickerSlider.resx
new file mode 100644
index 0000000000000000000000000000000000000000..ff31a6db56e23b5a334f34387830ba5b4bd33eb8
--- /dev/null
+++ b/Source/Plugins/ColorPicker/Controls/ColorPickerSlider.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
diff --git a/Source/Plugins/ColorPicker/Controls/ColorPickerSliderEventArgs.cs b/Source/Plugins/ColorPicker/Controls/ColorPickerSliderEventArgs.cs
new file mode 100644
index 0000000000000000000000000000000000000000..585ba702baf4eba6626a59e83212c16514d41b2a
--- /dev/null
+++ b/Source/Plugins/ColorPicker/Controls/ColorPickerSliderEventArgs.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace CodeImp.DoomBuilder.ColorPicker.Controls {
+    public class ColorPickerSliderEventArgs : EventArgs {
+        private int value;
+        public int Value { get { return value; } }
+
+        public ColorPickerSliderEventArgs(int value) {
+            this.value = value;
+        }
+    }
+}
diff --git a/Source/Plugins/ColorPicker/IColorPicker.cs b/Source/Plugins/ColorPicker/IColorPicker.cs
new file mode 100644
index 0000000000000000000000000000000000000000..d90b1958b440fff7bd6c237eb1590972f13ace84
--- /dev/null
+++ b/Source/Plugins/ColorPicker/IColorPicker.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace CodeImp.DoomBuilder.ColorPicker {
+    interface IColorPicker : IWin32Window {
+        Point Location { get; set; }
+        bool Visible { get; set; }
+        int Width { get; set; }
+
+        ColorPickerType Type { get; }
+
+        bool Setup(string editingModeName);
+        //void OnBeforeClose();
+        //void UpdateSelection();
+        //void UpdateSelection(string editingModeName);
+
+        DialogResult ShowDialog(IWin32Window w);
+        //void Show(IWin32Window w);
+        void Close();
+        void Dispose();
+        //void Activate();
+
+        event FormClosedEventHandler FormClosed;
+    }
+}
diff --git a/Source/Plugins/ColorPicker/Properties/AssemblyInfo.cs b/Source/Plugins/ColorPicker/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000000000000000000000000000000000..6c94e96712a3fe3ba090fb7f7667e624fcd43609
--- /dev/null
+++ b/Source/Plugins/ColorPicker/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// Управление общими сведениями о сборке осуществляется с помощью 
+// набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения,
+// связанные со сборкой.
+[assembly: AssemblyTitle("ColorPicker")]
+[assembly: AssemblyDescription("ColorPicker control for GZDoomBuilder")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ColorPicker")]
+[assembly: AssemblyCopyright("Copyright © MaxED 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Параметр ComVisible со значением FALSE делает типы в сборке невидимыми 
+// для COM-компонентов.  Если требуется обратиться к типу в этой сборке через 
+// COM, задайте атрибуту ComVisible значение TRUE для этого типа.
+[assembly: ComVisible(false)]
+
+// Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM
+[assembly: Guid("82178b31-4cd7-43e0-a25f-6a58de2fae4e")]
+
+// Сведения о версии сборки состоят из следующих четырех значений:
+//
+//      Основной номер версии
+//      Дополнительный номер версии 
+//      Номер построения
+//      Редакция
+//
+// Можно задать все значения или принять номер построения и номер редакции по умолчанию, 
+// используя "*", как показано ниже:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Source/Plugins/ColorPicker/Properties/Resources.Designer.cs b/Source/Plugins/ColorPicker/Properties/Resources.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..aec6e2f322b0304496462b67a11b8d1c109c5595
--- /dev/null
+++ b/Source/Plugins/ColorPicker/Properties/Resources.Designer.cs
@@ -0,0 +1,70 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     Этот код создан программой.
+//     Исполняемая версия:2.0.50727.5420
+//
+//     Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае
+//     повторной генерации кода.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace CodeImp.DoomBuilder.ColorPicker.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   Класс ресурса со строгой типизацией для поиска локализованных строк и т.д.
+    /// </summary>
+    // Этот класс создан автоматически классом StronglyTypedResourceBuilder
+    // с помощью такого средства, как ResGen или Visual Studio.
+    // Чтобы добавить или удалить член, измените файл .ResX и снова запустите ResGen
+    // с параметром /str или перестройте свой проект VS.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Возвращает кэшированный экземпляр ResourceManager, использованный этим классом.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CodeImp.DoomBuilder.ColorPicker.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Перезаписывает свойство CurrentUICulture текущего потока для всех
+        ///   обращений к ресурсу с помощью этого класса ресурса со строгой типизацией.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        internal static System.Drawing.Bitmap cp {
+            get {
+                object obj = ResourceManager.GetObject("cp", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+    }
+}
diff --git a/Source/Plugins/ColorPicker/Properties/Resources.resx b/Source/Plugins/ColorPicker/Properties/Resources.resx
new file mode 100644
index 0000000000000000000000000000000000000000..d2855eca01b4d6a52739d5b66820d5536b356c87
--- /dev/null
+++ b/Source/Plugins/ColorPicker/Properties/Resources.resx
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="cp" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\cp.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Source/Plugins/ColorPicker/Resources/Actions.cfg b/Source/Plugins/ColorPicker/Resources/Actions.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..8a3185103581243861d5ff7f0febb832dada73ee
--- /dev/null
+++ b/Source/Plugins/ColorPicker/Resources/Actions.cfg
@@ -0,0 +1,10 @@
+togglelightpannel
+{
+    title = "Toggle color picker";
+	category = "tools";
+	description = "Select dynamic light thing(s) or sectors, then use this pannel to set light properties quickly.";
+	allowkeys = true;
+	allowmouse = true;
+	allowscroll = false;
+	default = 75; //K
+}
\ No newline at end of file
diff --git a/Source/Plugins/ColorPicker/Resources/cp.png b/Source/Plugins/ColorPicker/Resources/cp.png
new file mode 100644
index 0000000000000000000000000000000000000000..28f423982934a69a776d6aaaf3038d4e21ac2220
Binary files /dev/null and b/Source/Plugins/ColorPicker/Resources/cp.png differ
diff --git a/Source/Plugins/ColorPicker/Windows/LightColorPicker.Designer.cs b/Source/Plugins/ColorPicker/Windows/LightColorPicker.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..fc5aaad7f841247d46d303d0190946b6d6c40c5a
--- /dev/null
+++ b/Source/Plugins/ColorPicker/Windows/LightColorPicker.Designer.cs
@@ -0,0 +1,106 @@
+namespace CodeImp.DoomBuilder.ColorPicker.Windows {
+    partial class LightColorPicker {
+        /// <summary>
+        /// Требуется переменная конструктора.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Освободить все используемые ресурсы.
+        /// </summary>
+        /// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
+        protected override void Dispose(bool disposing) {
+            if (disposing && (components != null)) {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Код, автоматически созданный конструктором форм Windows
+
+        /// <summary>
+        /// Обязательный метод для поддержки конструктора - не изменяйте
+        /// содержимое данного метода при помощи редактора кода.
+        /// </summary>
+        private void InitializeComponent() {
+            this.colorPickerControl1 = new CodeImp.DoomBuilder.ColorPicker.Controls.ColorPickerControl();
+            this.cbRelativeMode = new System.Windows.Forms.CheckBox();
+            this.colorPickerSlider1 = new CodeImp.DoomBuilder.ColorPicker.Controls.ColorPickerSlider();
+            this.colorPickerSlider2 = new CodeImp.DoomBuilder.ColorPicker.Controls.ColorPickerSlider();
+            this.colorPickerSlider3 = new CodeImp.DoomBuilder.ColorPicker.Controls.ColorPickerSlider();
+            this.SuspendLayout();
+            // 
+            // colorPickerControl1
+            // 
+            this.colorPickerControl1.Location = new System.Drawing.Point(8, 8);
+            this.colorPickerControl1.Name = "colorPickerControl1";
+            this.colorPickerControl1.Size = new System.Drawing.Size(311, 183);
+            this.colorPickerControl1.TabIndex = 0;
+            // 
+            // cbRelativeMode
+            // 
+            this.cbRelativeMode.AutoSize = true;
+            this.cbRelativeMode.Location = new System.Drawing.Point(14, 209);
+            this.cbRelativeMode.Name = "cbRelativeMode";
+            this.cbRelativeMode.Size = new System.Drawing.Size(93, 18);
+            this.cbRelativeMode.TabIndex = 5;
+            this.cbRelativeMode.Text = "Relative Mode";
+            this.cbRelativeMode.UseVisualStyleBackColor = true;
+            // 
+            // colorPickerSlider1
+            // 
+            this.colorPickerSlider1.Location = new System.Drawing.Point(8, 233);
+            this.colorPickerSlider1.Name = "colorPickerSlider1";
+            this.colorPickerSlider1.ShowLimits = true;
+            this.colorPickerSlider1.Size = new System.Drawing.Size(311, 45);
+            this.colorPickerSlider1.TabIndex = 6;
+            // 
+            // colorPickerSlider2
+            // 
+            this.colorPickerSlider2.Location = new System.Drawing.Point(8, 284);
+            this.colorPickerSlider2.Name = "colorPickerSlider2";
+            this.colorPickerSlider2.ShowLimits = false;
+            this.colorPickerSlider2.Size = new System.Drawing.Size(311, 48);
+            this.colorPickerSlider2.TabIndex = 7;
+            // 
+            // colorPickerSlider3
+            // 
+            this.colorPickerSlider3.Location = new System.Drawing.Point(8, 338);
+            this.colorPickerSlider3.Name = "colorPickerSlider3";
+            this.colorPickerSlider3.ShowLimits = true;
+            this.colorPickerSlider3.Size = new System.Drawing.Size(311, 48);
+            this.colorPickerSlider3.TabIndex = 8;
+            // 
+            // LightColorPicker
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+            this.ClientSize = new System.Drawing.Size(327, 391);
+            this.Controls.Add(this.colorPickerSlider3);
+            this.Controls.Add(this.colorPickerSlider2);
+            this.Controls.Add(this.colorPickerSlider1);
+            this.Controls.Add(this.cbRelativeMode);
+            this.Controls.Add(this.colorPickerControl1);
+            this.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
+            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
+            this.Name = "LightColorPicker";
+            this.Opacity = 0;
+            this.ShowIcon = false;
+            this.ShowInTaskbar = false;
+            this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
+            this.Text = "LightColorPicker";
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private CodeImp.DoomBuilder.ColorPicker.Controls.ColorPickerControl colorPickerControl1;
+        private System.Windows.Forms.CheckBox cbRelativeMode;
+        private CodeImp.DoomBuilder.ColorPicker.Controls.ColorPickerSlider colorPickerSlider1;
+        private CodeImp.DoomBuilder.ColorPicker.Controls.ColorPickerSlider colorPickerSlider2;
+        private CodeImp.DoomBuilder.ColorPicker.Controls.ColorPickerSlider colorPickerSlider3;
+
+    }
+}
\ No newline at end of file
diff --git a/Source/Plugins/ColorPicker/Windows/LightColorPicker.cs b/Source/Plugins/ColorPicker/Windows/LightColorPicker.cs
new file mode 100644
index 0000000000000000000000000000000000000000..d90256c49de7da3a4826c2814ed04cb3b8230255
--- /dev/null
+++ b/Source/Plugins/ColorPicker/Windows/LightColorPicker.cs
@@ -0,0 +1,364 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+
+using CodeImp.DoomBuilder.Config;
+using CodeImp.DoomBuilder.Map;
+using CodeImp.DoomBuilder.Plugins;
+using CodeImp.DoomBuilder.Windows;
+using CodeImp.DoomBuilder.GZBuilder;
+using CodeImp.DoomBuilder.VisualModes;
+using CodeImp.DoomBuilder.ColorPicker.Controls;
+
+namespace CodeImp.DoomBuilder.ColorPicker.Windows {
+    public partial class LightColorPicker : DelayedForm, IColorPicker {
+        public ColorPickerType Type { get { return ColorPickerType.CP_LIGHT; } }
+
+        private static bool RELATIVE_MODE = false;
+        
+        private static int[] LIGHT_USES_ANGLE_VALUE = { 9801, 9802, 9804, 9811, 9812, 9814, 9821, 9822, 9824 };
+        
+        private List<Thing> selection;
+        private List<VisualThing> visualSelection;
+        private List<LightProps> fixedValues; //this gets filled with radius / intencity values before RELATIVE_MODE is engaged
+
+        private string editingModeName;
+        private bool showAllControls;
+
+        private LightProps lightProps;
+ 
+        //maximum and minimum values for sliders for relative and absolute modes
+        //numericUpDown
+        private const int NUD_ABS_MIN = 0;
+        private const int NUD_ABS_MAX = 16384;
+
+        private const int NUD_REL_MIN = -16384;
+        private const int NUD_REL_MAX = 16384;
+
+        //trackBar
+        private const int TB_ABS_MIN = 0;
+        private const int TB_ABS_MAX = 512;
+
+        private const int TB_REL_MIN = -256;
+        private const int TB_REL_MAX = 256;
+
+        //trackBar controlling thing angle
+        private const int TB_ANGLE_ABS_MIN = 0;
+        private const int TB_ANGLE_ABS_MAX = 359;
+
+        private const int TB_ANGLE_REL_MIN = -180;
+        private const int TB_ANGLE_REL_MAX = 180;
+
+        //initialise pannel
+        public bool Setup(string editingModeName) {
+            this.editingModeName = editingModeName;
+            setupSelection();
+
+            int selCount = selection.Count;
+            if (selCount == 0) {
+                Plug.DisplayStatus(StatusType.Warning, "No lights found in selection!");
+                return false;
+            }
+
+            lightProps = new LightProps();
+
+            //initialise
+            InitializeComponent();
+
+            setupSliders(selection[0]);
+            updateLightPropsFromThing(selection[0]);
+            setControlsMode();
+
+            colorPickerControl1.Initialize(getThingColor(selection[0]));
+            colorPickerControl1.ColorChanged += new EventHandler<ColorChangedEventArgs>(colorPickerControl1_ColorChanged);
+            colorPickerControl1.OnOkPressed += new EventHandler(colorPickerControl1_OnOkPressed);
+            colorPickerControl1.OnCancelPressed += new EventHandler(colorPickerControl1_OnCancelPressed);
+
+            cbRelativeMode.Checked = RELATIVE_MODE;
+            cbRelativeMode.CheckStateChanged += new EventHandler(cbRelativeMode_CheckStateChanged);
+
+            this.AcceptButton = colorPickerControl1.OkButton;
+            this.CancelButton = colorPickerControl1.CancelButton;
+            this.Text = "Editing " + selCount + " light" + (selCount > 1 ? "s" : "");
+            
+            //undo
+            makeUndo(this.Text);
+            return true;
+        }
+
+        //create selection of lights. This is called only once
+        private void setupSelection() {
+            selection = new List<Thing>();
+
+            //check things
+            if (editingModeName == "BaseVisualMode") {
+                visualSelection = new List<VisualThing>();
+                List<VisualThing> selectedVisualThings = ((VisualMode)General.Editing.Mode).SelectedVisualThings;
+
+                foreach (VisualThing t in selectedVisualThings) {
+                    if (Array.IndexOf(GZGeneral.GZ_LIGHTS, t.Thing.Type) != -1) {
+                        selection.Add(t.Thing);
+                        visualSelection.Add(t);
+                    }
+                }
+            } else {
+                ICollection<Thing> list = General.Map.Map.GetSelectedThings(true);
+                foreach (Thing t in list) {
+                    if (Array.IndexOf(GZGeneral.GZ_LIGHTS, t.Type) != -1)
+                        selection.Add(t);
+                }
+            }
+        }
+
+        //set sliders count and labels based on given thing, set lightProps start values
+        //this is called only once
+        private void setupSliders(Thing referenceThing) {
+            ThingTypeInfo typeInfo = General.Map.Data.GetThingInfoEx(referenceThing.Type);
+            int firstArg = 3;
+            if (referenceThing.Type == 1502 || referenceThing.Type == 1503)
+                firstArg = 0;
+
+            //first slider is always used
+            colorPickerSlider1.Label = typeInfo.Args[firstArg].Title + ":";
+            colorPickerSlider1.OnValueChanged += new EventHandler<ColorPickerSliderEventArgs>(onSliderValueChanged);
+
+            //either both of them or none are used
+            if (Array.IndexOf(LIGHT_USES_ANGLE_VALUE, referenceThing.Type) != -1) {
+                showAllControls = true;
+                colorPickerSlider2.Label = typeInfo.Args[4].Title + ":";
+                colorPickerSlider2.OnValueChanged += new EventHandler<ColorPickerSliderEventArgs>(onSliderValueChanged);
+                
+                colorPickerSlider3.Label = "Interval:";
+                colorPickerSlider3.OnValueChanged += new EventHandler<ColorPickerSliderEventArgs>(onSliderValueChanged);
+            } else {
+                colorPickerSlider2.Visible = false;
+                colorPickerSlider3.Visible = false;
+            }
+
+            //set window height
+            int newHeight = 0;
+            if (showAllControls) {
+                newHeight = colorPickerSlider3.Location.Y + colorPickerSlider3.Height + 8;
+            } else {
+                newHeight = colorPickerSlider1.Location.Y + colorPickerSlider1.Height + 8;
+            }
+
+            this.ClientSize = new Size(this.ClientSize.Width, newHeight);
+        }
+
+        //this sets lightProps values from given thing
+        private void updateLightPropsFromThing(Thing referenceThing) {
+            //color
+            Color c = getThingColor(referenceThing);
+            lightProps.Red = c.R;
+            lightProps.Green = c.G;
+            lightProps.Blue = c.B;
+            
+            //size
+            int firstArg = 3;
+            if (referenceThing.Type == 1502 || referenceThing.Type == 1503)
+                firstArg = 0;
+
+            lightProps.PrimaryRadius = referenceThing.Args[firstArg];
+
+            //either both of them or none are used
+            if (showAllControls && Array.IndexOf(LIGHT_USES_ANGLE_VALUE, referenceThing.Type) != -1) {
+                lightProps.SecondaryRadius = referenceThing.Args[4];
+                lightProps.Interval = referenceThing.AngleDoom;
+            }
+        }
+
+        //this sets lightProps values from sliders
+        private void updateLightPropsFromSliders() {
+            ColorHandler.RGB curColor = colorPickerControl1.CurrentColor;
+            bool colorChanged = false; //need this check to allow relative mode to work properly
+
+            if ((byte)curColor.Red != lightProps.Red || (byte)curColor.Green != lightProps.Green || (byte)curColor.Blue != lightProps.Blue) {
+                lightProps.Red = (byte)curColor.Red;
+                lightProps.Green = (byte)curColor.Green;
+                lightProps.Blue = (byte)curColor.Blue;
+                colorChanged = true;
+            }
+
+            lightProps.PrimaryRadius = colorPickerSlider1.Value;
+            if (showAllControls) {
+                lightProps.SecondaryRadius = colorPickerSlider2.Value;
+                lightProps.Interval = colorPickerSlider3.Value;
+            }
+            updateSelection(colorChanged);
+        }
+
+        //this sets values from lightProps to things in selection
+        private void updateSelection(bool colorChanged) {
+            for (int i = 0; i < selection.Count; i++) {
+                Thing t = selection[i];
+
+                //update color 
+                if (colorChanged) { //need this check to allow relative mode to work properly
+                    if (t.Type == 1503) { //Vavoom Light Color
+                        t.Args[1] = lightProps.Red;
+                        t.Args[2] = lightProps.Green;
+                        t.Args[3] = lightProps.Blue;
+                    } else if (t.Type != 1502) { //vavoom light has no color settings
+                        t.Args[0] = lightProps.Red;
+                        t.Args[1] = lightProps.Green;
+                        t.Args[2] = lightProps.Blue;
+                    }
+                }
+
+                int firstArg = 3;
+
+                if (t.Type == 1502 || t.Type == 1503)
+                    firstArg = 0;
+
+                //update radius and intensity
+                if (RELATIVE_MODE) {
+                    LightProps fixedVal = fixedValues[i];
+
+                    t.Args[firstArg] = fixedVal.PrimaryRadius + lightProps.PrimaryRadius;
+                    if (t.Args[firstArg] < 0) t.Args[firstArg] = 0;
+
+                    if (showAllControls && Array.IndexOf(LIGHT_USES_ANGLE_VALUE, t.Type) != -1) {
+                        t.Args[4] = fixedVal.SecondaryRadius + lightProps.SecondaryRadius;
+                        if (t.Args[4] < 0) t.Args[4] = 0;
+
+                        t.Rotate(General.ClampAngle(fixedVal.Interval + lightProps.Interval));
+                    }
+                } else {
+                    if (lightProps.PrimaryRadius != -1)
+                        t.Args[firstArg] = lightProps.PrimaryRadius;
+
+                    if (showAllControls && Array.IndexOf(LIGHT_USES_ANGLE_VALUE, t.Type) != -1) {
+                        t.Args[4] = lightProps.SecondaryRadius;
+                        t.Rotate(General.ClampAngle(lightProps.Interval));
+                    }
+                }
+            }
+
+            //update VisualThings
+            if (editingModeName == "BaseVisualMode") {
+                foreach (VisualThing t in visualSelection)
+                    t.UpdateLight();
+            }
+        }
+
+        //switch between absolute and relative mode
+        private void setControlsMode() {
+            if (RELATIVE_MODE) {
+                setFixedValues();
+
+                colorPickerSlider1.SetLimits(TB_REL_MIN, TB_REL_MAX, NUD_REL_MIN, NUD_REL_MAX);
+                colorPickerSlider1.Value = 0;
+
+                if (showAllControls) {
+                    colorPickerSlider2.SetLimits(TB_REL_MIN, TB_REL_MAX, NUD_REL_MIN, NUD_REL_MAX);
+                    colorPickerSlider2.Value = 0;
+
+                    colorPickerSlider3.SetLimits(TB_ANGLE_REL_MIN, TB_ANGLE_REL_MAX, NUD_REL_MIN, NUD_REL_MAX);
+                    colorPickerSlider3.Value = 0;
+                }    
+            } else {
+                updateLightPropsFromThing(selection[0]);
+
+                colorPickerSlider1.SetLimits(TB_ABS_MIN, TB_ABS_MAX, NUD_ABS_MIN, NUD_ABS_MAX);
+                colorPickerSlider1.Value = lightProps.PrimaryRadius;
+
+                if (showAllControls) {
+                    colorPickerSlider2.SetLimits(TB_ABS_MIN, TB_ABS_MAX, NUD_ABS_MIN, NUD_ABS_MAX);
+                    colorPickerSlider2.Value = lightProps.SecondaryRadius;
+
+                    colorPickerSlider3.SetLimits(TB_ANGLE_ABS_MIN, TB_ANGLE_ABS_MAX, NUD_ABS_MIN, NUD_ABS_MAX);
+                    colorPickerSlider3.Value = lightProps.Interval;
+                }
+            }
+        }
+
+        private void makeUndo(string description) {
+            General.Map.UndoRedo.CreateUndo(description);
+
+            //tricky way to actually store undo information...
+            foreach (Thing t in selection)
+                t.Move(t.Position);
+        }
+
+        //this is called only once
+        private Color getThingColor(Thing thing) {
+            if (thing.Type == 1502) { //vavoom light
+                return Color.White;
+            } else if (thing.Type == 1503) { //vavoom colored light
+                return Color.FromArgb((byte)thing.Args[1], (byte)thing.Args[2], (byte)thing.Args[3]);
+            }
+            return Color.FromArgb((byte)thing.Args[0], (byte)thing.Args[1], (byte)thing.Args[2]); ;
+        }
+
+        //this sets data to use as a reference for relative mode
+        private void setFixedValues() {
+            fixedValues = new List<LightProps>();
+
+            for (int i = 0; i < selection.Count; i++) {
+                Thing t = selection[i];
+                //ThingTypeInfo typeInfo = General.Map.Data.GetThingInfoEx(t.Type);
+                LightProps lp = new LightProps();
+
+                int firstArg = 3;
+                if (t.Type == 1502 || t.Type == 1503)
+                    firstArg = 0;
+
+                //if(typeInfo.Args[firstArg].Used)
+                    lp.PrimaryRadius = t.Args[firstArg];
+
+                //if(typeInfo.Args[4].Used)
+                    //lp.SecondaryRadius = t.Args[4];
+
+                //either both of them or none are used
+                if (showAllControls &&  Array.IndexOf(LIGHT_USES_ANGLE_VALUE, t.Type) != -1) {
+                    lp.SecondaryRadius = t.Args[4];
+                    lp.Interval = t.AngleDoom;
+                }
+
+                fixedValues.Add(lp);
+            }
+        }
+
+//events
+        private void colorPickerControl1_ColorChanged(object sender, ColorChangedEventArgs e) {
+            //need this check to allow relative mode to work properly
+            if ((byte)e.RGB.Red != lightProps.Red || (byte)e.RGB.Green != lightProps.Green || (byte)e.RGB.Blue != lightProps.Blue) {
+                updateLightPropsFromSliders();
+            }
+        }
+
+        private void colorPickerControl1_OnCancelPressed(object sender, EventArgs e) {
+            //undo changes
+            General.Map.UndoRedo.PerformUndo();
+            Close();
+        }
+
+        private void colorPickerControl1_OnOkPressed(object sender, EventArgs e) {
+            Close();
+        }
+
+        private void cbRelativeMode_CheckStateChanged(object sender, EventArgs e) {
+            RELATIVE_MODE = ((CheckBox)sender).Checked;
+            setControlsMode();
+        }
+
+        private void onSliderValueChanged(object sender, ColorPickerSliderEventArgs e) {
+            updateLightPropsFromSliders();
+        }
+    }
+
+    struct LightProps {
+        public byte Red;
+        public byte Green;
+        public byte Blue;
+
+        public int PrimaryRadius;
+        public int SecondaryRadius;
+        public int Interval;
+    }
+}
diff --git a/Source/Plugins/ColorPicker/Windows/LightColorPicker.resx b/Source/Plugins/ColorPicker/Windows/LightColorPicker.resx
new file mode 100644
index 0000000000000000000000000000000000000000..ff31a6db56e23b5a334f34387830ba5b4bd33eb8
--- /dev/null
+++ b/Source/Plugins/ColorPicker/Windows/LightColorPicker.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
diff --git a/Source/Plugins/ColorPicker/Windows/SectorColorPicker.Designer.cs b/Source/Plugins/ColorPicker/Windows/SectorColorPicker.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..bc37470de3b315b0e2806a50417607bb70ddf218
--- /dev/null
+++ b/Source/Plugins/ColorPicker/Windows/SectorColorPicker.Designer.cs
@@ -0,0 +1,104 @@
+namespace CodeImp.DoomBuilder.ColorPicker.Windows
+{
+    partial class SectorColorPicker
+    {
+        /// <summary>
+        /// Требуется переменная конструктора.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Освободить все используемые ресурсы.
+        /// </summary>
+        /// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
+        protected override void Dispose(bool disposing) {
+            if (disposing && (components != null)) {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Код, автоматически созданный конструктором форм Windows
+
+        /// <summary>
+        /// Обязательный метод для поддержки конструктора - не изменяйте
+        /// содержимое данного метода при помощи редактора кода.
+        /// </summary>
+        private void InitializeComponent() {
+            this.groupBox1 = new System.Windows.Forms.GroupBox();
+            this.rbFadeColor = new System.Windows.Forms.RadioButton();
+            this.rbSectorColor = new System.Windows.Forms.RadioButton();
+            this.colorPickerControl1 = new CodeImp.DoomBuilder.ColorPicker.Controls.ColorPickerControl();
+            this.groupBox1.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // groupBox1
+            // 
+            this.groupBox1.Controls.Add(this.rbFadeColor);
+            this.groupBox1.Controls.Add(this.rbSectorColor);
+            this.groupBox1.Location = new System.Drawing.Point(8, 212);
+            this.groupBox1.Name = "groupBox1";
+            this.groupBox1.Size = new System.Drawing.Size(311, 62);
+            this.groupBox1.TabIndex = 2;
+            this.groupBox1.TabStop = false;
+            this.groupBox1.Text = "Edit:";
+            // 
+            // rbFadeColor
+            // 
+            this.rbFadeColor.AutoSize = true;
+            this.rbFadeColor.Location = new System.Drawing.Point(7, 41);
+            this.rbFadeColor.Name = "rbFadeColor";
+            this.rbFadeColor.Size = new System.Drawing.Size(76, 18);
+            this.rbFadeColor.TabIndex = 1;
+            this.rbFadeColor.Tag = "fadecolor";
+            this.rbFadeColor.Text = "Fade color";
+            this.rbFadeColor.UseVisualStyleBackColor = true;
+            // 
+            // rbSectorColor
+            // 
+            this.rbSectorColor.AutoSize = true;
+            this.rbSectorColor.Checked = true;
+            this.rbSectorColor.Location = new System.Drawing.Point(7, 20);
+            this.rbSectorColor.Name = "rbSectorColor";
+            this.rbSectorColor.Size = new System.Drawing.Size(84, 18);
+            this.rbSectorColor.TabIndex = 0;
+            this.rbSectorColor.TabStop = true;
+            this.rbSectorColor.Tag = "lightcolor";
+            this.rbSectorColor.Text = "Sector color";
+            this.rbSectorColor.UseVisualStyleBackColor = true;
+            // 
+            // colorPickerControl1
+            // 
+            this.colorPickerControl1.Location = new System.Drawing.Point(8, 9);
+            this.colorPickerControl1.Name = "colorPickerControl1";
+            this.colorPickerControl1.Size = new System.Drawing.Size(311, 197);
+            this.colorPickerControl1.TabIndex = 1;
+            // 
+            // SectorColorPicker
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+            this.ClientSize = new System.Drawing.Size(327, 278);
+            this.Controls.Add(this.groupBox1);
+            this.Controls.Add(this.colorPickerControl1);
+            this.DoubleBuffered = true;
+            this.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
+            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
+            this.Name = "SectorColorPicker";
+            this.Opacity = 0;
+            this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
+            this.Text = "SectorColorPicker";
+            this.groupBox1.ResumeLayout(false);
+            this.groupBox1.PerformLayout();
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private CodeImp.DoomBuilder.ColorPicker.Controls.ColorPickerControl colorPickerControl1;
+        private System.Windows.Forms.GroupBox groupBox1;
+        private System.Windows.Forms.RadioButton rbFadeColor;
+        private System.Windows.Forms.RadioButton rbSectorColor;
+    }
+}
\ No newline at end of file
diff --git a/Source/Plugins/ColorPicker/Windows/SectorColorPicker.cs b/Source/Plugins/ColorPicker/Windows/SectorColorPicker.cs
new file mode 100644
index 0000000000000000000000000000000000000000..b242f5855e52990521975d726bb1628eb9bb3d95
--- /dev/null
+++ b/Source/Plugins/ColorPicker/Windows/SectorColorPicker.cs
@@ -0,0 +1,147 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+
+using CodeImp.DoomBuilder.Windows;
+using CodeImp.DoomBuilder.Map;
+using CodeImp.DoomBuilder.Config;
+using CodeImp.DoomBuilder.Types;
+using CodeImp.DoomBuilder.VisualModes;
+
+using CodeImp.DoomBuilder.Plugins;
+
+namespace CodeImp.DoomBuilder.ColorPicker.Windows
+{
+    public partial class SectorColorPicker : DelayedForm, IColorPicker
+    {
+        public ColorPickerType Type { get { return ColorPickerType.CP_SECTOR; } }
+
+        private List<Sector> selection;
+        
+        private int curSectorColor;
+        private int curFadeColor;
+        private int initialSectorColor;
+        private int initialFadeColor;
+        private int defaultSectorColor;
+        private int defaultFadeColor;
+
+        private static string currentColorTag = "lightcolor"; //lightcolor or fadecolor
+        private string mode;
+
+        public bool Setup(string editingModeName) {
+            mode = editingModeName;
+            selection = (List<Sector>)(General.Map.Map.GetSelectedSectors(true));
+
+            //create undo
+            string rest = selection.Count + " sector" + (selection.Count > 1 ? "s" : "");
+            General.Map.UndoRedo.CreateUndo("Edit color of " + rest);
+            
+            foreach (Sector s in selection)
+                s.Fields.BeforeFieldsChange();
+
+            //get default values
+            List<UniversalFieldInfo> sectorFields = General.Map.Config.SectorFields;
+            foreach (UniversalFieldInfo i in sectorFields) {
+                if (i.Name == "lightcolor")
+                    defaultSectorColor = (int)i.Default;
+                else if (i.Name == "fadecolor")
+                    defaultFadeColor = (int)i.Default;
+            }
+
+            //set colors
+            curSectorColor = selection[0].Fields.GetValue<int>("lightcolor", -1);
+            if (curSectorColor == -1) { //add lightcolor field
+                curSectorColor = defaultSectorColor;
+                selection[0].Fields.Add("lightcolor", new UniValue(UniversalType.Color, curSectorColor));
+            }
+            
+            curFadeColor = selection[0].Fields.GetValue<int>("fadecolor", -1);
+            if (curFadeColor == -1) { //add fadecolor field
+                curFadeColor = defaultFadeColor;
+                selection[0].Fields.Add("fadecolor", new UniValue(UniversalType.Color, curFadeColor));
+            }
+
+            initialSectorColor = curSectorColor;
+            initialFadeColor = curFadeColor;
+
+            InitializeComponent();
+
+            colorPickerControl1.ColorChanged += new EventHandler<ColorChangedEventArgs>(colorPickerControl1_ColorChanged);
+            colorPickerControl1.OnOkPressed += new EventHandler(colorPickerControl1_OnOkPressed);
+            colorPickerControl1.OnCancelPressed += new EventHandler(colorPickerControl1_OnCancelPressed);
+            colorPickerControl1.Initialize(Color.FromArgb(currentColorTag == "lightcolor" ? curSectorColor : curFadeColor));
+
+            if (currentColorTag == "lightcolor")
+                rbSectorColor.Checked = true;
+            else
+                rbFadeColor.Checked = true;
+
+            rbSectorColor.CheckedChanged += new EventHandler(rbColor_CheckedChanged);
+            rbFadeColor.CheckedChanged += new EventHandler(rbColor_CheckedChanged);
+
+            Text = "Editing " + rest;
+
+            //cannot fail here :)
+            return true;
+        }
+
+        private void colorPickerControl1_OnCancelPressed(object sender, EventArgs e) {
+            //restore initial values
+            General.Map.UndoRedo.PerformUndo();
+            Close();
+        }
+
+        private void colorPickerControl1_OnOkPressed(object sender, EventArgs e) {
+            //check if values are default
+            foreach (Sector s in selection) {
+                if ((int)s.Fields["lightcolor"].Value == defaultSectorColor)
+                    s.Fields.Remove("lightcolor");
+
+                if ((int)s.Fields["fadecolor"].Value == defaultFadeColor)
+                    s.Fields.Remove("fadecolor");
+            }
+            
+            Close();
+        }
+
+        private void colorPickerControl1_ColorChanged(object sender, ColorChangedEventArgs e) {
+            foreach (Sector s in selection) {
+                s.Fields[currentColorTag].Value = e.RGB.Red << 16 | e.RGB.Green << 8 | e.RGB.Blue;
+                s.UpdateNeeded = true;
+                s.UpdateCache();
+            }
+
+            //update display
+            if (mode == "SectorsMode") {
+                General.Interface.RedrawDisplay();
+            } else { //should be visual mode
+                VisualMode vm = (VisualMode)General.Editing.Mode;
+                
+                foreach (Sector s in selection) {
+                    if (vm.VisualSectorExists(s)) {
+                        VisualSector vs = vm.GetVisualSector(s);
+                        vs.UpdateSectorData();
+                    }
+                }
+            }
+        }
+
+        private void rbColor_CheckedChanged(object sender, EventArgs e) {
+            RadioButton b = (RadioButton)sender;
+            if (b.Checked) {
+                currentColorTag = (string)b.Tag;
+
+                //update color picker
+                if (currentColorTag == "lightcolor")
+                    colorPickerControl1.SetInitialColor(Color.FromArgb(initialSectorColor));
+                else
+                    colorPickerControl1.SetInitialColor(Color.FromArgb(initialFadeColor));
+                colorPickerControl1.SetCurrentColor(Color.FromArgb((int)selection[0].Fields[currentColorTag].Value));
+            }
+        }
+    }
+}
diff --git a/Source/Plugins/ColorPicker/Windows/SectorColorPicker.resx b/Source/Plugins/ColorPicker/Windows/SectorColorPicker.resx
new file mode 100644
index 0000000000000000000000000000000000000000..ff31a6db56e23b5a334f34387830ba5b4bd33eb8
--- /dev/null
+++ b/Source/Plugins/ColorPicker/Windows/SectorColorPicker.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
diff --git a/Source/Plugins/ColorPicker/Windows/ToolForm.Designer.cs b/Source/Plugins/ColorPicker/Windows/ToolForm.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..38c677590ed5c9f69d06269592f7adcd3dee1370
--- /dev/null
+++ b/Source/Plugins/ColorPicker/Windows/ToolForm.Designer.cs
@@ -0,0 +1,90 @@
+namespace CodeImp.DoomBuilder.ColorPicker
+{
+    partial class ToolsForm
+    {
+        /// <summary>
+        /// Требуется переменная конструктора.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Освободить все используемые ресурсы.
+        /// </summary>
+        /// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
+        protected override void Dispose(bool disposing) {
+            if (disposing && (components != null)) {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Код, автоматически созданный конструктором форм Windows
+
+        /// <summary>
+        /// Обязательный метод для поддержки конструктора - не изменяйте
+        /// содержимое данного метода при помощи редактора кода.
+        /// </summary>
+        private void InitializeComponent() {
+            this.toolStrip1 = new System.Windows.Forms.ToolStrip();
+            this.separator1 = new System.Windows.Forms.ToolStripSeparator();
+            this.cpButton = new System.Windows.Forms.ToolStripButton();
+            this.separator2 = new System.Windows.Forms.ToolStripSeparator();
+            this.toolStrip1.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // toolStrip1
+            // 
+            this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.separator1,
+            this.cpButton,
+            this.separator2});
+            this.toolStrip1.Location = new System.Drawing.Point(0, 0);
+            this.toolStrip1.Name = "toolStrip1";
+            this.toolStrip1.Size = new System.Drawing.Size(284, 25);
+            this.toolStrip1.TabIndex = 0;
+            this.toolStrip1.Text = "toolStrip1";
+            // 
+            // separator1
+            // 
+            this.separator1.Name = "separator1";
+            this.separator1.Size = new System.Drawing.Size(6, 25);
+            // 
+            // cpButton
+            // 
+            this.cpButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this.cpButton.Image = global::CodeImp.DoomBuilder.ColorPicker.Properties.Resources.cp;
+            this.cpButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.cpButton.Name = "cpButton";
+            this.cpButton.Size = new System.Drawing.Size(23, 22);
+            this.cpButton.Tag = "togglelightpannel";
+            this.cpButton.Text = "Color Picker";
+            this.cpButton.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
+            // separator2
+            // 
+            this.separator2.Name = "separator2";
+            this.separator2.Size = new System.Drawing.Size(6, 25);
+            // 
+            // ToolsForm
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(284, 262);
+            this.Controls.Add(this.toolStrip1);
+            this.Name = "ToolsForm";
+            this.Text = "ToolStrip";
+            this.toolStrip1.ResumeLayout(false);
+            this.toolStrip1.PerformLayout();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.ToolStrip toolStrip1;
+        private System.Windows.Forms.ToolStripButton cpButton;
+        private System.Windows.Forms.ToolStripSeparator separator1;
+        private System.Windows.Forms.ToolStripSeparator separator2;
+    }
+}
\ No newline at end of file
diff --git a/Source/Plugins/ColorPicker/Windows/ToolForm.cs b/Source/Plugins/ColorPicker/Windows/ToolForm.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a861b07b01b5fd7a9aac85e47243a1035ab9608f
--- /dev/null
+++ b/Source/Plugins/ColorPicker/Windows/ToolForm.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+
+using CodeImp.DoomBuilder;
+
+namespace CodeImp.DoomBuilder.ColorPicker
+{
+    public partial class ToolsForm : Form
+    {
+        public ToolsForm() {
+            InitializeComponent();
+
+            General.Interface.AddButton(separator1);
+            General.Interface.AddButton(cpButton);
+            General.Interface.AddButton(separator2);
+        }
+
+        private void InvokeTaggedAction(object sender, EventArgs e) {
+            General.Interface.InvokeTaggedAction(sender, e);
+        }
+    }
+}
diff --git a/Source/Plugins/ColorPicker/Windows/ToolForm.resx b/Source/Plugins/ColorPicker/Windows/ToolForm.resx
new file mode 100644
index 0000000000000000000000000000000000000000..36f2967b5c1d4c3261b1fba7d66b0b0a4e3033a7
--- /dev/null
+++ b/Source/Plugins/ColorPicker/Windows/ToolForm.resx
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
diff --git a/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualMode.cs b/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualMode.cs
index 154a0c9ad0807a1d3329c63d8db30249adb3e190..4c3e0381d5e8ffad77fce0d0bc091896827b9887 100644
--- a/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualMode.cs
+++ b/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualMode.cs
@@ -415,7 +415,7 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
 		}
 		
 		// This updates the VisualSectors and VisualThings that have their Changed property set
-		private void UpdateChangedObjects()
+        private void UpdateChangedObjects()
 		{
 			foreach(KeyValuePair<Sector, VisualSector> vs in allsectors)
 			{
diff --git a/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualSector.cs b/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualSector.cs
index e0c0a6d53a2b29fa680bf3cd336e38c51e62d8b7..4fa7f2bb0a0457639282d134d163c7aa6fa60ce3 100644
--- a/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualSector.cs
+++ b/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualSector.cs
@@ -117,7 +117,10 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
 		// This updates this virtual the sector and neightbours if needed
 		public void UpdateSectorGeometry(bool includeneighbours)
 		{
-			if(isupdating)
+			//mxd dbg
+            GZBuilder.GZGeneral.Trace("UpdateSectorGeometry isupdating=" + isupdating);
+            
+            if(isupdating)
 				return;
 				
 			isupdating = true;
@@ -169,6 +172,27 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
 			
 			isupdating = false;
 		}
+
+        //mxd. call this to update sector and things in it when Sector.Fields are changed 
+        override public void UpdateSectorData() {
+            //update sector data
+            SectorData data = GetSectorData();
+            data.Update(true);
+
+            //update sector
+            Rebuild();
+
+            //update things in this sector
+            foreach (Thing t in General.Map.Map.Things) {
+                if (t.Sector == this.Sector) {
+                    if (mode.VisualThingExists(t)) {
+                        // Update thing
+                        BaseVisualThing vt = (mode.GetVisualThing(t) as BaseVisualThing);
+                        vt.Rebuild();
+                    }
+                }
+            }
+        }
 		
 		// This (re)builds the visual sector, calculating all geometry from scratch
 		public void Rebuild()
diff --git a/Source/Plugins/GZDoomEditing/VisualModes/SectorData.cs b/Source/Plugins/GZDoomEditing/VisualModes/SectorData.cs
index cb7ccd5eef5c96bdb0a304e837e242c1fe509d20..423e38ff88d171ed900143272bf871c7079c8413 100644
--- a/Source/Plugins/GZDoomEditing/VisualModes/SectorData.cs
+++ b/Source/Plugins/GZDoomEditing/VisualModes/SectorData.cs
@@ -211,12 +211,18 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
 			ceiling.colorbelow = lightcolor.WithAlpha(255);
 		}
 
+        //mxd
+        public void Update(bool forced) {
+            updated = !forced;
+            Update();
+        }
+
 		// When no geometry has been changed and no effects have been added or removed,
 		// you can call this again to update existing effects. The effects will update
 		// the existing SectorLevels to match with any changes.
 		public void Update()
 		{
-			if(isupdating || updated) return;
+            if(isupdating || updated) return;
 			isupdating = true;
 			
 			// Set floor/ceiling to their original setup