diff --git a/Build/Textures/Crosshair.png b/Build/Textures/Crosshair.png
new file mode 100644
index 0000000000000000000000000000000000000000..7d069a2f871a170c18a20a51c8cd5bedb3431402
Binary files /dev/null and b/Build/Textures/Crosshair.png differ
diff --git a/Build/Textures/CrosshairBusy.png b/Build/Textures/CrosshairBusy.png
new file mode 100644
index 0000000000000000000000000000000000000000..c534727119fd33ffb11e8875ff5ab31dd9f4edce
Binary files /dev/null and b/Build/Textures/CrosshairBusy.png differ
diff --git a/Build/Textures/Hourglass3D.png b/Build/Textures/Hourglass3D.png
new file mode 100644
index 0000000000000000000000000000000000000000..f3a1b7d06e3bd56353d2d0f2e6e8f28107961c69
Binary files /dev/null and b/Build/Textures/Hourglass3D.png differ
diff --git a/Build/Textures/MissingTexture3D.png b/Build/Textures/MissingTexture3D.png
new file mode 100644
index 0000000000000000000000000000000000000000..1e24d4c5774886b22b4d66e33fca613fe560561b
Binary files /dev/null and b/Build/Textures/MissingTexture3D.png differ
diff --git a/Build/Textures/UnknownTexture3D.png b/Build/Textures/UnknownTexture3D.png
new file mode 100644
index 0000000000000000000000000000000000000000..7f31fa08213a60d0193fc7aeca9e2ca004dd9a03
Binary files /dev/null and b/Build/Textures/UnknownTexture3D.png differ
diff --git a/Setup/gzbuilder_setup.iss b/Setup/gzbuilder_setup.iss
index f75fd52ef455e2c69d8c7b423f7e25dbd6caae07..b3e9669674586a18cd146ef9277a204ed8c92ef8 100644
--- a/Setup/gzbuilder_setup.iss
+++ b/Setup/gzbuilder_setup.iss
@@ -64,6 +64,7 @@ Source: Plugins\TagRange.dll; DestDir: {app}\Plugins; Flags: ignoreversion
 Source: Plugins\VisplaneExplorer.dll; DestDir: {app}\Plugins; Flags: ignoreversion
 Source: Plugins\Loadorder.cfg; DestDir: {app}\Plugins; Flags: ignoreversion onlyifdoesntexist
 Source: Sprites\*; DestDir: {app}\Sprites; Flags: ignoreversion recursesubdirs
+Source: Textures\*; DestDir: {app}\Textures; Flags: ignoreversion
 
 [Icons]
 Name: {group}\GZDoom Builder; Filename: {app}\Builder.exe
diff --git a/Source/Core/Data/DataManager.cs b/Source/Core/Data/DataManager.cs
index e753cffb8a0301e9c06211079baf3a737e9709af..1c87d84e13b0adfec1652f4bacb932ead5bfac6c 100644
--- a/Source/Core/Data/DataManager.cs
+++ b/Source/Core/Data/DataManager.cs
@@ -173,17 +173,7 @@ namespace CodeImp.DoomBuilder.Data
 			glowingflats = new Dictionary<long, GlowingFlatData>();
 			soundsequences = new List<string>();
 
-			// Load special images
-			missingtexture3d = new ResourceImage("CodeImp.DoomBuilder.Resources.MissingTexture3D.png");
-			missingtexture3d.LoadImage();
-			unknowntexture3d = new ResourceImage("CodeImp.DoomBuilder.Resources.UnknownTexture3D.png");
-			unknowntexture3d.LoadImage();
-			hourglass3d = new ResourceImage("CodeImp.DoomBuilder.Resources.Hourglass3D.png");
-			hourglass3d.LoadImage();
-			crosshair = new ResourceImage("CodeImp.DoomBuilder.Resources.Crosshair.png");
-			crosshair.LoadImage();
-			crosshairbusy = new ResourceImage("CodeImp.DoomBuilder.Resources.CrosshairBusy.png");
-			crosshairbusy.LoadImage();
+			// Load special images (mxd: the rest is loaded in LoadInternalTextures())
 			whitetexture = new ResourceImage("CodeImp.DoomBuilder.Resources.White.png") { UseColorCorrection = false };
 			whitetexture.LoadImage();
 			whitetexture.CreateTexture();
@@ -359,6 +349,7 @@ namespace CodeImp.DoomBuilder.Data
 			int thingcount = LoadDecorateThings(spawnnums, doomednums);
 			int spritecount = LoadThingSprites();
 			LoadInternalSprites();
+			LoadInternalTextures(); //mxd
 
 			//mxd. Load more stuff
 			LoadReverbs();
@@ -1043,6 +1034,35 @@ namespace CodeImp.DoomBuilder.Data
 			if(textures.ContainsKey(hash) && textures[hash] is HighResImage) return hash; //TEXTURES textures should still override regular ones...
 			return (General.Map.Config.UseLongTextureNames && texturenamesshorttofull.ContainsKey(hash) ? texturenamesshorttofull[hash] : hash);
 		}
