diff --git a/Sledge.Formats.Configuration.Tests/RegistryUtil.cs b/Sledge.Formats.Configuration.Tests/RegistryUtil.cs
index fda99e3..6667679 100644
--- a/Sledge.Formats.Configuration.Tests/RegistryUtil.cs
+++ b/Sledge.Formats.Configuration.Tests/RegistryUtil.cs
@@ -1,5 +1,4 @@
-using System.Diagnostics;
-using Microsoft.Win32;
+using Microsoft.Win32;
using Sledge.Formats.Configuration.Registry;
namespace Sledge.Formats.Configuration.Tests;
diff --git a/Sledge.Formats.Configuration.Tests/Resources/Worldcraft/GameCfg-wc20.wc b/Sledge.Formats.Configuration.Tests/Resources/Worldcraft/GameCfg-wc20.wc
new file mode 100644
index 0000000..2b15ee3
Binary files /dev/null and b/Sledge.Formats.Configuration.Tests/Resources/Worldcraft/GameCfg-wc20.wc differ
diff --git a/Sledge.Formats.Configuration.Tests/Resources/Worldcraft/GameCfg-wc33.wc b/Sledge.Formats.Configuration.Tests/Resources/Worldcraft/GameCfg-wc33.wc
new file mode 100644
index 0000000..e586723
Binary files /dev/null and b/Sledge.Formats.Configuration.Tests/Resources/Worldcraft/GameCfg-wc33.wc differ
diff --git a/Sledge.Formats.Configuration.Tests/Sledge.Formats.Configuration.Tests.csproj b/Sledge.Formats.Configuration.Tests/Sledge.Formats.Configuration.Tests.csproj
index 378f019..beda79a 100644
--- a/Sledge.Formats.Configuration.Tests/Sledge.Formats.Configuration.Tests.csproj
+++ b/Sledge.Formats.Configuration.Tests/Sledge.Formats.Configuration.Tests.csproj
@@ -8,6 +8,16 @@
true
+
+
+
+
+
+
+
+
+
+
diff --git a/Sledge.Formats.Configuration.Tests/TestWorldcraftConfiguration.cs b/Sledge.Formats.Configuration.Tests/TestWorldcraftConfiguration.cs
index 2a49489..575aa71 100644
--- a/Sledge.Formats.Configuration.Tests/TestWorldcraftConfiguration.cs
+++ b/Sledge.Formats.Configuration.Tests/TestWorldcraftConfiguration.cs
@@ -1,8 +1,10 @@
-using Microsoft.Win32;
+using System.Drawing;
+using Microsoft.Win32;
using Sledge.Formats.Configuration.Worldcraft;
namespace Sledge.Formats.Configuration.Tests;
+#pragma warning disable CS0612 // Type or member is obsolete
#pragma warning disable CA1416
[TestClass]
@@ -26,10 +28,15 @@ public void TestLoadSettings()
var config = WorldcraftConfiguration.LoadFromRegistry(new WorldcraftConfigurationLoadSettings
{
LoadGameConfigurations = false,
- AutodetectRegistryLocation = false,
RegistryLocation = reg.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default).OpenSubKey(@"Software\Valve\Worldcraft")
});
+ Assert.IsNotNull(config.General);
+ Assert.IsNotNull(config.Views2D);
+ Assert.IsNotNull(config.Views3D);
+ Assert.IsNotNull(config.TextureDirectories);
+ Assert.IsNull(config.GameConfigurations);
+
Assert.AreEqual(@"C:\Users\WDAGUtilityAccount\Desktop\Worldcraft 3.3", config.General.InstallDirectory, StringComparer.InvariantCultureIgnoreCase);
Assert.AreEqual(true, config.General.UseIndependentWindowConfigurations);
Assert.AreEqual(false, config.General.LoadDefaultWindowPositionsWithMaps);
@@ -37,16 +44,203 @@ public void TestLoadSettings()
Assert.AreEqual(true, config.General.AllowGroupingWhileIgnoreGroupsChecked);
Assert.AreEqual(false, config.General.StretchArchesToFitOriginalBoundingRectangle);
+ Assert.AreEqual(true, config.Views2D.CrosshairCursor);
+ Assert.AreEqual(true, config.Views2D.DefaultTo15DegreeRotations);
+ Assert.AreEqual(false, config.Views2D.DisplayScrollbars);
+ Assert.AreEqual(false, config.Views2D.DrawVertices);
+ Assert.AreEqual(false, config.Views2D.WhiteOnBlackColorScheme);
+ Assert.AreEqual(false, config.Views2D.KeepGroupWhenCloneDragging);
+ Assert.AreEqual(true, config.Views2D.CenterOnCameraAfterMovement);
+ Assert.AreEqual(false, config.Views2D.UseVisgroupColorsForObjectLines);
+ Assert.AreEqual(true, config.Views2D.ArrowKeysNudgeSelectedObject);
+ Assert.AreEqual(true, config.Views2D.ReorientPrimitivesOnCreation);
+ Assert.AreEqual(true, config.Views2D.AutomaticInfiniteSelection);
+ Assert.AreEqual(true, config.Views2D.SelectionBoxSelectsByCenterHandlesOnly);
+ Assert.AreEqual(0x20, config.Views2D.Grid.Size);
+ Assert.AreEqual(0x42, config.Views2D.Grid.Intensity);
+ Assert.AreEqual(true, config.Views2D.Grid.HighlightEvery64Units);
+ Assert.AreEqual(0x00, config.Views2D.Grid.HighlightEveryNGridLines);
+ Assert.AreEqual(false, config.Views2D.Grid.HideGridSmallerThan4Pixels);
+ Assert.AreEqual(false, config.Views2D.Grid.HighlightEvery1024Units);
+ Assert.AreEqual(false, config.Views2D.Grid.DottedGrid);
+
+ Assert.AreEqual(0x1ef9, config.Views3D.BackClippingPlane);
+ Assert.AreEqual(false, config.Views3D.FilterTextures);
+ Assert.AreEqual(true, config.Views3D.AnimateModels);
+ Assert.AreEqual(0x190, config.Views3D.ModelRenderDistance);
+ Assert.AreEqual(false, config.Views3D.UseMouselookNavigation);
+ Assert.AreEqual(true, config.Views3D.ReverseMouseYAxis);
+ Assert.AreEqual(0x0b0d, config.Views3D.ForwardSpeed);
+ Assert.AreEqual(0x0783 / 1000m, config.Views3D.TimeToTopSpeed);
+ Assert.AreEqual(true, config.Views3D.ReverseSelectionOrder);
+ Assert.AreEqual(Color.Black.ToArgb(), config.Views3D.BackgroundColor.ToArgb());
+
CollectionAssert.AreEqual(new[] { @"c:\users\wdagutilityaccount\desktop\zhlt.wad" }, config.TextureDirectories, StringComparer.InvariantCultureIgnoreCase);
}
+ [TestMethod]
+ public void TestReadGameConfigFile20()
+ {
+ using var file = typeof(TestWorldcraftConfiguration).Assembly.GetManifestResourceStream("Sledge.Formats.Configuration.Tests.Resources.Worldcraft.GameCfg-wc20.wc");
+ var configs = new WorldcraftGameConfigurationFile(file).Configurations;
+
+ Assert.AreEqual(configs.Count, 1);
+ var config = configs[0];
+
+ Assert.AreEqual("test", config.Name);
+ CollectionAssert.AreEqual(new[] { @"C:\fgd\a.fgd" }, config.GameDataFiles);
+ Assert.AreEqual(TextureFormat.Wad3, config.TextureFormat);
+ Assert.AreEqual(MapType.HalfLife, config.MapType);
+ Assert.AreEqual("ammo_357", config.DefaultPointEntityClass);
+ Assert.AreEqual("worldspawn", config.DefaultSolidEntityClass);
+ Assert.AreEqual("a", config.GameExecutableDirectory);
+ Assert.AreEqual("", config.ModDirectory);
+ Assert.AreEqual("", config.GameDirectory);
+ Assert.AreEqual("b", config.RmfDirectory);
+ Assert.AreEqual("c", config.PaletteFile);
+ Assert.AreEqual("d", config.BuildPrograms.GameExecutable);
+ Assert.AreEqual("", config.BuildPrograms.CsgExecutable);
+ Assert.AreEqual("e", config.BuildPrograms.BspExecutable);
+ Assert.AreEqual("g", config.BuildPrograms.VisExecutable);
+ Assert.AreEqual("f", config.BuildPrograms.RadExecutable);
+ Assert.AreEqual("h", config.BuildPrograms.BspDirectory);
+ }
+
+ [TestMethod]
+ public void TestReadGameConfigFile33()
+ {
+ using var file = typeof(TestWorldcraftConfiguration).Assembly.GetManifestResourceStream("Sledge.Formats.Configuration.Tests.Resources.Worldcraft.GameCfg-wc33.wc");
+ var configs = new WorldcraftGameConfigurationFile(file).Configurations;
+
+ Assert.AreEqual(configs.Count, 1);
+ var config = configs[0];
+
+ Assert.AreEqual("Half-Life", config.Name);
+ CollectionAssert.AreEqual(new[] { @"C:\fgd\a.fgd", @"C:\fgd\b.fgd", @"C:\fgd\halflife.fgd", }, config.GameDataFiles);
+ Assert.AreEqual(TextureFormat.Wad3, config.TextureFormat);
+ Assert.AreEqual(MapType.HalfLife, config.MapType);
+ Assert.AreEqual("light", config.DefaultPointEntityClass);
+ Assert.AreEqual("func_door", config.DefaultSolidEntityClass);
+ Assert.AreEqual(@"C:\hl", config.GameExecutableDirectory);
+ Assert.AreEqual(@"C:\hl\cstrike", config.ModDirectory);
+ Assert.AreEqual(@"C:\hl\valve", config.GameDirectory);
+ Assert.AreEqual(@"C:\rmf", config.RmfDirectory);
+ Assert.AreEqual("", config.PaletteFile);
+ Assert.AreEqual(@"C:\hl\hl.exe", config.BuildPrograms.GameExecutable);
+ Assert.AreEqual(@"C:\hl\build\csg.exe", config.BuildPrograms.CsgExecutable);
+ Assert.AreEqual(@"C:\hl\build\bsp.exe", config.BuildPrograms.BspExecutable);
+ Assert.AreEqual(@"C:\hl\build\vis.exe", config.BuildPrograms.VisExecutable);
+ Assert.AreEqual(@"C:\hl\build\rad.exe", config.BuildPrograms.RadExecutable);
+ Assert.AreEqual(@"C:\hl\cstrike\maps", config.BuildPrograms.BspDirectory);
+ }
+
+ [TestMethod]
+ public void TestWriteGameConfigFile20()
+ {
+ var file = new WorldcraftGameConfigurationFile();
+ file.Configurations.Add(new WorldcraftGameConfiguration
+ {
+ Name = "Half-Life",
+ GameDataFiles = [@"C:\fgd\a.fgd", @"C:\fgd\b.fgd", @"C:\fgd\halflife.fgd"],
+ TextureFormat = TextureFormat.Wad3,
+ MapType = MapType.HalfLife,
+ DefaultPointEntityClass = "light",
+ DefaultSolidEntityClass = "func_door",
+ GameExecutableDirectory = @"C:\hl",
+ PaletteFile = "palette.pal",
+ RmfDirectory = @"C:\rmf",
+ BuildPrograms = new WorldcraftGameConfigurationBuildPrograms
+ {
+ GameExecutable = @"C:\hl\hl.exe",
+ BspExecutable = @"C:\hl\build\bsp.exe",
+ VisExecutable = @"C:\hl\build\vis.exe",
+ RadExecutable = @"C:\hl\build\rad.exe",
+ BspDirectory = @"C:\hl\cstrike\maps",
+ }
+ });
+
+ var ms = new MemoryStream();
+ file.Write(ms, WorldcraftGameConfigurationFile.MinVersion);
+ ms.Position = 0;
+
+ var file2 = new WorldcraftGameConfigurationFile(ms);
+ Assert.AreEqual(file.Configurations[0].Name, file2.Configurations[0].Name);
+ CollectionAssert.AreEqual(file.Configurations[0].GameDataFiles, file2.Configurations[0].GameDataFiles);
+ Assert.AreEqual(file.Configurations[0].TextureFormat, file2.Configurations[0].TextureFormat);
+ Assert.AreEqual(file.Configurations[0].MapType, file2.Configurations[0].MapType);
+ Assert.AreEqual(file.Configurations[0].DefaultPointEntityClass, file2.Configurations[0].DefaultPointEntityClass);
+ Assert.AreEqual(file.Configurations[0].DefaultSolidEntityClass, file2.Configurations[0].DefaultSolidEntityClass);
+ Assert.AreEqual(file.Configurations[0].GameExecutableDirectory, file2.Configurations[0].GameExecutableDirectory);
+ Assert.AreEqual(file.Configurations[0].ModDirectory, file2.Configurations[0].ModDirectory);
+ Assert.AreEqual(file.Configurations[0].GameDirectory, file2.Configurations[0].GameDirectory);
+ Assert.AreEqual(file.Configurations[0].RmfDirectory, file2.Configurations[0].RmfDirectory);
+ Assert.AreEqual(file.Configurations[0].PaletteFile, file2.Configurations[0].PaletteFile);
+ Assert.AreEqual(file.Configurations[0].BuildPrograms.GameExecutable, file2.Configurations[0].BuildPrograms.GameExecutable);
+ Assert.AreEqual(file.Configurations[0].BuildPrograms.CsgExecutable, file2.Configurations[0].BuildPrograms.CsgExecutable);
+ Assert.AreEqual(file.Configurations[0].BuildPrograms.BspExecutable, file2.Configurations[0].BuildPrograms.BspExecutable);
+ Assert.AreEqual(file.Configurations[0].BuildPrograms.VisExecutable, file2.Configurations[0].BuildPrograms.VisExecutable);
+ Assert.AreEqual(file.Configurations[0].BuildPrograms.RadExecutable, file2.Configurations[0].BuildPrograms.RadExecutable);
+ Assert.AreEqual(file.Configurations[0].BuildPrograms.BspDirectory, file2.Configurations[0].BuildPrograms.BspDirectory);
+ }
+
+ [TestMethod]
+ public void TestWriteGameConfigFile33()
+ {
+ var file = new WorldcraftGameConfigurationFile();
+ file.Configurations.Add(new WorldcraftGameConfiguration
+ {
+ Name = "Half-Life",
+ GameDataFiles = [@"C:\fgd\a.fgd", @"C:\fgd\b.fgd", @"C:\fgd\halflife.fgd"],
+ TextureFormat = TextureFormat.Wad3,
+ MapType = MapType.HalfLife,
+ DefaultPointEntityClass = "light",
+ DefaultSolidEntityClass = "func_door",
+ GameExecutableDirectory = @"C:\hl",
+ ModDirectory = @"C:\hl\cstrike",
+ GameDirectory = @"C:\hl\valve",
+ RmfDirectory = @"C:\rmf",
+ BuildPrograms = new WorldcraftGameConfigurationBuildPrograms
+ {
+ GameExecutable = @"C:\hl\hl.exe",
+ CsgExecutable = @"C:\hl\build\csg.exe",
+ BspExecutable = @"C:\hl\build\bsp.exe",
+ VisExecutable = @"C:\hl\build\vis.exe",
+ RadExecutable = @"C:\hl\build\rad.exe",
+ BspDirectory = @"C:\hl\cstrike\maps",
+ }
+ });
+
+ var ms = new MemoryStream();
+ file.Write(ms, WorldcraftGameConfigurationFile.MaxVersion);
+ ms.Position = 0;
+
+ var file2 = new WorldcraftGameConfigurationFile(ms);
+ Assert.AreEqual(file.Configurations[0].Name, file2.Configurations[0].Name);
+ CollectionAssert.AreEqual(file.Configurations[0].GameDataFiles, file2.Configurations[0].GameDataFiles);
+ Assert.AreEqual(file.Configurations[0].TextureFormat, file2.Configurations[0].TextureFormat);
+ Assert.AreEqual(file.Configurations[0].MapType, file2.Configurations[0].MapType);
+ Assert.AreEqual(file.Configurations[0].DefaultPointEntityClass, file2.Configurations[0].DefaultPointEntityClass);
+ Assert.AreEqual(file.Configurations[0].DefaultSolidEntityClass, file2.Configurations[0].DefaultSolidEntityClass);
+ Assert.AreEqual(file.Configurations[0].GameExecutableDirectory, file2.Configurations[0].GameExecutableDirectory);
+ Assert.AreEqual(file.Configurations[0].ModDirectory, file2.Configurations[0].ModDirectory);
+ Assert.AreEqual(file.Configurations[0].GameDirectory, file2.Configurations[0].GameDirectory);
+ Assert.AreEqual(file.Configurations[0].RmfDirectory, file2.Configurations[0].RmfDirectory);
+ Assert.AreEqual(file.Configurations[0].PaletteFile, file2.Configurations[0].PaletteFile);
+ Assert.AreEqual(file.Configurations[0].BuildPrograms.GameExecutable, file2.Configurations[0].BuildPrograms.GameExecutable);
+ Assert.AreEqual(file.Configurations[0].BuildPrograms.CsgExecutable, file2.Configurations[0].BuildPrograms.CsgExecutable);
+ Assert.AreEqual(file.Configurations[0].BuildPrograms.BspExecutable, file2.Configurations[0].BuildPrograms.BspExecutable);
+ Assert.AreEqual(file.Configurations[0].BuildPrograms.VisExecutable, file2.Configurations[0].BuildPrograms.VisExecutable);
+ Assert.AreEqual(file.Configurations[0].BuildPrograms.RadExecutable, file2.Configurations[0].BuildPrograms.RadExecutable);
+ Assert.AreEqual(file.Configurations[0].BuildPrograms.BspDirectory, file2.Configurations[0].BuildPrograms.BspDirectory);
+ }
+
private const string Worldcraft33RegString = """
Windows Registry Editor Version 5.00
-
+
[HKEY_CURRENT_USER\SOFTWARE\Valve]
-
+
[HKEY_CURRENT_USER\SOFTWARE\Valve\Worldcraft]
-
+
[HKEY_CURRENT_USER\SOFTWARE\Valve\Worldcraft\2D Views]
"Crosshairs"=dword:00000001
"GroupCarve"=dword:00000001
@@ -68,7 +262,7 @@ Windows Registry Editor Version 5.00
"GridDots"=dword:00000000
"Centeroncamera"=dword:00000001
"Usegroupcolors"=dword:00000000
-
+
[HKEY_CURRENT_USER\SOFTWARE\Valve\Worldcraft\3D Views]
"Hardware"=dword:00000000
"Reverse Y"=dword:00000001
@@ -80,13 +274,13 @@ Windows Registry Editor Version 5.00
"TimeToMaxSpeed"=dword:00000783
"FilterTextures"=dword:00000000
"ReverseSelection"=dword:00000001
-
+
[HKEY_CURRENT_USER\SOFTWARE\Valve\Worldcraft\Configured]
"Installed"=dword:6767bfdf
"Configured"=dword:00000002
-
+
[HKEY_CURRENT_USER\SOFTWARE\Valve\Worldcraft\Custom2DColors]
-
+
[HKEY_CURRENT_USER\SOFTWARE\Valve\Worldcraft\General]
"Directory"="C:\\Users\\WDAGUtilityAccount\\Desktop\\Worldcraft 3.3"
"TextureFileCount"=dword:00000001
@@ -100,12 +294,12 @@ Windows Registry Editor Version 5.00
"GroupWhileIgnore"=dword:00000001
"StretchArches"=dword:00000000
"NewBars"=dword:00000001
-
+
[HKEY_CURRENT_USER\SOFTWARE\Valve\Worldcraft\Recent File List]
"File1"="C:\\Users\\WDAGUtilityAccount\\Desktop\\Worldcraft 3.3\\123"
-
+
[HKEY_CURRENT_USER\SOFTWARE\Valve\Worldcraft\Settings]
-
-
+
+
""";
}
\ No newline at end of file
diff --git a/Sledge.Formats.Configuration/Sledge.Formats.Configuration.csproj b/Sledge.Formats.Configuration/Sledge.Formats.Configuration.csproj
index 9ab8a1e..2db6880 100644
--- a/Sledge.Formats.Configuration/Sledge.Formats.Configuration.csproj
+++ b/Sledge.Formats.Configuration/Sledge.Formats.Configuration.csproj
@@ -8,4 +8,8 @@
+
+
+
+
diff --git a/Sledge.Formats.Configuration/Worldcraft/MapType.cs b/Sledge.Formats.Configuration/Worldcraft/MapType.cs
index 45d9b78..b22d676 100644
--- a/Sledge.Formats.Configuration/Worldcraft/MapType.cs
+++ b/Sledge.Formats.Configuration/Worldcraft/MapType.cs
@@ -4,9 +4,9 @@ namespace Sledge.Formats.Configuration.Worldcraft
{
public enum MapType
{
- HalfLife,
- [Obsolete] Quake,
- [Obsolete] Quake2,
- [Obsolete] Hexen2,
+ HalfLife = 3,
+ [Obsolete] Quake = 0,
+ [Obsolete] Quake2 = 2,
+ [Obsolete] Hexen2 = 1,
}
}
\ No newline at end of file
diff --git a/Sledge.Formats.Configuration/Worldcraft/TextureFormat.cs b/Sledge.Formats.Configuration/Worldcraft/TextureFormat.cs
index 42da68b..011f104 100644
--- a/Sledge.Formats.Configuration/Worldcraft/TextureFormat.cs
+++ b/Sledge.Formats.Configuration/Worldcraft/TextureFormat.cs
@@ -4,8 +4,8 @@ namespace Sledge.Formats.Configuration.Worldcraft
{
public enum TextureFormat
{
- Wad3,
- [Obsolete] Wad2,
- [Obsolete] Wal,
+ Wad3 = 2,
+ [Obsolete] Wad2 = 0,
+ [Obsolete] Wal = 1,
}
}
\ No newline at end of file
diff --git a/Sledge.Formats.Configuration/Worldcraft/Worldcraft2DViewsConfiguration.cs b/Sledge.Formats.Configuration/Worldcraft/Worldcraft2DViewsConfiguration.cs
index 2b69496..f4d663f 100644
--- a/Sledge.Formats.Configuration/Worldcraft/Worldcraft2DViewsConfiguration.cs
+++ b/Sledge.Formats.Configuration/Worldcraft/Worldcraft2DViewsConfiguration.cs
@@ -65,6 +65,6 @@ public class Worldcraft2DViewsConfiguration
///
/// Grid configuration
///
- public WorldcraftGridOptions Grid { get; set; }
+ public WorldcraftGridOptions Grid { get; } = new WorldcraftGridOptions();
}
}
\ No newline at end of file
diff --git a/Sledge.Formats.Configuration/Worldcraft/Worldcraft3DViewsConfiguration.cs b/Sledge.Formats.Configuration/Worldcraft/Worldcraft3DViewsConfiguration.cs
index dbddc59..5618b6b 100644
--- a/Sledge.Formats.Configuration/Worldcraft/Worldcraft3DViewsConfiguration.cs
+++ b/Sledge.Formats.Configuration/Worldcraft/Worldcraft3DViewsConfiguration.cs
@@ -42,7 +42,7 @@ public class Worldcraft3DViewsConfiguration
///
/// Time to top speed (0-10 seconds)
///
- public float TimeToTopSpeed { get; set; }
+ public decimal TimeToTopSpeed { get; set; }
///
/// Reverse selection order
@@ -52,6 +52,6 @@ public class Worldcraft3DViewsConfiguration
///
/// Background color
///
- public Color BackgroundColor { get; set; }
+ public Color BackgroundColor { get; set; } = Color.Black;
}
}
\ No newline at end of file
diff --git a/Sledge.Formats.Configuration/Worldcraft/WorldcraftConfiguration.cs b/Sledge.Formats.Configuration/Worldcraft/WorldcraftConfiguration.cs
index b5cf2fd..e070b5a 100644
--- a/Sledge.Formats.Configuration/Worldcraft/WorldcraftConfiguration.cs
+++ b/Sledge.Formats.Configuration/Worldcraft/WorldcraftConfiguration.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using System.Drawing;
using System.IO;
using System.Linq;
using Sledge.Formats.Configuration.Registry;
@@ -17,7 +18,7 @@ public static WorldcraftConfiguration LoadFromRegistry(WorldcraftConfigurationLo
{
settings = settings ?? WorldcraftConfigurationLoadSettings.Default;
var key = settings.RegistryLocation;
- if (settings.AutodetectRegistryLocation)
+ if (settings.AutodetectRegistryLocation && key == null)
{
var reg = new WindowsRegistry();
var baseKey = reg.OpenBaseKey(settings.RegistryHive, settings.RegistryView);
@@ -27,9 +28,28 @@ public static WorldcraftConfiguration LoadFromRegistry(WorldcraftConfigurationLo
var config = new WorldcraftConfiguration();
(config.General, config.TextureDirectories) = LoadGeneralRegistry(key.OpenSubKey(WorldcraftRegistryInfo.KeyGeneral));
- config.Views2D = null;
- config.Views3D = null;
- config.GameConfigurations = null;
+ config.Views2D = LoadViews2DRegistry(key.OpenSubKey(WorldcraftRegistryInfo.Key2DViews));
+ config.Views3D = LoadViews3DRegistry(key.OpenSubKey(WorldcraftRegistryInfo.Key3DViews));
+
+ var installDir = settings.InstallDirectory;
+ if (settings.AutodetectInstallDirectory && installDir == null)
+ {
+ installDir = config.General.InstallDirectory;
+ }
+
+ if (settings.LoadGameConfigurations && Directory.Exists(installDir))
+ {
+ var configFile = Path.Combine(installDir, "GameCfg.wc");
+ if (File.Exists(configFile))
+ {
+ using (var fs = File.OpenRead(configFile))
+ {
+ var cfg = new WorldcraftGameConfigurationFile(fs);
+ config.GameConfigurations = cfg.Configurations;
+ }
+ }
+ }
+
return config;
}
@@ -59,6 +79,58 @@ private static (WorldcraftGeneralConfiguration, List) LoadGeneralRegistr
return (config, textures);
}
+ private static Worldcraft2DViewsConfiguration LoadViews2DRegistry(IRegistryKey key)
+ {
+ var config = new Worldcraft2DViewsConfiguration();
+ if (key != null)
+ {
+ config.CrosshairCursor = key.GetBoolValue(WorldcraftRegistryInfo.Key2DViewsCrosshairs);
+ config.DefaultTo15DegreeRotations = key.GetBoolValue(WorldcraftRegistryInfo.Key2DViewsRotateConstrain);
+ config.DisplayScrollbars = key.GetBoolValue(WorldcraftRegistryInfo.Key2DViewsScrollbars);
+ config.DrawVertices = key.GetBoolValue(WorldcraftRegistryInfo.Key2DViewsDrawVertices);
+ config.WhiteOnBlackColorScheme = key.GetBoolValue(WorldcraftRegistryInfo.Key2DViewsWhiteOnBlack);
+ config.KeepGroupWhenCloneDragging = key.GetBoolValue(WorldcraftRegistryInfo.Key2DViewsKeepCloneGroup);
+ config.CenterOnCameraAfterMovement = key.GetBoolValue(WorldcraftRegistryInfo.Key2DViewsCenterOnCamera);
+ config.UseVisgroupColorsForObjectLines = key.GetBoolValue(WorldcraftRegistryInfo.Key2DViewsUseGroupColors);
+ config.ArrowKeysNudgeSelectedObject = key.GetBoolValue(WorldcraftRegistryInfo.Key2DViewsNudge);
+ config.ReorientPrimitivesOnCreation = key.GetBoolValue(WorldcraftRegistryInfo.Key2DViewsOrientPrimitives);
+ config.AutomaticInfiniteSelection = key.GetBoolValue(WorldcraftRegistryInfo.Key2DViewsAutoSelect);
+ config.SelectionBoxSelectsByCenterHandlesOnly = key.GetBoolValue(WorldcraftRegistryInfo.Key2DViewsSelectByHandles);
+
+ config.Grid.Size = key.GetIntValue(WorldcraftRegistryInfo.Key2DViewsDefaultGrid);
+ config.Grid.Intensity = key.GetIntValue(WorldcraftRegistryInfo.Key2DViewsGridIntensity);
+ config.Grid.HighlightEvery64Units = key.GetBoolValue(WorldcraftRegistryInfo.Key2DViewsGridHigh64);
+ var nLines = key.GetBoolValue(WorldcraftRegistryInfo.Key2DViewsGridHigh10);
+ config.Grid.HighlightEveryNGridLines = nLines ? key.GetIntValue(WorldcraftRegistryInfo.Key2DViewsGridHighSpec) : 0;
+ config.Grid.HideGridSmallerThan4Pixels = key.GetBoolValue(WorldcraftRegistryInfo.Key2DViewsHideSmallGrid);
+ config.Grid.HighlightEvery1024Units = key.GetBoolValue(WorldcraftRegistryInfo.Key2DViewsGridHigh1024);
+ config.Grid.DottedGrid = key.GetBoolValue(WorldcraftRegistryInfo.Key2DViewsGridDots);
+
+ }
+ return config;
+ }
+
+ private static Worldcraft3DViewsConfiguration LoadViews3DRegistry(IRegistryKey key)
+ {
+ var config = new Worldcraft3DViewsConfiguration();
+ if (key != null)
+ {
+ //load 3d view settings into config of type Worldcraft3DViewsConfiguration:
+ config.BackClippingPlane = key.GetIntValue(WorldcraftRegistryInfo.Key3DViewsBackPlane);
+ config.FilterTextures = key.GetBoolValue(WorldcraftRegistryInfo.Key3DViewsFilterTextures);
+ config.AnimateModels = key.GetBoolValue(WorldcraftRegistryInfo.Key3DViewsAnimateModels);
+ config.ModelRenderDistance = key.GetIntValue(WorldcraftRegistryInfo.Key3DViewsModelDistance);
+ config.UseMouselookNavigation = key.GetBoolValue(WorldcraftRegistryInfo.Key3DViewsUseMouseLook);
+ config.ReverseMouseYAxis = key.GetBoolValue(WorldcraftRegistryInfo.Key3DViewsReverseY);
+ config.ForwardSpeed = key.GetIntValue(WorldcraftRegistryInfo.Key3DViewsForwardSpeedMax);
+ config.TimeToTopSpeed = key.GetIntValue(WorldcraftRegistryInfo.Key3DViewsTimeToMaxSpeed) / 1000m;
+ config.ReverseSelectionOrder = key.GetBoolValue(WorldcraftRegistryInfo.Key3DViewsReverseSelection);
+ config.BackgroundColor = Color.FromArgb(255, Color.FromArgb(key.GetIntValue(WorldcraftRegistryInfo.Key3DViewsClearColor)));
+ }
+ return config;
+ }
+
+
private static IRegistryKey FindDefaultRegistryKey(IRegistryKey baseKey)
{
foreach (var path in WorldcraftRegistryInfo.DefaultRegistryPaths)
diff --git a/Sledge.Formats.Configuration/Worldcraft/WorldcraftConfigurationLoadSettings.cs b/Sledge.Formats.Configuration/Worldcraft/WorldcraftConfigurationLoadSettings.cs
index 757acb0..e87c5c5 100644
--- a/Sledge.Formats.Configuration/Worldcraft/WorldcraftConfigurationLoadSettings.cs
+++ b/Sledge.Formats.Configuration/Worldcraft/WorldcraftConfigurationLoadSettings.cs
@@ -1,6 +1,4 @@
-using System.IO;
-using System.Linq;
-using Microsoft.Win32;
+using Microsoft.Win32;
using Sledge.Formats.Configuration.Registry;
namespace Sledge.Formats.Configuration.Worldcraft
@@ -8,7 +6,8 @@ namespace Sledge.Formats.Configuration.Worldcraft
public class WorldcraftConfigurationLoadSettings
{
///
- /// True to attempt to autodetect the registry location from the known default registry locations
+ /// True to attempt to autodetect the registry location from the known default registry locations.
+ /// Ignored if RegistryLocation is not null.
///
public bool AutodetectRegistryLocation { get; set; } = true;
@@ -23,7 +22,7 @@ public class WorldcraftConfigurationLoadSettings
public RegistryView RegistryView { get; set; } = RegistryView.Default;
///
- /// Set to a non-null value and set AutodetectRegistryLocation to false to specify the registry location.
+ /// Set to a non-null value to specify the registry location.
/// The registry location will usually be called "Worldcraft" or "Valve Hammer Editor" and contain subkeys called "General", "2D Views", "3D Views", etc.
///
public IRegistryKey RegistryLocation { get; set; }
@@ -36,11 +35,12 @@ public class WorldcraftConfigurationLoadSettings
///
/// True to attempt to autodetect the install directory from the registry ([Worldcraft/General/Directory] registry key).
/// All worldcraft versions store the install directory in the registry except for version 1.0.
+ /// Ignored if InstallDirectory is not null.
///
public bool AutodetectInstallDirectory { get; set; } = true;
///
- /// Set to a non-null value and set AutodetectInstallDirectory to false to specify the install directory
+ /// Set to a non-null value to specify the install directory
///
public string InstallDirectory { get; set; }
diff --git a/Sledge.Formats.Configuration/Worldcraft/WorldcraftGameConfiguration.cs b/Sledge.Formats.Configuration/Worldcraft/WorldcraftGameConfiguration.cs
index 1e58a34..10ac6aa 100644
--- a/Sledge.Formats.Configuration/Worldcraft/WorldcraftGameConfiguration.cs
+++ b/Sledge.Formats.Configuration/Worldcraft/WorldcraftGameConfiguration.cs
@@ -8,61 +8,61 @@ public class WorldcraftGameConfiguration
///
/// Configuration name
///
- public string Name { get; set; }
+ public string Name { get; set; } = "";
///
/// List of game data files (.fgd)
///
- public List GameDataFiles { get; set; }
+ public List GameDataFiles { get; set; } = new List();
///
/// Texture Format
///
- public TextureFormat TextureFormat { get; set; }
+ public TextureFormat TextureFormat { get; set; } = TextureFormat.Wad3;
///
/// Map Type
///
- public MapType MapType { get; set; }
+ public MapType MapType { get; set; } = MapType.HalfLife;
///
/// Default PointEntity class
///
- public string DefaultPointEntityClass { get; set; }
+ public string DefaultPointEntityClass { get; set; } = "";
///
/// Default SolidEntity class
///
- public string DefaultSolidEntityClass { get; set; }
+ public string DefaultSolidEntityClass { get; set; } = "";
///
/// Game executable directory (ex: C:\HalfLife)
///
- public string GameExecutableDirectory { get; set; }
+ public string GameExecutableDirectory { get; set; } = "";
///
/// Mod directory (ex: C:\HalfLife\tfc)
///
- public string ModDirectory { get; set; }
+ public string ModDirectory { get; set; } = "";
///
/// Game directory (ex: C:\HalfLife\valve)
///
- public string GameDirectory { get; set; }
+ public string GameDirectory { get; set; } = "";
///
/// RMF directory
///
- public string RmfDirectory { get; set; }
+ public string RmfDirectory { get; set; } = "";
///
/// Palette file
///
- [Obsolete] public string PaletteFile { get; set; }
+ [Obsolete] public string PaletteFile { get; set; } = "";
///
/// Build programs for this configuration
///
- public WorldcraftGameConfigurationBuildPrograms BuildPrograms { get; set; }
+ public WorldcraftGameConfigurationBuildPrograms BuildPrograms { get; set; } = new WorldcraftGameConfigurationBuildPrograms();
}
}
\ No newline at end of file
diff --git a/Sledge.Formats.Configuration/Worldcraft/WorldcraftGameConfigurationBuildPrograms.cs b/Sledge.Formats.Configuration/Worldcraft/WorldcraftGameConfigurationBuildPrograms.cs
index d6127fd..9712b6f 100644
--- a/Sledge.Formats.Configuration/Worldcraft/WorldcraftGameConfigurationBuildPrograms.cs
+++ b/Sledge.Formats.Configuration/Worldcraft/WorldcraftGameConfigurationBuildPrograms.cs
@@ -5,31 +5,31 @@ public class WorldcraftGameConfigurationBuildPrograms
///
/// Game executable
///
- public string GameExecutable { get; set; }
+ public string GameExecutable { get; set; } = "";
///
/// CSG executable
///
- public string CsgExecutable { get; set; }
+ public string CsgExecutable { get; set; } = "";
///
/// BSP executable
///
- public string BspExecutable { get; set; }
+ public string BspExecutable { get; set; } = "";
///
/// VIS executable
///
- public string VisExecutable { get; set; }
+ public string VisExecutable { get; set; } = "";
///
/// RAD executable
///
- public string RadExecutable { get; set; }
+ public string RadExecutable { get; set; } = "";
///
/// Place compiled maps in this directory before running the game
///
- public string BspDirectory { get; set; }
+ public string BspDirectory { get; set; } = "";
}
}
\ No newline at end of file
diff --git a/Sledge.Formats.Configuration/Worldcraft/WorldcraftGameConfigurationFile.cs b/Sledge.Formats.Configuration/Worldcraft/WorldcraftGameConfigurationFile.cs
new file mode 100644
index 0000000..152c9ce
--- /dev/null
+++ b/Sledge.Formats.Configuration/Worldcraft/WorldcraftGameConfigurationFile.cs
@@ -0,0 +1,141 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace Sledge.Formats.Configuration.Worldcraft
+{
+ public class WorldcraftGameConfigurationFile
+ {
+ private const int StringLength = 128;
+ private static readonly string ConfigFileHeader = "Game Configurations File\r\n" + (char)0x1A + '\0';
+
+ ///
+ /// Version 1.3 used for Worldcraft 1.6a-2.1
+ ///
+ public const float MinVersion = 1.3f;
+
+ ///
+ /// Version 1.4 used for Worldcraft 3.3 and VHE 3.5
+ ///
+ public const float MaxVersion = 1.4f;
+
+ public List Configurations { get; set; }
+
+ public WorldcraftGameConfigurationFile()
+ {
+ Configurations = new List();
+ }
+
+ public WorldcraftGameConfigurationFile(Stream stream)
+ {
+ Configurations = new List();
+ ReadFromStream(stream);
+ }
+
+ public static WorldcraftGameConfigurationFile FromFile(string file)
+ {
+ using (var stream = File.OpenRead(file))
+ {
+ return new WorldcraftGameConfigurationFile(stream);
+ }
+ }
+
+ private void ReadFromStream(Stream stream)
+ {
+ using (var br = new BinaryReader(stream, Encoding.ASCII, true))
+ {
+ var header = br.ReadFixedLengthString(Encoding.ASCII, ConfigFileHeader.Length);
+ if (header != ConfigFileHeader.TrimEnd('\0')) throw new NotSupportedException($"Incorrect configuration file header. Expected '{ConfigFileHeader}', got '{header}'.");
+
+ var version = br.ReadSingle();
+ if (version < MinVersion || version > MaxVersion) throw new NotSupportedException($"Unsupported configuration file version. Expected {MinVersion} or {MaxVersion}, got {version}.");
+
+ var numGames = br.ReadInt32();
+ for (var i = 0; i < numGames; i++)
+ {
+ var config = new WorldcraftGameConfiguration
+ {
+ Name = br.ReadFixedLengthString(Encoding.ASCII, StringLength)
+ };
+
+ var numFgds = br.ReadInt32();
+ config.TextureFormat = (TextureFormat) br.ReadInt32();
+ config.MapType = (MapType) br.ReadInt32();
+
+ if (Math.Abs(version - 1.3f) < float.Epsilon)
+ {
+#pragma warning disable CS0612 // Type or member is obsolete
+ config.PaletteFile = br.ReadFixedLengthString(Encoding.ASCII, StringLength);
+#pragma warning restore CS0612
+ }
+
+ config.BuildPrograms.GameExecutable = br.ReadFixedLengthString(Encoding.ASCII, StringLength);
+ config.DefaultSolidEntityClass = br.ReadFixedLengthString(Encoding.ASCII, StringLength);
+ config.DefaultPointEntityClass = br.ReadFixedLengthString(Encoding.ASCII, StringLength);
+ config.BuildPrograms.BspExecutable = br.ReadFixedLengthString(Encoding.ASCII, StringLength);
+ config.BuildPrograms.RadExecutable = br.ReadFixedLengthString(Encoding.ASCII, StringLength);
+ config.BuildPrograms.VisExecutable = br.ReadFixedLengthString(Encoding.ASCII, StringLength);
+ config.GameExecutableDirectory = br.ReadFixedLengthString(Encoding.ASCII, StringLength);
+ config.RmfDirectory = br.ReadFixedLengthString(Encoding.ASCII, StringLength);
+ config.BuildPrograms.BspDirectory = br.ReadFixedLengthString(Encoding.ASCII, StringLength);
+ if (Math.Abs(version - 1.4f) < float.Epsilon)
+ {
+ config.BuildPrograms.CsgExecutable = br.ReadFixedLengthString(Encoding.ASCII, StringLength);
+ config.ModDirectory = br.ReadFixedLengthString(Encoding.ASCII, StringLength);
+ config.GameDirectory = br.ReadFixedLengthString(Encoding.ASCII, StringLength);
+ }
+ for (var j = 0; j < numFgds; j++)
+ {
+ config.GameDataFiles.Add(br.ReadFixedLengthString(Encoding.ASCII, StringLength));
+ }
+ Configurations.Add(config);
+ }
+ }
+ }
+
+ public void Write(Stream stream, float version = MaxVersion)
+ {
+ if (version < MinVersion || version > MaxVersion) throw new NotSupportedException($"Unsupported configuration file version. Expected {MinVersion} or {MaxVersion}, got {version}.");
+
+ using (var bw = new BinaryWriter(stream, Encoding.ASCII, true))
+ {
+ bw.WriteFixedLengthString(Encoding.ASCII, ConfigFileHeader.Length, ConfigFileHeader);
+ bw.Write(version);
+ bw.Write(Configurations.Count);
+ foreach (var config in Configurations)
+ {
+ bw.WriteFixedLengthString(Encoding.ASCII, StringLength, config.Name);
+ bw.Write(config.GameDataFiles.Count);
+ bw.Write((int)config.TextureFormat);
+ bw.Write((int)config.MapType);
+ if (Math.Abs(version - 1.3f) < float.Epsilon)
+ {
+#pragma warning disable CS0612 // Type or member is obsolete
+ bw.WriteFixedLengthString(Encoding.ASCII, StringLength, config.PaletteFile);
+#pragma warning restore CS0612
+ }
+ bw.WriteFixedLengthString(Encoding.ASCII, StringLength, config.BuildPrograms.GameExecutable);
+ bw.WriteFixedLengthString(Encoding.ASCII, StringLength, config.DefaultSolidEntityClass);
+ bw.WriteFixedLengthString(Encoding.ASCII, StringLength, config.DefaultPointEntityClass);
+ bw.WriteFixedLengthString(Encoding.ASCII, StringLength, config.BuildPrograms.BspExecutable);
+ bw.WriteFixedLengthString(Encoding.ASCII, StringLength, config.BuildPrograms.RadExecutable);
+ bw.WriteFixedLengthString(Encoding.ASCII, StringLength, config.BuildPrograms.VisExecutable);
+ bw.WriteFixedLengthString(Encoding.ASCII, StringLength, config.GameExecutableDirectory);
+ bw.WriteFixedLengthString(Encoding.ASCII, StringLength, config.RmfDirectory);
+ bw.WriteFixedLengthString(Encoding.ASCII, StringLength, config.BuildPrograms.BspDirectory);
+ if (Math.Abs(version - 1.4f) < float.Epsilon)
+ {
+ bw.WriteFixedLengthString(Encoding.ASCII, StringLength, config.BuildPrograms.CsgExecutable);
+ bw.WriteFixedLengthString(Encoding.ASCII, StringLength, config.ModDirectory);
+ bw.WriteFixedLengthString(Encoding.ASCII, StringLength, config.GameDirectory);
+ }
+ foreach (var fgd in config.GameDataFiles)
+ {
+ bw.WriteFixedLengthString(Encoding.ASCII, StringLength, fgd);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Sledge.Formats.Configuration/Worldcraft/WorldcraftRegistryInfo.cs b/Sledge.Formats.Configuration/Worldcraft/WorldcraftRegistryInfo.cs
index ea2cd4e..dee91f3 100644
--- a/Sledge.Formats.Configuration/Worldcraft/WorldcraftRegistryInfo.cs
+++ b/Sledge.Formats.Configuration/Worldcraft/WorldcraftRegistryInfo.cs
@@ -29,5 +29,41 @@ public static class WorldcraftRegistryInfo
public const string KeyGeneralTextureFilePrefix = "TextureFile";
public const string KeyGeneralTextureFileCount = "TextureFileCount";
public const string KeyGeneralUndoLevels = "Undo Levels";
+
+ public const string Key2DViewsCrosshairs = "Crosshairs";
+ public const string Key2DViewsGroupCarve = "GroupCarve";
+ public const string Key2DViewsScrollbars = "Scrollbars";
+ public const string Key2DViewsRotateConstrain = "RotateConstrain";
+ public const string Key2DViewsDrawVertices = "Draw Vertices";
+ public const string Key2DViewsDefaultGrid = "Default Grid";
+ public const string Key2DViewsWhiteOnBlack = "WhiteOnBlack";
+ public const string Key2DViewsGridHigh10 = "GridHigh10";
+ public const string Key2DViewsGridHigh1024 = "GridHigh1024";
+ public const string Key2DViewsGridIntensity = "GridIntensity";
+ public const string Key2DViewsHideSmallGrid = "HideSmallGrid";
+ public const string Key2DViewsNudge = "Nudge";
+ public const string Key2DViewsOrientPrimitives = "OrientPrimitives";
+ public const string Key2DViewsAutoSelect = "AutoSelect";
+ public const string Key2DViewsSelectByHandles = "SelectByHandles";
+ public const string Key2DViewsGridHighSpec = "GridHighSpec";
+ public const string Key2DViewsKeepCloneGroup = "KeepCloneGroup";
+ public const string Key2DViewsGridHigh64 = "Gridhigh64";
+ public const string Key2DViewsGridDots = "GridDots";
+ public const string Key2DViewsCenterOnCamera = "Centeroncamera";
+ public const string Key2DViewsUseGroupColors = "Usegroupcolors";
+
+ public const string Key3DViewsHardware = "Hardware";
+ public const string Key3DViewsReverseY = "Reverse Y";
+ public const string Key3DViewsBackPlane = "BackPlane";
+ public const string Key3DViewsUseMouseLook = "UseMouseLook";
+ public const string Key3DViewsModelDistance = "ModelDistance";
+ public const string Key3DViewsAnimateModels = "AnimateModels";
+ public const string Key3DViewsForwardSpeedMax = "ForwardSpeedMax";
+ public const string Key3DViewsTimeToMaxSpeed = "TimeToMaxSpeed";
+ public const string Key3DViewsFilterTextures = "FilterTextures";
+ public const string Key3DViewsReverseSelection = "ReverseSelection";
+ public const string Key3DViewsClearColor = "ClearColor";
+
+ public const string KeyRecentFileListPrefix = "File";
}
}
\ No newline at end of file