diff --git a/Source/Core/Builder.csproj b/Source/Core/Builder.csproj
index c06dc53540d57a12047244a67ea090d333caeb87..68e292f789725b50418cdeac5e5826adfa558da5 100644
--- a/Source/Core/Builder.csproj
+++ b/Source/Core/Builder.csproj
@@ -796,6 +796,8 @@
     <None Include="Resources\Angle.png" />
     <Content Include="Resources\DB2.ico" />
     <None Include="Resources\GZDB2.ico" />
+    <None Include="Resources\fog.png" />
+    <None Include="Resources\fx.png" />
     <Content Include="Resources\Light.png" />
     <Content Include="Resources\Light_animate.png" />
     <Content Include="Resources\Model.png" />
diff --git a/Source/Core/Builder.sln b/Source/Core/Builder.sln
index 754c0063434b1a105f150b3bc8024132ab0d02ee..8b5d3259a8534dd34cb83c72226afb26b87891cf 100644
--- a/Source/Core/Builder.sln
+++ b/Source/Core/Builder.sln
@@ -5,10 +5,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Builder", "Builder.csproj",
 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
@@ -29,38 +25,16 @@ Global
 		{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|Any CPU.ActiveCfg = Debug|x86
+		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Debug|Mixed Platforms.Build.0 = Debug|x86
 		{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|Any CPU.ActiveCfg = Release|x86
+		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|Mixed Platforms.ActiveCfg = Release|x86
+		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|Mixed Platforms.Build.0 = Release|x86
 		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|x86.ActiveCfg = Release|x86
 		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|x86.Build.0 = Release|x86
-		{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/GZGeneral.cs b/Source/Core/GZBuilder/GZGeneral.cs
index 0507f1e85467d3bb722ce38800ddbc749f95ad50..17c5797c912508aa90b907fdae6d81b37272186e 100644
--- a/Source/Core/GZBuilder/GZGeneral.cs
+++ b/Source/Core/GZBuilder/GZGeneral.cs
@@ -32,9 +32,10 @@ namespace CodeImp.DoomBuilder.GZBuilder
         private static int[] gzAnimatedLightTypes = { (int)GZDoomLightType.FLICKER, (int)GZDoomLightType.RANDOM, (int)GZDoomLightType.PULSE };
         public static int[] GZ_ANIMATED_LIGHT_TYPES {  get { return gzAnimatedLightTypes; } }
 
+        public static bool UDMF;
 
         //version
-        public const float Version = 1.05f;
+        public const float Version = 1.06f;
 
         //debug console
 #if DEBUG
@@ -59,6 +60,7 @@ namespace CodeImp.DoomBuilder.GZBuilder
         public static void OnMapOpenEnd() {
             loadModelDefs();
             loadModels();
+            UDMF = (General.Map.Config.FormatInterface == "UniversalMapSetIO");
             General.MainWindow.UpdateGZDoomPannel();
         }
 
@@ -71,13 +73,11 @@ namespace CodeImp.DoomBuilder.GZBuilder
 #endif
         }
 
-        //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)) {
-                General.ErrorLogger.Add(ErrorType.Warning, "GZBuilder: got model override for thing id " + t.Type);
+                string msg = "GZBuilder: got model override for Thing â„–" + t.Type;
+                General.ErrorLogger.Add(ErrorType.Warning, msg);
+                General.WriteLogLine(msg);
 
                 if (modelDefEntries[t.Type].Model == null) {
                     //load model and texture
@@ -85,11 +85,18 @@ namespace CodeImp.DoomBuilder.GZBuilder
                     mde.Model = ModelReader.Parse(mde, General.Map.Graphics.Device);
 
                     if (mde.Model != null) {
-                        General.Map.IsChanged = true; //update display
-                        General.ErrorLogger.Add(ErrorType.Warning, "GZBuilder: loaded model for thing id " + t.Type);
+                        //General.Map.IsChanged = true; 
+                        //General.MainWindow.RedrawDisplay(); //update display
+                        msg = "GZBuilder: loaded model for Thing â„–" + t.Type;
+                        General.ErrorLogger.Add(ErrorType.Warning, msg);
+                        General.WriteLogLine(msg);
                         return true;
                     } else {
-                        General.ErrorLogger.Add(ErrorType.Warning, "GZBuilder: failed to load model(s) for thing id " + t.Type + ". Node removed.");
+                        modelDefEntries.Remove(t.Type);
+                        msg = "GZBuilder: failed to load model(s) for Thing â„–" + t.Type + ". ModelDef node removed.";
+                        General.ErrorLogger.Add(ErrorType.Warning, msg);
+                        General.WriteLogLine(msg);
+                        return false;
                     }
                 }
                 return true;
@@ -99,6 +106,8 @@ namespace CodeImp.DoomBuilder.GZBuilder
 
 //functions
         private static void loadModelDefs() {
+            General.MainWindow.DisplayStatus(StatusType.Busy, "Parsing model definitions...");
+
             Dictionary<string, int> Actors = new Dictionary<string,int>();
             Dictionary<int, ThingTypeInfo> things = General.Map.Config.GetThingTypes();
 
@@ -111,8 +120,9 @@ namespace CodeImp.DoomBuilder.GZBuilder
             //and for actors defined in DECORATE
             ICollection<ActorStructure> ac = General.Map.Data.Decorate.Actors;
             foreach (ActorStructure actor in ac) {
-                if (actor.DoomEdNum != -1) //we don't need actors without DoomEdNum
-                    Actors.Add(actor.ClassName.ToLower(), actor.DoomEdNum);
+                string className = actor.ClassName.ToLower();
+                if (actor.DoomEdNum != -1 && !Actors.ContainsKey(className)) //we don't need actors without DoomEdNum
+                    Actors.Add(className, actor.DoomEdNum);
             }
 
             Dictionary<string, ModelDefEntry> modelDefEntriesByName = new Dictionary<string, ModelDefEntry>();
@@ -126,17 +136,24 @@ namespace CodeImp.DoomBuilder.GZBuilder
                 if (Actors.ContainsKey(e.Value.Name)) {
                     modelDefEntries[Actors[e.Value.Name]] = modelDefEntriesByName[e.Value.Name];
                 } else {
-                    General.ErrorLogger.Add(ErrorType.Warning, "GZBuilder: ModelDefEntry wasn't found in Decorate: '" + e.Value.Name + "'");
+                    string msg = "GZBuilder: ModelDefEntry wasn't found in Decorate: '" + e.Value.Name + "'";
+                    General.ErrorLogger.Add(ErrorType.Warning, msg);
+                    General.WriteLogLine(msg);
                 }
             }
         }
 
         //load models for things which are already in the map
         private static void loadModels() {
-            General.ErrorLogger.Add(ErrorType.Warning, "GZBuilder: loading models...");
+            General.MainWindow.DisplayStatus(StatusType.Busy, "Loading models...");
+            string msg = "GZBuilder: loading models...";
+            General.ErrorLogger.Add(ErrorType.Warning, msg);
+            General.WriteLogLine(msg);
             
             foreach(Thing t in General.Map.Map.Things)
                 LoadModelForThing(t);
+
+            General.MainWindow.RedrawDisplay();
         }
 
 //debug
@@ -165,68 +182,60 @@ namespace CodeImp.DoomBuilder.GZBuilder
 //actions
         [BeginAction("gztogglemodels")]
         private static void toggleModels() {
-            ToggleModels();
-            General.MainWindow.UpdateGZDoomPannel();
-        }
-
-        public static void ToggleModels() {
             General.Settings.GZDrawModels = !General.Settings.GZDrawModels;
             General.MainWindow.DisplayStatus(StatusType.Action, "MD3 models rendering is " + (General.Settings.GZDrawModels ? "ENABLED" : "DISABLED"));
             General.MainWindow.RedrawDisplay();
+            General.MainWindow.UpdateGZDoomPannel();
         }
 
         [BeginAction("gztogglelights")]
         private static void toggleLights() {
-            ToggleLights();
-            General.MainWindow.UpdateGZDoomPannel();
-        }
-
-        public static void ToggleLights() {
             General.Settings.GZDrawLights = !General.Settings.GZDrawLights;
             General.MainWindow.DisplayStatus(StatusType.Action, "Dynamic lights rendering is " + (General.Settings.GZDrawLights ? "ENABLED" : "DISABLED"));
             General.MainWindow.RedrawDisplay();
+            General.MainWindow.UpdateGZDoomPannel();
         }
 
         [BeginAction("gztogglelightsanimation")]
         private static void toggleLightsAnimation() {
-            ToggleLightsAnimation();
-            General.MainWindow.UpdateGZDoomPannel();
-        }
-        public static void ToggleLightsAnimation() {
             General.Settings.GZAnimateLights = !General.Settings.GZAnimateLights;
             General.MainWindow.DisplayStatus(StatusType.Action, "Dynamic lights animation is " + (General.Settings.GZAnimateLights ? "ENABLED" : "DISABLED"));
             General.MainWindow.RedrawDisplay();
+            General.MainWindow.UpdateGZDoomPannel();
         }
 
         [BeginAction("gztogglefog")]
         private static void toggleFog() {
-            ToggleFog();
-            General.MainWindow.UpdateGZDoomPannel();
-        }
-
-        public static void ToggleFog() {
             General.Settings.GZDrawFog = !General.Settings.GZDrawFog;
-            General.MainWindow.DisplayStatus(StatusType.Action, "Colored fog rendering is " + (General.Settings.GZDrawFog ? "ENABLED" : "DISABLED"));
+            General.MainWindow.DisplayStatus(StatusType.Action, "Fog rendering is " + (General.Settings.GZDrawFog ? "ENABLED" : "DISABLED"));
             General.MainWindow.RedrawDisplay();
-            General.ShowWarningMessage("Not implemented yet...", MessageBoxButtons.OK);
+            General.MainWindow.UpdateGZDoomPannel();
         }
 
-
         [BeginAction("gzdrawselectedmodelsonly")]
         private static void toggleDrawSelectedModelsOnly() {
-            ToggleDrawSelectedModelsOnly();
-            General.MainWindow.UpdateGZDoomPannel();
-        }
-
-        public static void ToggleDrawSelectedModelsOnly() {
             General.Settings.GZDrawSelectedModelsOnly = !General.Settings.GZDrawSelectedModelsOnly;
             General.MainWindow.DisplayStatus(StatusType.Action, "Rendering " + (General.Settings.GZDrawSelectedModelsOnly ? "only selected" : "all") + " models.");
             General.MainWindow.RedrawDisplay();
+            General.MainWindow.UpdateGZDoomPannel();
         }
 
-        [BeginAction("gztogglefogpannel")]
-        public static void ToggleFogPannel() {
-            General.ShowWarningMessage("Not implemented yet...", MessageBoxButtons.OK);
+        [BeginAction("gztogglefx")]
+        private static void toggleFx() {
+            int on = 0;
+            on += General.Settings.GZDrawFog ? 1 : -1;
+            on += General.Settings.GZDrawLights ? 1 : -1;
+            on += General.Settings.GZDrawModels ? 1 : -1;
+
+            bool enable = (on < 0);
+
+            General.Settings.GZDrawFog = enable;
+            General.Settings.GZDrawLights = enable;
+            General.Settings.GZDrawModels = enable;
+            General.MainWindow.DisplayStatus(StatusType.Action, "Advanced effects are " + (enable ? "ENABLED" : "DISABLED") );
+
+            General.MainWindow.RedrawDisplay();
+            General.MainWindow.UpdateGZDoomPannel();
         }
     }
 }