+
+		//mxd
+		private void LoadInternalTextures()
+		{
+			missingtexture3d = LoadInternalTexture("MissingTexture3D.png"); //mxd
+			unknowntexture3d = LoadInternalTexture("UnknownTexture3D.png"); //mxd
+			hourglass3d = LoadInternalTexture("Hourglass3D.png"); //mxd
+			crosshair = LoadInternalTexture("Crosshair.png"); //mxd
+			crosshairbusy = LoadInternalTexture("CrosshairBusy.png"); //mxd
+		}
+
+		//mxd
+		private static ImageData LoadInternalTexture(string name)
+		{
+			ImageData result;
+			string path = Path.Combine(General.TexturesPath, name);
+			if(File.Exists(path))
+			{
+				result = new FileImage(name, path) { AllowUnload = false };
+			}
+			else
+			{
+				General.ErrorLogger.Add(ErrorType.Warning, "Unable to load editor texture '" + name + "'. Using built-in one instead.");
+				result = new ResourceImage("CodeImp.DoomBuilder.Resources." + name);
+			}
+
+			result.LoadImage();
+			return result;
+		}
 		
 		#endregion
 
diff --git a/Source/Core/Data/TextureImage.cs b/Source/Core/Data/TextureImage.cs
index a166e939fe996e36d8ac107f6e94679a9d28edca..cbda6c1fd07df80f0588b263d238b076324583cc 100644
--- a/Source/Core/Data/TextureImage.cs
+++ b/Source/Core/Data/TextureImage.cs
@@ -94,7 +94,7 @@ namespace CodeImp.DoomBuilder.Data
 					loadfailed = true;
 				}
 
-				int failCount = 0; //mxd
+				int missingpatches = 0; //mxd
 
 				if(!loadfailed)
 				{
@@ -126,7 +126,7 @@ namespace CodeImp.DoomBuilder.Data
 									// Data is in an unknown format!
 									General.ErrorLogger.Add(ErrorType.Error, "Patch lump '" + p.lumpname + "' data format could not be read, while loading texture '" + this.Name + "'. Does this lump contain valid picture data at all?");
 									loadfailed = true;
-									failCount++; //mxd
+									missingpatches++; //mxd
 								}
 							}
 
@@ -140,7 +140,7 @@ namespace CodeImp.DoomBuilder.Data
 									// Data cannot be read!
 									General.ErrorLogger.Add(ErrorType.Error, "Patch lump '" + p.lumpname + "' data format could not be read, while loading texture '" + this.Name + "'. Does this lump contain valid picture data at all?");
 									loadfailed = true;
-									failCount++; //mxd
+									missingpatches++; //mxd
 								}
 							}
 
@@ -152,7 +152,7 @@ namespace CodeImp.DoomBuilder.Data
 							// Missing a patch lump!
 							General.ErrorLogger.Add(ErrorType.Error, "Missing patch lump '" + p.lumpname + "' while loading texture '" + this.Name + "'. Did you forget to include required resources?");
 							loadfailed = true;
-							failCount++; //mxd
+							missingpatches++; //mxd
 						}
 					}
 
@@ -161,7 +161,7 @@ namespace CodeImp.DoomBuilder.Data
 				}
 				
 				// Dispose bitmap if load failed
-				if((bitmap != null) && (loadfailed || failCount >= patches.Count)) //mxd. We can still display texture if at least one of the patches was loaded
+				if((bitmap != null) && (loadfailed || missingpatches >= patches.Count)) //mxd. We can still display texture if at least one of the patches was loaded
 				{
 					bitmap.Dispose();
 					bitmap = null;
diff --git a/Source/Core/General/General.cs b/Source/Core/General/General.cs
index 0746e6294677c54bef66ce520de9a19bc14cb501..e5ba1a53f04dd627a18b99232d0302211cfc3d83 100644
--- a/Source/Core/General/General.cs
+++ b/Source/Core/General/General.cs
@@ -130,6 +130,7 @@ namespace CodeImp.DoomBuilder
 		private const string MAP_RESTORE_DIR = "Restore"; //mxd
 		private const string SETUP_DIR = "Setup";
 		private const string SPRITES_DIR = "Sprites";
+		private const string TEXTURES_DIR = "Textures"; //mxd
 		private const string HELP_FILE = "Refmanual.chm";
 
 		// SCROLLINFO structure
@@ -162,6 +163,7 @@ namespace CodeImp.DoomBuilder
 		private static string screenshotspath; //mxd
 		private static string pluginspath;
 		private static string spritespath;
+		private static string texturespath; //mxd
 		
 		// Main objects
 		private static Assembly thisasm;
@@ -216,6 +218,7 @@ namespace CodeImp.DoomBuilder
 		public static string CompilersPath { get { return compilerspath; } }
 		public static string PluginsPath { get { return pluginspath; } }
 		public static string SpritesPath { get { return spritespath; } }
+		internal static string TexturesPath { get { return texturespath; } } //mxd
 		public static string SnippetsPath { get { return snippetspath; } } //mxd
 		public static string DefaultScreenshotsPath { get { return screenshotspath; } } //mxd
 		public static ICollection<string> CommandArgs { get { return Array.AsReadOnly(cmdargs); } }
@@ -583,6 +586,7 @@ namespace CodeImp.DoomBuilder
 			snippetspath = Path.Combine(apppath, SNIPPETS_DIR); //mxd
 			screenshotspath = Path.Combine(apppath, SCREENSHOTS_DIR).Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); //mxd
 			spritespath = Path.Combine(apppath, SPRITES_DIR);
+			texturespath = Path.Combine(apppath, TEXTURES_DIR); //mxd
 			logfile = Path.Combine(settingspath, LOG_FILE);
 			
 			// Make program settings directory if missing