diff --git a/Source/Core/GZBuilder/IO/ModelDefParser.cs b/Source/Core/GZBuilder/IO/ModelDefParser.cs
index a5852838b6ac9651353ab23faa208ed3d71425a9..4e799e542761dde70530dfb1167e9fce6bcdb89d 100644
--- a/Source/Core/GZBuilder/IO/ModelDefParser.cs
+++ b/Source/Core/GZBuilder/IO/ModelDefParser.cs
@@ -8,6 +8,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.IO
 {
     class ModelDefParser
     {
+        public static string INVALID_TEXTURE = "**INVALID_TEXTURE**";
+        private static string[] SUPPORTED_TEXTURE_EXTENSIONS = { ".jpg", ".tga", ".png", ".dds", ".bmp" };
+        
         public static void ParseFolder(Dictionary<string, ModelDefEntry> modelDefEntriesByName, string path) {
             string[] files = Directory.GetFiles(path);
 
@@ -16,21 +19,13 @@ namespace CodeImp.DoomBuilder.GZBuilder.IO
                     Parse(modelDefEntriesByName, path, fileName);
             }
 
-            #if DEBUG
-                General.ErrorLogger.Add(ErrorType.Warning, "ModelDefParser: parsed " + modelDefEntriesByName.Count + " definitions;");
-            #else
-                General.WriteLogLine("ModelDefParser: parsed " + modelDefEntriesByName.Count + " definitions;");
-            #endif
+            logAndTrace("ModelDefParser: parsed " + modelDefEntriesByName.Count + " definitions;");
         }
 
         public static void Parse(Dictionary<string, ModelDefEntry> modelDefEntriesByName, string path, string fileName) {
-            #if DEBUG
-                General.ErrorLogger.Add(ErrorType.Warning, "ModelDefParser: Parsing '" + fileName + "'");
-            #else
-				General.WriteLogLine("ModelDefParser: Parsing '" + fileName + "'");
-            #endif
+            logAndTrace("ModelDefParser: Parsing '" + fileName + "'");
 
-                if (File.Exists(fileName)) {
+            if (File.Exists(fileName)) {
                 StreamReader s = File.OpenText(fileName);
                 string contents = s.ReadToEnd();
                 s.Close();
@@ -46,11 +41,14 @@ namespace CodeImp.DoomBuilder.GZBuilder.IO
                 }
 
             } else {
-                General.WriteLogLine("File '" + fileName + "' doesn't exist!");
+                logAndTrace("ModelDefParser: File '" + fileName + "' doesn't exist!");
             }
         }
 
         private static void parseModelDef(Dictionary<string, ModelDefEntry> modelDefEntriesByName, string path, string modelDef) {
+            string[] modelNames = new string[16];
+            string[] textureNames = new string[16];
+            
             string[] lines = modelDef.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
             char[] space = new char[] { ' ' };
             string[] parts = lines[0].Split(space, StringSplitOptions.RemoveEmptyEntries);
@@ -70,46 +68,89 @@ namespace CodeImp.DoomBuilder.GZBuilder.IO
                 if (parts.Length > 0) {
                     string s = parts[0].Trim();
 
-                    switch (s) {
-                        case "frameindex":
-                            if (mde.Name != String.Empty && mde.Path != String.Empty && mde.ModelNames.Count > 0 && mde.TextureNames.Count > 0) {
-                                modelDefEntriesByName[mde.Name] = mde;
-                            } else {
-                                General.ErrorLogger.Add(ErrorType.Warning, "Error while parsing ModelDef. Not all required fileds are present." + Environment.NewLine + "Parsed data: [" + Environment.NewLine + ModelDefEntry_ToString(mde) + "]" + Environment.NewLine);
-                                return;
+                    //LOTS of boilerplate! Yay!!!
+                    if (s.IndexOf("frameindex") != -1) {
+                        if (mde.Name != String.Empty && mde.Path != String.Empty) {
+                            for (int c = 0; c < modelNames.Length; c++) {
+                                if (modelNames[c] != null && textureNames[c] != null) {
+                                    mde.ModelNames.Add(modelNames[c]);
+                                    mde.TextureNames.Add(textureNames[c]);
+                                }
                             }
-                            break;
-
-                        case "model":
-                            string fileName = parts[2].Trim(splitter);
-                            //string fileExt = fileName.Substring(fileName.Length - 4);
-                            string fileExt = Path.GetExtension(fileName);
-                            
-                            if(fileExt == ".md3" || fileExt == ".md2"){
-                                mde.ModelNames.Add(fileName);
-                            }else{
-                                General.ErrorLogger.Add(ErrorType.Warning, "Model '" + fileName + "' not parsed. Only MD3 and MD2 models are supported.");
+
+                            if (mde.ModelNames.Count > 0 && mde.TextureNames.Count > 0)
+                                modelDefEntriesByName[mde.Name] = mde;
+                            else
+                                logAndTrace("Error while parsing ModelDef. Not all required fileds are present." + Environment.NewLine + "Parsed data: [" + Environment.NewLine + ModelDefEntry_ToString(mde) + "]" + Environment.NewLine);
+                            return; //we don't want to parse all frames
+  
+                        } 
+                        logAndTrace("Error while parsing ModelDef. Not all required fileds are present." + Environment.NewLine + "Parsed data: [" + Environment.NewLine + ModelDefEntry_ToString(mde) + "]" + Environment.NewLine);
+                        return;
+
+                    } else if (s.IndexOf("model") != -1) {
+                        if (parts.Length != 3) {
+                            logAndTrace("Incorrect syntax in 'model' token for class '" + name + "': expected 3 entries, but got " + parts.Length + "!");
+                            return;
+                        }
+
+                        int fileIndex = int.Parse(parts[1].Trim(splitter), NumberStyles.Integer);
+                        string fileName = parts[2].Trim(splitter);
+                        string fileExt = Path.GetExtension(fileName);
+
+                        if (fileExt == ".md3" || fileExt == ".md2") {
+                            if (modelNames[fileIndex] != null) {
+                                logAndTrace("Incorrect syntax in 'model' token for class '" + name + "': already got model with index " + fileIndex + "!");
                                 return;
                             }
-                            break;
-
-                        case "path":
-                            mde.Path = path + "\\" + parts[1].Trim(splitter).Replace("/", "\\");
-                            break;
-
-                        case "skin":
-                            mde.TextureNames.Add(parts[2].Trim(splitter));
-                            break;
-
-                        case "scale":
-                            mde.Scale.X = float.Parse(parts[1], NumberStyles.Float);
-                            mde.Scale.Y = float.Parse(parts[2], NumberStyles.Float);
-                            mde.Scale.Z = float.Parse(parts[3], NumberStyles.Float);
-                            break;
-
-                        case "zoffset":
-                            mde.zOffset = float.Parse(parts[1], NumberStyles.Float);
-                            break;
+                            modelNames[fileIndex] = fileName;
+
+                        } else {
+                            logAndTrace("Model '" + fileName + "' not parsed. Only MD3 and MD2 models are supported.");
+                            return;
+                        }
+
+                    } else if (s.IndexOf("path") != -1) {
+                        if (parts.Length != 2) {
+                            logAndTrace("Incorrect syntax in 'path' token for class '" + name + "': expected 2 entries, but got " + parts.Length + "!");
+                            return;
+                        }
+
+                        mde.Path = path + "\\" + parts[1].Trim(splitter).Replace("/", "\\");
+
+                    } else if (s.IndexOf("skin") != -1) {
+                        if (parts.Length != 3) {
+                            logAndTrace("Incorrect syntax in 'skin' token for class '" + name + "': expected 3 entries, but got " + parts.Length + "!");
+                            return;
+                        }
+
+                        int index = int.Parse(parts[1].Trim(splitter), NumberStyles.Integer);
+                        if (textureNames[index] != null) {
+                            logAndTrace("Incorrect syntax in 'skin' token for class '" + name + "': already got skin with index " + index + "!");
+                            return;
+                        }
+
+                        string textureName = parts[2].Trim(splitter);
+                        string fileExt = Path.GetExtension(textureName);
+                        textureNames[index] = Array.IndexOf(SUPPORTED_TEXTURE_EXTENSIONS, fileExt) == -1 ? INVALID_TEXTURE : textureName;
+
+                    } else if (s.IndexOf("scale") != -1) {
+                        if (parts.Length != 4) {
+                            logAndTrace("Incorrect syntax in 'scale' token for class '" + name + "': expected 4 entries, but got " + parts.Length + "!");
+                            return;
+                        }
+
+                        mde.Scale.X = float.Parse(parts[1], NumberStyles.Float);
+                        mde.Scale.Y = float.Parse(parts[2], NumberStyles.Float);
+                        mde.Scale.Z = float.Parse(parts[3], NumberStyles.Float);
+
+                    } else if (s.IndexOf("zoffset") != -1) {
+                        if (parts.Length != 2) {
+                            logAndTrace("Incorrect syntax in 'zoffset' token for class '" + name + "': expected 2 entries, but got " + parts.Length + "!");
+                            return;
+                        }
+
+                        mde.zOffset = float.Parse(parts[1], NumberStyles.Float);
                     }
                 }
             }
@@ -122,13 +163,12 @@ namespace CodeImp.DoomBuilder.GZBuilder.IO
             string[] textures = new string[mde.TextureNames.Count];
             mde.TextureNames.CopyTo(textures);
 
-            string s = "Name: " + mde.Name + Environment.NewLine
-                       + "Path: " + mde.Path + Environment.NewLine
-                       + "Models: " + String.Join(", ", models) + Environment.NewLine
-                       + "Textures: " + String.Join(", ", textures) + Environment.NewLine
-                       + "Scale: " + mde.Scale + Environment.NewLine
-                       + "zOffset: " + mde.zOffset + Environment.NewLine;
-            return s;
+            return "Name: " + mde.Name + Environment.NewLine
+                   + "Path: " + mde.Path + Environment.NewLine
+                   + "Models: " + String.Join(", ", models) + Environment.NewLine
+                   + "Skins: " + String.Join(", ", textures) + Environment.NewLine
+                   + "Scale: " + mde.Scale + Environment.NewLine
+                   + "zOffset: " + mde.zOffset + Environment.NewLine;
         }
 
         private static string StripComments(string contents) {
@@ -148,5 +188,10 @@ namespace CodeImp.DoomBuilder.GZBuilder.IO
 
             return contents;
         }
+
+        private static void logAndTrace(string message) {
+            General.ErrorLogger.Add(ErrorType.Warning, message);
+            General.WriteLogLine(message);
+        }
     }
 }
\ No newline at end of file
diff --git a/Source/Core/GZBuilder/md3/GZModel.cs b/Source/Core/GZBuilder/md3/GZModel.cs
index 27cc345d3634da9a915337779ead9bcb25949e88..a9193119b1d436d61ff1b82c735167be4b838597 100644
--- a/Source/Core/GZBuilder/md3/GZModel.cs
+++ b/Source/Core/GZBuilder/md3/GZModel.cs
@@ -7,23 +7,17 @@ using CodeImp.DoomBuilder.Geometry;
 namespace ColladaDotNet.Pipeline.MD3
 {
     public class GZModel {
-        /*public List<Mesh> meshes;
-        public List<Texture> textures;
-        public List<short> indeces2D;
-        public List<Vector2D> verts2D;
-        public int NUM_MESHES = 0;*/
         public List<Mesh> Meshes;
         public List<Texture> Textures;
         public byte NUM_MESHES = 0; //can't be greater than 255, can it?
         public Vector3[] BoundingBox;
         public List<IndexBuffer> Indeces2D;
         public List<short> NumIndeces2D;
+        public float Angle = 0; //crappy way to set rotation to md2 models...
 
         public GZModel() {
             Meshes = new List<Mesh>();
             Textures = new List<Texture>();
-            //indeces2D = new List<short>();
-            //verts2D = new List<Vector2D>();
             Indeces2D = new List<IndexBuffer>();
             NumIndeces2D = new List<short>();
         }
diff --git a/Source/Core/GZBuilder/md3/ModelReader.cs b/Source/Core/GZBuilder/md3/ModelReader.cs
index ef87e06229cfd12284088b94a83d07fee88b0a0b..02851523f602d90a5c9c7650e8af76525459be1f 100644
--- a/Source/Core/GZBuilder/md3/ModelReader.cs
+++ b/Source/Core/GZBuilder/md3/ModelReader.cs
@@ -7,6 +7,7 @@ using System.Collections.Generic;
 using CodeImp.DoomBuilder;
 using CodeImp.DoomBuilder.Rendering;
 using CodeImp.DoomBuilder.GZBuilder.Data;
+using CodeImp.DoomBuilder.GZBuilder.IO;
 
 using SlimDX;
 using SlimDX.Direct3D9;
@@ -32,24 +33,27 @@ namespace ColladaDotNet.Pipeline.MD3 {
             BoundingBoxSizes bbs = new BoundingBoxSizes();
 
             for (int i = 0; i < modelPaths.Length; i++) {
-                if (File.Exists(mde.Path + "\\" + modelPaths[i])) {
-                    General.WriteLogLine("MD3Reader: loading '" + mde.Path + "\\" + modelPaths[i] + "'");
+                string modelPath = mde.Path + "\\" + modelPaths[i];
+                if (File.Exists(modelPath)) {
+                    General.WriteLogLine("MD3Reader: loading '" + modelPath + "'");
                     //mesh
                     string ext = modelPaths[i].Substring(modelPaths[i].Length - 4);
                     bool loaded = false;
                     if (ext == ".md3") {
-                        loaded = ReadMD3Model(ref bbs, mde, model, mde.Path + "\\" + modelPaths[i], D3DDevice);
+                        loaded = ReadMD3Model(ref bbs, mde, model, modelPath, D3DDevice);
                     } else if (ext == ".md2") {
-                        loaded = ReadMD2Model(ref bbs, mde, model, mde.Path + "\\" + modelPaths[i], D3DDevice);
+                        loaded = ReadMD2Model(ref bbs, mde, model, modelPath, D3DDevice);
                     }
 
                     //texture
                     if (loaded) {
-                        if (File.Exists(mde.Path + "\\" + texturePaths[i])) {
-                            model.Textures.Add(Texture.FromFile(D3DDevice, mde.Path + "\\" + texturePaths[i]));
+                        string texturePath = mde.Path + "\\" + texturePaths[i];
+                        if (texturePaths[i] != ModelDefParser.INVALID_TEXTURE && File.Exists(texturePath)) {
+                            model.Textures.Add(Texture.FromFile(D3DDevice, texturePath));
                         } else {
                             model.Textures.Add(General.Map.Data.UnknownTexture3D.Texture);
-                            General.ErrorLogger.Add(ErrorType.Warning, "MD3Reader: unable to load texture '" + mde.Path + "\\" + texturePaths[i] + "' - no such file");
+                            if (texturePaths[i] != ModelDefParser.INVALID_TEXTURE)
+                                General.ErrorLogger.Add(ErrorType.Warning, "MD3Reader: unable to load texture '" + texturePath + "' - no such file");
                         }
                     } else {
                         model.NUM_MESHES--;
@@ -73,8 +77,9 @@ namespace ColladaDotNet.Pipeline.MD3 {
             long start = s.Position;
 
             using (var br = new BinaryReader(s, Encoding.ASCII)) {
-                if (ReadString(br, 4) != "IDP3") {
-                    General.ErrorLogger.Add(ErrorType.Warning, "MD3Reader: Error while loading '" + modelPath + "': Magic should be IDP3");
+                string magic = ReadString(br, 4);
+                if (magic != "IDP3") {
+                    General.ErrorLogger.Add(ErrorType.Warning, "MD3Reader: Error while loading '" + modelPath + "': Magic should be 'IDP3', not '" + magic + "'");
                     return false;
                 }
 
@@ -123,9 +128,9 @@ namespace ColladaDotNet.Pipeline.MD3 {
 
         private static void ReadSurface(ref BoundingBoxSizes bbs, BinaryReader br, List<short> polyIndecesList, List<WorldVertex> vertList, ModelDefEntry mde) {
             var start = br.BaseStream.Position;
-
-            if (ReadString(br, 4) != "IDP3") {
-                General.ErrorLogger.Add(ErrorType.Warning, "MD3Reader: Error while reading surface: Magic should be IDP3");
+            string magic = ReadString(br, 4);
+            if (magic != "IDP3") {
+                General.ErrorLogger.Add(ErrorType.Warning, "MD3Reader: Error while reading surface: Magic should be 'IDP3', not '" + magic + "'");
                 return;
             }
 
@@ -194,13 +199,14 @@ namespace ColladaDotNet.Pipeline.MD3 {
             long start = s.Position;
 
             using (var br = new BinaryReader(s, Encoding.ASCII)) {
-                if (ReadString(br, 4) != "IDP2") { //magic number: "IDP2"
-                    General.ErrorLogger.Add(ErrorType.Warning, "MD3Reader: Error while loading '" + modelPath + "': Magic should be IDP2");
+                string magic = ReadString(br, 4);
+                if (magic != "IDP2") { //magic number: "IDP2"
+                    General.ErrorLogger.Add(ErrorType.Warning, "MD3Reader: Error while loading '" + modelPath + "': Magic should be 'IDP2', not '" + magic + "'");
                     return false;
                 }
                 int modelVersion = br.ReadInt32();
                 if (modelVersion != 8) { //MD2 version. Must be equal to 8
-                    General.ErrorLogger.Add(ErrorType.Warning, "MD3Reader: Error while loading '" + modelPath + "': MD2 version must be equal to 8 but is " + modelVersion);
+                    General.ErrorLogger.Add(ErrorType.Warning, "MD3Reader: Error while loading '" + modelPath + "': MD2 version must be 8 but is " + modelVersion);
                     return false;
                 }
 
@@ -278,7 +284,8 @@ namespace ColladaDotNet.Pipeline.MD3 {
                     WorldVertex v = vertList[polyIndecesList[i]];
                     
                     //bounding box
-                    BoundingBoxTools.UpdateBoundingBoxSizes(ref bbs, v);
+                    //BoundingBoxTools.UpdateBoundingBoxSizes(ref bbs, v);
+                    BoundingBoxTools.UpdateBoundingBoxSizes(ref bbs, new WorldVertex(v.y, v.x, v.z));
 
                     //uv
                     v.u = uvCoordsList[uvIndecesList[i]].X;
@@ -312,6 +319,7 @@ namespace ColladaDotNet.Pipeline.MD3 {
 
                 model.Indeces2D.Add(indeces2d);
                 model.NumIndeces2D.Add((short)polyIndecesList.Count);
+                model.Angle = -90.0f * (float)Math.PI / 180.0f;
 
                 return true;
             }
diff --git a/Source/Core/Properties/Resources.Designer.cs b/Source/Core/Properties/Resources.Designer.cs
index 5cc3d18a9763b9393e7de20eed5f22e8412edf22..87f1b48ef57b119d42d36090080ba042ee72dd94 100644
--- a/Source/Core/Properties/Resources.Designer.cs
+++ b/Source/Core/Properties/Resources.Designer.cs
@@ -130,6 +130,13 @@ namespace CodeImp.DoomBuilder.Properties {
             }
         }
         
+        internal static System.Drawing.Bitmap fog {
+            get {
+                object obj = ResourceManager.GetObject("fog", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
         internal static System.Drawing.Bitmap Folder {
             get {
                 object obj = ResourceManager.GetObject("Folder", resourceCulture);
@@ -137,6 +144,13 @@ namespace CodeImp.DoomBuilder.Properties {
             }
         }
         
+        internal static System.Drawing.Bitmap fx {
+            get {
+                object obj = ResourceManager.GetObject("fx", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
         internal static System.Drawing.Bitmap Grid2 {
             get {
                 object obj = ResourceManager.GetObject("Grid2", resourceCulture);
diff --git a/Source/Core/Properties/Resources.resx b/Source/Core/Properties/Resources.resx
index 136f30efb235786927b4932eec2df720a6f25aa9..1c2fbb48adfbf89aecc1858dfcafdb73dfdc90d9 100644
--- a/Source/Core/Properties/Resources.resx
+++ b/Source/Core/Properties/Resources.resx
@@ -337,4 +337,10 @@
   <data name="GZDB2" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\Resources\GZDB2.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
+  <data name="fog" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\fog.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="fx" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\fx.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/Core/Rendering/Renderer2D.cs b/Source/Core/Rendering/Renderer2D.cs
index 5893fd50ed678e819abf77c4b2d1ecaefb0ad0b3..ffd4def12f5e8252b83053243ef2c6e46570282d 100644
--- a/Source/Core/Rendering/Renderer2D.cs
+++ b/Source/Core/Rendering/Renderer2D.cs
@@ -1122,7 +1122,7 @@ namespace CodeImp.DoomBuilder.Rendering
                         ModelDefEntry mde = GZBuilder.GZGeneral.ModelDefEntries[group.Value.Type];
 
                         if (mde.Model != null)
-                            RenderModel(mde.Model, group.Key, group.Value.Angle, group.Value.Selected);
+                            RenderModel(mde.Model, group.Key, group.Value.Angle + mde.Model.Angle, group.Value.Selected);
                         else
                             group.Value.IsModel = GZBuilder.GZGeneral.LoadModelForThing(group.Value);
                     }
diff --git a/Source/Core/Rendering/Renderer3D.cs b/Source/Core/Rendering/Renderer3D.cs
index e2c4e41e3d9841d41f2b54ed8aa2d4b5225e5345..c24cc870c3035c91f7be74339f23f9ad5fe10b26 100644
--- a/Source/Core/Rendering/Renderer3D.cs
+++ b/Source/Core/Rendering/Renderer3D.cs
@@ -523,7 +523,10 @@ namespace CodeImp.DoomBuilder.Rendering
 		// This ends rendering world geometry
 		public void FinishGeometry()
 		{
-			//mxd. sort lights
+			//dbg
+            //GZBuilder.GZGeneral.ClearTrace();
+            
+            //mxd. sort lights
             if (General.Settings.GZDrawLights && !fullbrightness && thingsWithLight.Count > 0)
                 updateLights();
             
@@ -634,7 +637,7 @@ namespace CodeImp.DoomBuilder.Rendering
             //mxd. Doesn't look nearly as good as I expected :(
             //graphics.Device.SetRenderState(RenderState.AntialiasedLineEnable, General.Settings.QualityDisplay);
 
-            graphics.Shaders.World3D.BeginPass(8);
+            graphics.Shaders.World3D.BeginPass(16);
 
             foreach (VisualThing t in thingsbydistance) {
                 // Setup matrix
@@ -740,6 +743,10 @@ namespace CodeImp.DoomBuilder.Rendering
 						// Determine the shader pass we want to use for this object
 						int wantedshaderpass = (((g == highlighted) && showhighlight) || (g.Selected && showselection)) ? highshaderpass : shaderpass;
 
+                        //mxd
+                        if (General.Settings.GZDrawFog && !fullbrightness && sector.Sector.Brightness < 248)
+                            wantedshaderpass += 8;
+
                         //mxd. Seems that lines rendered with RenderPass.Alpha or RenderPass.Additive aren't affected by dynamic lights in GZDoom
                         if (g.RenderPass != RenderPass.Alpha && g.RenderPass != RenderPass.Additive && General.Settings.GZDrawLights && !fullbrightness && thingsWithLight.Count > 0) {
                             if (curtexture.Texture != null) {
@@ -765,6 +772,21 @@ namespace CodeImp.DoomBuilder.Rendering
 						}
 						else
 						{
+                            //mxd. set variables for fog rendering
+                            if (wantedshaderpass > 7) {
+                                graphics.Shaders.World3D.World = world;
+
+                                bool sectorHasFogColor = true;
+                                if(GZBuilder.GZGeneral.UDMF && sector.Sector.Fields.ContainsKey("fadecolor")){
+                                    graphics.Shaders.World3D.LightColor = new Color4( (int)sector.Sector.Fields["fadecolor"].Value );
+                                }else{
+                                    graphics.Shaders.World3D.LightColor = new Color4(); //black
+                                    sectorHasFogColor = false;
+                                }
+
+                                graphics.Shaders.World3D.CameraPosition = new Vector4(cameraposition.x, cameraposition.y, cameraposition.z, getFogEnd(sector.Sector, sectorHasFogColor));
+                            }
+                            
                             graphics.Shaders.World3D.SetHighlightColor(CalculateHighlightColor((g == highlighted) && showhighlight, (g.Selected && showselection)).ToArgb());
 							graphics.Shaders.World3D.ApplySettings();
 						}
@@ -820,15 +842,13 @@ namespace CodeImp.DoomBuilder.Rendering
                                     // Determine the shader pass we want to use for this object
                                     int wantedshaderpass = (((t == highlighted) && showhighlight) || (t.Selected && showselection)) ? highshaderpass : shaderpass;
 
+                                    //mxd. if fog is enagled, switch to shader, which calculates it
+                                    if (General.Settings.GZDrawFog && !fullbrightness && t.Thing.Sector != null && t.Thing.Sector.Brightness < 248)
+                                        wantedshaderpass += 8;
+
                                     //mxd. if current thing is light - set it's color to light color
-                                    if (t.LightType != -1) {
+                                    if (t.LightType != -1 && !fullbrightness) {
                                         wantedshaderpass += 4; //render using one of passes, which uses World3D.VertexColor
-                                        /*Color4 c = t.LightColor;
-                                        if (t.LightRenderStyle == (int)GZDoomLightRenderStyle.NEGATIVE) {
-                                            c.Red = 1.0f - t.LightColor.Blue;
-                                            c.Green = 1.0f - t.LightColor.Green;
-                                            c.Blue = 1.0f - t.LightColor.Red;
-                                        } */
                                         graphics.Shaders.World3D.VertexColor = t.LightColor;
                                     //mxd. check if Thing is affected by dynamic lights and set color accordingly
                                     }else if (General.Settings.GZDrawLights && !fullbrightness && thingsWithLight.Count > 0) {
@@ -859,6 +879,22 @@ namespace CodeImp.DoomBuilder.Rendering
                                     if (t.Billboard) world = Matrix.Multiply(world, billboard);
                                     world = Matrix.Multiply(world, t.Position);
                                     ApplyMatrices3D();
+
+                                    //mxd. set variables for fog rendering
+                                    if (wantedshaderpass > 7) {
+                                        Sector sector = t.Thing.Sector;
+                                        graphics.Shaders.World3D.World = world;
+
+                                        bool sectorHasFogColor = true;
+                                        if (GZBuilder.GZGeneral.UDMF && sector.Fields.ContainsKey("fadecolor")) {
+                                            graphics.Shaders.World3D.LightColor = new Color4((int)sector.Fields["fadecolor"].Value);
+                                        } else {
+                                            graphics.Shaders.World3D.LightColor = new Color4(); //black
+                                            sectorHasFogColor = false;
+                                        }
+                                        graphics.Shaders.World3D.CameraPosition = new Vector4(cameraposition.x, cameraposition.y, cameraposition.z, getFogEnd(sector, sectorHasFogColor));
+                                    }
+
                                     graphics.Shaders.World3D.ApplySettings();
 
                                     // Apply buffer
@@ -884,7 +920,7 @@ namespace CodeImp.DoomBuilder.Rendering
         //mxd. Dynamic lights pass!
         private void RenderLights(Dictionary<Texture, List<VisualGeometry>> geometry_to_lit, List<VisualThing> lights) {
             graphics.Shaders.World3D.World = world;
-            graphics.Shaders.World3D.BeginPass(9);
+            graphics.Shaders.World3D.BeginPass(17);
 
             int i, count;
             Vector4 lpr;
@@ -990,6 +1026,10 @@ namespace CodeImp.DoomBuilder.Rendering
                     // Determine the shader pass we want to use for this object
                     int wantedshaderpass = ((((t == highlighted) && showhighlight) || (t.Selected && showselection)) ? highshaderpass : shaderpass);
 
+                    //mxd. if fog is enagled, switch to shader, which calculates it
+                    if (General.Settings.GZDrawFog && !fullbrightness && t.Thing.Sector != null && t.Thing.Sector.Brightness < 248)
+                        wantedshaderpass += 8;
+
                     // Switch shader pass?
                     if (currentshaderpass != wantedshaderpass) {
                         graphics.Shaders.World3D.EndPass();
@@ -1006,10 +1046,25 @@ namespace CodeImp.DoomBuilder.Rendering
                     }
 
                     // Create the matrix for positioning / rotation
-                    world = Matrix.Multiply(t.Orientation, Matrix.RotationZ(t.Thing.Angle));
+                    world = Matrix.Multiply(t.Orientation, Matrix.RotationZ(t.Thing.Angle + group.Key.Model.Angle));
                     world = Matrix.Multiply(world, t.Position);
                     ApplyMatrices3D();
 
+                    //mxd. set variables for fog rendering
+                    if (wantedshaderpass > 7) {
+                        Sector sector = t.Thing.Sector;
+                        graphics.Shaders.World3D.World = world;
+
+                        bool sectorHasFogColor = true;
+                        if (GZBuilder.GZGeneral.UDMF && sector.Fields.ContainsKey("fadecolor")) {
+                            graphics.Shaders.World3D.LightColor = new Color4((int)sector.Fields["fadecolor"].Value);
+                        } else {
+                            graphics.Shaders.World3D.LightColor = new Color4(); //black
+                            sectorHasFogColor = false;
+                        }
+                        graphics.Shaders.World3D.CameraPosition = new Vector4(cameraposition.x, cameraposition.y, cameraposition.z, getFogEnd(sector, sectorHasFogColor));
+                    }
+
                     for (int i = 0; i < group.Key.Model.NUM_MESHES; i++) {
                         if (!graphics.Shaders.Enabled) graphics.Device.SetTexture(0, group.Key.Model.Textures[i]);
                         graphics.Shaders.World3D.Texture1 = group.Key.Model.Textures[i];
@@ -1047,6 +1102,16 @@ namespace CodeImp.DoomBuilder.Rendering
             return litColor;
         }
 
+        //mxd. This returns distance, at which fog color completely replaces texture color for given sector
+        private float getFogEnd(Sector s, bool sectorHasFogColor) {
+            //TODO: check if MapInfo has fog settings and apply them 
+            float brightness = (float)Math.Max(30, s.Brightness);
+            if (sectorHasFogColor) {
+                return brightness * 11.0f;
+            }
+            return (float)Math.Pow(2.0f, brightness / 10.0f);
+        }
+
 		// This calculates the highlight/selection color
 		public Color4 CalculateHighlightColor(bool ishighlighted, bool isselected)
 		{
@@ -1248,7 +1313,7 @@ namespace CodeImp.DoomBuilder.Rendering
 			crosshairbusy = busy;
 		}
 
-        //dbg
+        //mxd. dbg
         //private int lastTick, lastFrameRate, frameRate;
 
         /*private int calculateFrameRate() {
diff --git a/Source/Core/Rendering/World3DShader.cs b/Source/Core/Rendering/World3DShader.cs
index 60fefeba52558cd97dfe49be0d92111ed94ad2eb..2b3aee55728ab7ab9ec75d0e512efdf9ff16c9c7 100644
--- a/Source/Core/Rendering/World3DShader.cs
+++ b/Source/Core/Rendering/World3DShader.cs
@@ -56,6 +56,8 @@ namespace CodeImp.DoomBuilder.Rendering
         private EffectHandle lightPositionAndRadiusHandle;
         private EffectHandle lightColorHandle;
         private EffectHandle worldHandle;
+        //fog
+        private EffectHandle camPosHandle;
         //used in ModelReader
         private VertexElement[] vertexElements;
 
@@ -69,8 +71,14 @@ namespace CodeImp.DoomBuilder.Rendering
 
         //mxd
         public Color4 VertexColor { set { if (manager.Enabled) effect.SetValue<Color4>(vertexColorHadle, value); } }
+        
+        //lights
         public Color4 LightColor { set { if (manager.Enabled) effect.SetValue<Color4>(lightColorHandle, value); } }
         public Vector4 LightPositionAndRadius { set { if (manager.Enabled) effect.SetValue(lightPositionAndRadiusHandle, value); } }
+        
+        //fog
+        public Vector4 CameraPosition { set { if (manager.Enabled) effect.SetValue(camPosHandle, value); } }
+
         public Matrix World { set { if (manager.Enabled) effect.SetValue<Matrix>(worldHandle, value); } }
         public VertexElement[] VertexElements { get { return vertexElements; } }
 
@@ -101,6 +109,9 @@ namespace CodeImp.DoomBuilder.Rendering
                 //lights
                 lightPositionAndRadiusHandle = effect.GetParameter(null, "lightPosAndRadius");
                 lightColorHandle = effect.GetParameter(null, "lightColor");
+                //fog
+                camPosHandle = effect.GetParameter(null, "cameraPos");
+
                 worldHandle = effect.GetParameter(null, "world");
 			}
 
@@ -140,8 +151,10 @@ namespace CodeImp.DoomBuilder.Rendering
                 if (vertexColorHadle != null) vertexColorHadle.Dispose();
                 if (lightColorHandle != null) lightColorHandle.Dispose();
                 if (lightPositionAndRadiusHandle != null) lightPositionAndRadiusHandle.Dispose();
+                if (camPosHandle != null) camPosHandle.Dispose();
                 if (worldHandle != null) worldHandle.Dispose();
 
+
 				// Done
 				base.Dispose();
 			}
@@ -232,7 +245,7 @@ namespace CodeImp.DoomBuilder.Rendering
 				// First texture stage
                 //mxd
 				//if((index == 0) || (index == 2))
-                if ((index == 0) || (index == 2) || (index == 4) || (index == 6) || index > 7)
+                if ((index == 0) || (index == 2) || (index == 4) || (index == 6) || (index == 8) || (index == 10) || (index == 12) || (index == 14) || index > 15)
 				{
 					// Normal
 					device.SetTextureStageState(0, TextureStage.ColorOperation, TextureOperation.Modulate);
@@ -269,8 +282,9 @@ namespace CodeImp.DoomBuilder.Rendering
 
 				// Highlight?
                 //mxd
-				//if(index > 1)
-                if ((index > 1 && index < 4) || (index > 5 && index < 8))
+				//if(index > 1) 2 3 6 10 14
+                //if ((index > 1 && index < 4) || (index > 5 && index < 8) || (index > 9 && index < 12) || (index > 13 && index < 16))
+                if (index == 2 || index == 3 || index == 6 || index == 10 || index == 14)
 				{
 					// Third texture stage
 					device.SetTextureStageState(2, TextureStage.ColorOperation, TextureOperation.AddSigned);
diff --git a/Source/Core/Resources/Actions.cfg b/Source/Core/Resources/Actions.cfg
index c34c909a3825257a9cc0ffb6dbc589fef72964e6..a6c34c2c1e2b5cf418fe8da7aba8a57d586acdc1 100644
--- a/Source/Core/Resources/Actions.cfg
+++ b/Source/Core/Resources/Actions.cfg
@@ -842,7 +842,7 @@ gztogglelights
 {
     title = "Toggle dynamic lights rendering";
 	category = "gzdoombuilder";
-	description = "Toggle dynamic lights rendering.";
+	description = "Toggles dynamic lights rendering.";
 	allowkeys = true;
 	allowmouse = true;
 	allowscroll = false;
@@ -852,7 +852,7 @@ gztogglelightsanimation
 {
     title = "Toggle dynamic lights animation";
 	category = "gzdoombuilder";
-	description = "Toggle dynamic lights animation.";
+	description = "Toggles dynamic lights animation.";
 	allowkeys = true;
 	allowmouse = true;
 	allowscroll = false;
@@ -860,9 +860,9 @@ gztogglelightsanimation
 
 gztogglefog
 {
-    title = "Toggle colored fog rendering";
+    title = "Toggle fog rendering";
 	category = "gzdoombuilder";
-	description = "Toggle colored fog rendering.";
+	description = "Toggles fog rendering.";
 	allowkeys = true;
 	allowmouse = true;
 	allowscroll = false;
@@ -878,12 +878,12 @@ gzdrawselectedmodelsonly
 	allowscroll = false;
 }
 
-gztogglefogpannel
+gztogglefx
 {
-    title = "Toggle fog pannel";
+   title = "Toggle GZDoom effects";
 	category = "gzdoombuilder";
-	description = "Use this pannel to set fog properties quickly.";
+	description = "Toggles models, dynamic lights and fog rendering.";
 	allowkeys = true;
 	allowmouse = true;
 	allowscroll = false;
-}
+}
\ No newline at end of file
diff --git a/Source/Core/Resources/Splash3_trans.png b/Source/Core/Resources/Splash3_trans.png
index 9b9ebe242796bb39254bb87aec2ca3d33df22197..d004897ed2da13bec2d7381798a7128c64953c1d 100644
Binary files a/Source/Core/Resources/Splash3_trans.png and b/Source/Core/Resources/Splash3_trans.png differ
diff --git a/Source/Core/Resources/fog.png b/Source/Core/Resources/fog.png
new file mode 100644
index 0000000000000000000000000000000000000000..1ce62f69656b1b7f8970da72df0d76670651e370
Binary files /dev/null and b/Source/Core/Resources/fog.png differ
diff --git a/Source/Core/Resources/fx.png b/Source/Core/Resources/fx.png
new file mode 100644
index 0000000000000000000000000000000000000000..5b4dcc2726b01d4880bf86d3152ecdb7be5ef590
Binary files /dev/null and b/Source/Core/Resources/fx.png differ
diff --git a/Source/Core/Resources/world3d.fx b/Source/Core/Resources/world3d.fx
index d07d34f40352ecb5efa82712b656123693e594f7..6a6b0df22986a86ca09549a980ca936a89c74679 100644
--- a/Source/Core/Resources/world3d.fx
+++ b/Source/Core/Resources/world3d.fx
@@ -43,7 +43,9 @@ float4x4 world;
 float4 vertexColor;
 //light
 float4 lightPosAndRadius;
-float4 lightColor;
+float4 lightColor; //also used as fog color
+//fog
+float4 cameraPos;  //w is set to fade factor (distance, at wich fog color completely overrides pixel color)
 
 // Texture input
 texture texture1;
@@ -88,14 +90,27 @@ PixelData vs_customvertexcolor(VertexData vd) {
     return pd;
 }
 
+LitPixelData vs_customvertexcolor_fog(VertexData vd) {
+    LitPixelData pd;
+    // Fill pixel data input
+    pd.pos = mul(float4(vd.pos, 1.0f), worldviewproj);
+    pd.pos_w = mul(float4(vd.pos, 1.0f), world);
+    pd.color = vertexColor;
+    pd.color.a = 1.0f;
+    pd.uv = vd.uv;
+    pd.normal = vd.normal;
+    // Return result
+    return pd;
+}
+
 //mxd. light pass vertex shader
 LitPixelData vs_lightpass(VertexData vd) {
     LitPixelData pd;
     pd.pos = mul(float4(vd.pos, 1.0f), worldviewproj);
-    pd.pos_w = mul(vd.pos, (float3x3)world);
+    //pd.pos_w = mul(vd.pos, (float3x3)world);
+    pd.pos_w = mul(float4(vd.pos, 1.0f), world);
     pd.color = vd.color;
     pd.uv = vd.uv;
-    //pd.normal = normalize(mul(vd.normal, (float3x3)world));
     pd.normal = vd.normal;
 
     // Return result
@@ -145,6 +160,33 @@ float4 ps_fullbright_highlight(PixelData pd) : COLOR
     return float4(hcolor.rgb * highlightcolor.a + (ncolor.rgb - 0.4f * highlightcolor.a), tcolor.a);
 }
 
+//mxd. This adds fog color to current pixel color
+float4 getFogColor(LitPixelData pd, float4 color){
+   float fogdist = max(16.0f, distance(pd.pos_w, cameraPos.xyz));
+   float fogfactor = min(1.0f, fogdist / cameraPos.w);
+   //float fogfactor = exp2(cameraPos.w * fogdist);
+   if(fogfactor == 1.0f) //texture color completly replaced by fog color
+       return float4(lightColor.rgb, color.a);
+   return float4(lightColor.rgb * fogfactor + color.rgb * (1.0f - fogfactor), color.a);
+}
+
+//mxd. Shaders with fog calculation
+// Normal pixel shader
+float4 ps_main_fog(LitPixelData pd) : COLOR {
+    float4 tcolor = tex2D(texturesamp, pd.uv);
+    return getFogColor(pd, tcolor * pd.color * modulatecolor);
+}
+
+// Normal pixel shader with highlight
+float4 ps_main_highlight_fog(LitPixelData pd) : COLOR {
+	float4 tcolor = tex2D(texturesamp, pd.uv);
+	
+	// Blend texture color, vertex color and modulation color
+	float4 ncolor = tcolor * pd.color * modulatecolor;
+	float4 hcolor = float4(highlightcolor.rgb, ncolor.a);
+  return getFogColor(pd, float4(hcolor.rgb * highlightcolor.a + (ncolor.rgb - 0.4f * highlightcolor.a), tcolor.a));
+}
+
 //mxd: used to draw bounding boxes
 float4 ps_constant_color(PixelData pd) : COLOR {
     return vertexColor;
@@ -213,11 +255,7 @@ technique SM20 {
 	    PixelShader = compile ps_2_0 ps_main();
     }
     
-    // Full brightness mode
-    pass p5 {
-	    VertexShader = compile vs_2_0 vs_customvertexcolor();
-	    PixelShader = compile ps_2_0 ps_fullbright();
-    }
+    pass p5 {} //mxd. need this only to maintain offset
 	
 	// Normal with highlight
     pass p6 {
@@ -225,20 +263,51 @@ technique SM20 {
 	    PixelShader = compile ps_2_0 ps_main_highlight();
     }
 
-    // Full brightness mode with highlight
-    pass p7 {
-	    VertexShader = compile vs_2_0 vs_customvertexcolor();
-	    PixelShader = compile ps_2_0 ps_fullbright_highlight();
+    pass p7 {} //mxd. need this only to maintain offset
+    
+    //mxd. same as p0-p3, but with fog calculation
+     // Normal
+    pass p8 {
+	    VertexShader = compile vs_2_0 vs_lightpass();
+	    PixelShader = compile ps_2_0 ps_main_fog();
+    }
+    
+    pass p9 {} //mxd. need this only to maintain offset
+
+	// Normal with highlight
+    pass p10 {
+	    VertexShader = compile vs_2_0 vs_lightpass();
+	    PixelShader = compile ps_2_0 ps_main_highlight_fog();
+    }
+
+    pass p11 {} //mxd. need this only to maintain offset
+    
+    //mxd. same as p4-p7, but with fog calculation
+    // Normal
+    pass p12 {
+	    VertexShader = compile vs_2_0 vs_customvertexcolor_fog();
+	    PixelShader = compile ps_2_0 ps_main_fog();
+    }
+
+    pass p13 {} //mxd. need this only to maintain offset
+	
+	// Normal with highlight
+    pass p14 {
+	    VertexShader = compile vs_2_0 vs_customvertexcolor_fog();
+	    PixelShader = compile ps_2_0 ps_main_highlight_fog();
     }
+
+
+    pass p15 {} //mxd. need this only to maintain offset
     
     //mxd. Just fills everything with vertexColor. Used in ThingCage rendering.
-    pass p8 {
+    pass p16 {
 	    VertexShader = compile vs_2_0 vs_customvertexcolor();
 	    PixelShader  = compile ps_2_0 ps_constant_color();
     }
     
     //mxd. Light pass
-    pass p9 {
+    pass p17 {
         VertexShader = compile vs_2_0 vs_lightpass();
         PixelShader  = compile ps_2_0 ps_lightpass();
         AlphaBlendEnable = true;
diff --git a/Source/Core/VisualModes/VisualMode.cs b/Source/Core/VisualModes/VisualMode.cs
index 29f6b29c45f6e95e272c572fe9fbbfe22ddc12fa..196f71bd12a78965e5aedaa5895b94ead1133c7e 100644
--- a/Source/Core/VisualModes/VisualMode.cs
+++ b/Source/Core/VisualModes/VisualMode.cs
@@ -71,8 +71,8 @@ namespace CodeImp.DoomBuilder.VisualModes
         private bool keydown;
 
         //mxd
-        private bool visibleThingsUpdated;
-        private List<VisualThing> selectedThings;
+        private List<VisualThing> selectedVisualThings;
+        private List<VisualSector> selectedVisualSectors;
 
 		// Map
 		protected VisualBlockMap blockmap;
@@ -82,21 +82,6 @@ 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
 
@@ -148,6 +133,10 @@ namespace CodeImp.DoomBuilder.VisualModes
 				allsectors = null;
 				allthings = null;
 				blockmap = null;
+
+                //mxd
+                selectedVisualSectors = null;
+                selectedVisualThings = null;
 				
 				// Done
 				base.Dispose();
@@ -338,7 +327,8 @@ namespace CodeImp.DoomBuilder.VisualModes
 			visiblethings = new List<VisualThing>(visiblethings.Capacity);
 
             //mxd
-            visibleThingsUpdated = true;
+            //visibleThingsUpdated = true;
+            //visibleGeometryUpdated = true;
 
 			// Get the blocks within view range
 			visibleblocks = blockmap.GetFrustumRange(renderer.Frustum2D);
@@ -797,6 +787,65 @@ namespace CodeImp.DoomBuilder.VisualModes
 		/// </summary>
 		public VisualThing GetVisualThing(Thing t) { return allthings[t]; }
 
+        //mxd
+        public List<VisualThing> GetSelectedVisualThings(bool refreshSelection) {
+            if (refreshSelection || selectedVisualThings == null) {
+                selectedVisualThings = new List<VisualThing>();
+                foreach (KeyValuePair<Thing, VisualThing> group in allthings) {
+                    if (group.Value.Selected)
+                        selectedVisualThings.Add(group.Value);
+                }
+            }
+
+            //if nothing is selected - try to get thing from hilighted object
+            if (selectedVisualThings.Count == 0) {
+                Vector3D start = General.Map.VisualCamera.Position;
+                Vector3D delta = General.Map.VisualCamera.Target - General.Map.VisualCamera.Position;
+                delta = delta.GetFixedLength(General.Settings.ViewDistance * 0.98f);
+                VisualPickResult target = PickObject(start, start + delta);
+
+                //not appropriate way to do this, but...
+                if (target.picked != null && target.picked.GetType().Name.IndexOf("Thing") != -1)
+                    return new List<VisualThing>() { (VisualThing)target.picked };
+            }
+
+            return selectedVisualThings;
+        }
+
+        /// <summary>
+        /// mxd. This returns list of selected sectors based on surfaces selected in visual mode
+        /// </summary>
+        public List<VisualSector> GetSelectedVisualSectors(bool refreshSelection) {
+            if (refreshSelection || selectedVisualSectors == null) {
+                selectedVisualSectors = new List<VisualSector>();
+                foreach (KeyValuePair<Sector, VisualSector> group in allsectors) {
+                    foreach (VisualGeometry vg in group.Value.AllGeometry) {
+                        if (vg.Selected) {
+                            selectedVisualSectors.Add(group.Value);
+                            break;
+                        }
+                    }
+                }
+            }
+
+            //if nothing is selected - try to get sector from hilighted object
+            if (selectedVisualSectors.Count == 0) {
+                Vector3D start = General.Map.VisualCamera.Position;
+                Vector3D delta = General.Map.VisualCamera.Target - General.Map.VisualCamera.Position;
+                delta = delta.GetFixedLength(General.Settings.ViewDistance * 0.98f);
+                VisualPickResult target = PickObject(start, start + delta);
+
+                //not appropriate way to do this, but...
+                if (target.picked != null && target.picked.GetType().Name.IndexOf("Thing") == -1) {
+                    VisualGeometry vg = (VisualGeometry)target.picked;
+                    if(vg.Sector != null)
+                        return new List<VisualSector>() { vg.Sector };
+                }
+            }
+
+            return selectedVisualSectors;
+        }
+
 		/// <summary>
 		/// Returns True when a VisualSector has been created for the specified Sector.
 		/// </summary>
diff --git a/Source/Core/VisualModes/VisualThing.cs b/Source/Core/VisualModes/VisualThing.cs
index 09d6ee42602ce03859ee31d562cdfd11663ee361..6115635f1f251846a81f3bce618fe5387cdf48ee 100644
--- a/Source/Core/VisualModes/VisualThing.cs
+++ b/Source/Core/VisualModes/VisualThing.cs
@@ -480,7 +480,7 @@ namespace CodeImp.DoomBuilder.VisualModes
             for (int i = 0; i < len; i++) {
                 Vector3 v = mde.Model.BoundingBox[i];
                 boundingBox[i] = new Vector3(v.X + position_v3.X, v.Y + position_v3.Y, v.Z + position_v3.Z);
-            }
+            }    
         }
 		
 		/// <summary>
diff --git a/Source/Core/Windows/MainForm.Designer.cs b/Source/Core/Windows/MainForm.Designer.cs
index 2ed50e98dd95917ef67e1cf344346c9ea4fe7cb7..1886316d797ac9de67b12a6f404710b9d924cce0 100644
--- a/Source/Core/Windows/MainForm.Designer.cs
+++ b/Source/Core/Windows/MainForm.Designer.cs
@@ -132,10 +132,12 @@ namespace CodeImp.DoomBuilder.Windows
             this.buttonsnaptogrid = new System.Windows.Forms.ToolStripButton();
             this.buttonautomerge = new System.Windows.Forms.ToolStripButton();
             this.separatorgzmodes = new System.Windows.Forms.ToolStripSeparator();
+            this.buttontogglefx = 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.buttontogglefog = 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();
@@ -894,10 +896,12 @@ namespace CodeImp.DoomBuilder.Windows
             this.buttonsnaptogrid,
             this.buttonautomerge,
             this.separatorgzmodes,
+            this.buttontogglefx,
             this.buttontoggledynlight,
             this.buttontoggleanimatedlight,
             this.buttontogglemodels,
             this.buttonselectedmodelsonly,
+            this.buttontogglefog,
             this.seperatorgeometry,
             this.buttontest,
             this.seperatortesting});
@@ -1142,11 +1146,21 @@ namespace CodeImp.DoomBuilder.Windows
             this.separatorgzmodes.Name = "separatorgzmodes";
             this.separatorgzmodes.Size = new System.Drawing.Size(6, 25);
             // 
+            // buttontogglefx
+            // 
+            this.buttontogglefx.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this.buttontogglefx.Enabled = false;
+            this.buttontogglefx.Image = global::CodeImp.DoomBuilder.Properties.Resources.fx;
+            this.buttontogglefx.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.buttontogglefx.Name = "buttontogglefx";
+            this.buttontogglefx.Size = new System.Drawing.Size(23, 22);
+            this.buttontogglefx.Tag = "builder_gztogglefx";
+            this.buttontogglefx.Text = "Toggle GZDoom Effects";
+            this.buttontogglefx.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
             // 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;
@@ -1172,9 +1186,7 @@ namespace CodeImp.DoomBuilder.Windows
             // 
             // 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")));
@@ -1198,6 +1210,19 @@ namespace CodeImp.DoomBuilder.Windows
             this.buttonselectedmodelsonly.Text = "Render models for selected things only";
             this.buttonselectedmodelsonly.Click += new System.EventHandler(this.InvokeTaggedAction);
             // 
+            // buttontogglefog
+            // 
+            this.buttontogglefog.CheckOnClick = true;
+            this.buttontogglefog.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this.buttontogglefog.Enabled = false;
+            this.buttontogglefog.Image = global::CodeImp.DoomBuilder.Properties.Resources.fog;
+            this.buttontogglefog.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.buttontogglefog.Name = "buttontogglefog";
+            this.buttontogglefog.Size = new System.Drawing.Size(23, 22);
+            this.buttontogglefog.Tag = "builder_gztogglefog";
+            this.buttontogglefog.Text = "Toggle Fog Rendering";
+            this.buttontogglefog.Click += new System.EventHandler(this.InvokeTaggedAction);
+            // 
             // seperatorgeometry
             // 
             this.seperatorgeometry.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0);
@@ -1848,5 +1873,7 @@ namespace CodeImp.DoomBuilder.Windows
         private System.Windows.Forms.ToolStripButton buttontogglemodels;
         private System.Windows.Forms.ToolStripButton buttonselectedmodelsonly;
         private System.Windows.Forms.ToolStripButton buttontoggleanimatedlight;
+        private System.Windows.Forms.ToolStripButton buttontogglefx;
+        private System.Windows.Forms.ToolStripButton buttontogglefog;
 	}
 }
\ No newline at end of file
diff --git a/Source/Core/Windows/MainForm.cs b/Source/Core/Windows/MainForm.cs
index 0a8632073186876dd265dc20c3be7b7959b5caba..da8ff7b3ccacc28085530eda184d0e43ad653857 100644
--- a/Source/Core/Windows/MainForm.cs
+++ b/Source/Core/Windows/MainForm.cs
@@ -1649,6 +1649,8 @@ namespace CodeImp.DoomBuilder.Windows
             buttonselectedmodelsonly.Visible = General.Settings.GZToolbarGZDoom;
             buttontoggledynlight.Visible = General.Settings.GZToolbarGZDoom;
             buttontoggleanimatedlight.Visible = General.Settings.GZToolbarGZDoom;
+            buttontogglefx.Visible = General.Settings.GZToolbarGZDoom;
+            buttontogglefog.Visible = General.Settings.GZToolbarGZDoom;
             separatorgzmodes.Visible = General.Settings.GZToolbarGZDoom;
 
 
@@ -1783,18 +1785,23 @@ namespace CodeImp.DoomBuilder.Windows
                 buttonselectedmodelsonly.Enabled = true;
                 buttontoggledynlight.Enabled = true;
                 buttontoggleanimatedlight.Enabled = true;
+                buttontogglefog.Enabled = true;
+                buttontogglefx.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;
+                    buttontogglefog.Checked = General.Settings.GZDrawFog;
                 }
             } else {
                 buttontogglemodels.Enabled = false;
                 buttonselectedmodelsonly.Enabled = false;
                 buttontoggledynlight.Enabled = false;
                 buttontoggleanimatedlight.Enabled = false;
+                buttontogglefog.Enabled = false;
+                buttontogglefx.Enabled = false;
             }
         }
 
diff --git a/Source/Core/Windows/MainForm.resx b/Source/Core/Windows/MainForm.resx
index 44cd10d30d8ea8fdb02ad1e7a95f681bc615606e..638918d509afea7953835961d1e32bbd8279107f 100644
--- a/Source/Core/Windows/MainForm.resx
+++ b/Source/Core/Windows/MainForm.resx
@@ -195,6 +195,30 @@
   <metadata name="sectorinfo.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
+  <metadata name="heightpanel1.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="vertexinfo.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="labelcollapsedinfo.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="buttontoggleinfo.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="modename.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="linedefinfo.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="thinginfo.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="sectorinfo.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
   <metadata name="redrawtimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
     <value>319, 17</value>
   </metadata>
diff --git a/Source/Plugins/ColorPicker/BuilderPlug.cs b/Source/Plugins/ColorPicker/BuilderPlug.cs
index f0cb287d7ec6c5cd138f9b4c4e2d86629169eb6c..cb47c0db796d5db1f06d15d70bb84a5808d11faf 100644
--- a/Source/Plugins/ColorPicker/BuilderPlug.cs
+++ b/Source/Plugins/ColorPicker/BuilderPlug.cs
@@ -31,9 +31,8 @@ namespace CodeImp.DoomBuilder.ColorPicker
         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!");
+            if (GZBuilder.GZGeneral.Version < 1.06f) {
+                General.ErrorLogger.Add(ErrorType.Error, "ColorPicker plugin: GZDoomBuilder 1.06 or later required!");
                 return;
             }
             
@@ -69,7 +68,6 @@ namespace CodeImp.DoomBuilder.ColorPicker
                 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") {
@@ -80,7 +78,7 @@ namespace CodeImp.DoomBuilder.ColorPicker
                 form = new LightColorPicker();
 
             } else if (currentModeName == "SectorsMode") {
-                if (udmf) {
+                if (GZBuilder.GZGeneral.UDMF) {
                     if (General.Map.Map.SelectedSectorsCount == 0) {
                         Plug.DisplayStatus(StatusType.Warning, "Select some sectors first!");
                         return;
@@ -93,19 +91,20 @@ namespace CodeImp.DoomBuilder.ColorPicker
 
             } else if (currentModeName == "BaseVisualMode") {
                 //nothing selected in visual mode?
-                if ( ((VisualMode)General.Editing.Mode).SelectedVisualThings.Count == 0 ) {
+                if ( ((VisualMode)General.Editing.Mode).GetSelectedVisualThings(true).Count == 0 ) {
                     //check sectors
-                    if (udmf && General.Map.Map.SelectedSectorsCount > 0) {
+                    int selectedSectorsCount = ((VisualMode)General.Editing.Mode).GetSelectedVisualSectors(true).Count;
+                    if (GZBuilder.GZGeneral.UDMF && (selectedSectorsCount > 0 || General.Map.Map.SelectedSectorsCount > 0)) {
                         form = new SectorColorPicker();
                     } else {
-                        Plug.DisplayStatus(StatusType.Warning, "Select some lights " + (udmf ? "or sectors " : "") + "first!");
+                        Plug.DisplayStatus(StatusType.Warning, "Select some lights " + (GZBuilder.GZGeneral.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!");
+                Plug.DisplayStatus(StatusType.Warning, "Switch to" + (GZBuilder.GZGeneral.UDMF ? " Sectors," : "") + " Things or GZDoom Visual Mode first!");
                 return;
             }
 
@@ -130,4 +129,4 @@ namespace CodeImp.DoomBuilder.ColorPicker
             form = null;
         }
     }
-}
+}
\ No newline at end of file
diff --git a/Source/Plugins/ColorPicker/Controls/ColorPickerControl.cs b/Source/Plugins/ColorPicker/Controls/ColorPickerControl.cs
index f3dde6b9c8b003573d74c01607c8319a9ad6bf85..5d16ef53ce5378f046cbc9953cb71a1b6f35c37d 100644
--- a/Source/Plugins/ColorPicker/Controls/ColorPickerControl.cs
+++ b/Source/Plugins/ColorPicker/Controls/ColorPickerControl.cs
@@ -191,4 +191,4 @@ namespace CodeImp.DoomBuilder.ColorPicker.Controls {
                 handler(this, e);
         }
     }
-}
+}
\ No newline at end of file
diff --git a/Source/Plugins/ColorPicker/Windows/LightColorPicker.cs b/Source/Plugins/ColorPicker/Windows/LightColorPicker.cs
index d90256c49de7da3a4826c2814ed04cb3b8230255..50c35158ca20fe524b5130faf07f6d509e92ae21 100644
--- a/Source/Plugins/ColorPicker/Windows/LightColorPicker.cs
+++ b/Source/Plugins/ColorPicker/Windows/LightColorPicker.cs
@@ -97,7 +97,7 @@ namespace CodeImp.DoomBuilder.ColorPicker.Windows {
             //check things
             if (editingModeName == "BaseVisualMode") {
                 visualSelection = new List<VisualThing>();
-                List<VisualThing> selectedVisualThings = ((VisualMode)General.Editing.Mode).SelectedVisualThings;
+                List<VisualThing> selectedVisualThings = ((VisualMode)General.Editing.Mode).GetSelectedVisualThings(false);
 
                 foreach (VisualThing t in selectedVisualThings) {
                     if (Array.IndexOf(GZGeneral.GZ_LIGHTS, t.Thing.Type) != -1) {
diff --git a/Source/Plugins/ColorPicker/Windows/SectorColorPicker.cs b/Source/Plugins/ColorPicker/Windows/SectorColorPicker.cs
index 0721547d0571cef5d240f6bc2317340227dc821f..cab1699e3d860d168069dae4b57382f01923d4d2 100644
--- a/Source/Plugins/ColorPicker/Windows/SectorColorPicker.cs
+++ b/Source/Plugins/ColorPicker/Windows/SectorColorPicker.cs
@@ -21,6 +21,7 @@ namespace CodeImp.DoomBuilder.ColorPicker.Windows
         public ColorPickerType Type { get { return ColorPickerType.CP_SECTOR; } }
 
         private List<Sector> selection;
+        private List<VisualSector> visualSelection;
         
         private int curSectorColor;
         private int curFadeColor;
@@ -34,7 +35,27 @@ namespace CodeImp.DoomBuilder.ColorPicker.Windows
 
         public bool Setup(string editingModeName) {
             mode = editingModeName;
-            selection = (List<Sector>)(General.Map.Map.GetSelectedSectors(true));
+
+            if (mode == "SectorsMode") {
+                selection = (List<Sector>)(General.Map.Map.GetSelectedSectors(true));
+            } else { //should be Visual mode
+                selection = new List<Sector>();
+                VisualMode vm = (VisualMode)General.Editing.Mode;
+                visualSelection = vm.GetSelectedVisualSectors(false);
+                
+                if (visualSelection.Count > 0) {
+                    foreach (VisualSector vs in visualSelection)
+                        selection.Add(vs.Sector);
+                } else { //should be some sectors selected in 2d-mode...
+                    visualSelection = new List<VisualSector>();
+                    selection = (List<Sector>)(General.Map.Map.GetSelectedSectors(true));
+
+                    foreach (Sector s in selection) {
+                        if (vm.VisualSectorExists(s))
+                            visualSelection.Add(vm.GetVisualSector(s));
+                    }
+                }
+            }
 
             //create undo
             string rest = selection.Count + " sector" + (selection.Count > 1 ? "s" : "");
@@ -124,14 +145,8 @@ namespace CodeImp.DoomBuilder.ColorPicker.Windows
             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();
-                    }
-                }
+                foreach (VisualSector vs in visualSelection)
+                    vs.UpdateSectorData();
             }
         }