diff --git a/src/TSMapEditor/Config/Constants.ini b/src/TSMapEditor/Config/Constants.ini index c2bc6f7b1..06b22d86c 100644 --- a/src/TSMapEditor/Config/Constants.ini +++ b/src/TSMapEditor/Config/Constants.ini @@ -48,7 +48,7 @@ GameRegistryInstallPath=SOFTWARE\DawnOfTheTiberiumAge ; Specifies the file filter string used in OpenFileDialog (Windows) ; For multiple file formats, list them with : (instead of ;) ; Example config with multiple file extensions: "YR maps|*.map:*.mpr:*.yrm|All files|*.*" -OpenFileDialogFilter=TS maps|*.map|All files|*.* +OpenMapFileDialogFilter=TS maps|*.map|All files|*.* ; Should the editor consider Ares [#include] or Phobos [$Include] section? EnableIniInclude=false diff --git a/src/TSMapEditor/Config/Importer/Default.ini b/src/TSMapEditor/Config/Importer/Default.ini new file mode 100644 index 000000000..4cd6f6ce0 --- /dev/null +++ b/src/TSMapEditor/Config/Importer/Default.ini @@ -0,0 +1,32 @@ +; C&C World-Altering Editor (WAE) +; https://github.com/Rampastring/TSMapEditor + +; This file contains the configuration for the Terrain from image importer + +[Tiles] +; Internal name for mapping = TileID +Default=0 ; LAT +Grass=0 +DarkGrass=131 +RoughGrass=418 +Pavement=534 +Sand=493 +Water=322 + +[Colors] +; R,G,B[,A] +Red=255,0,0 +Blue=0,0,255 +Green=0,255,0 +DarkGreen=0,191,0 +Yellow=255,255,0 +Gray=127,127,127 + +[Mapping] +; Color = Tile +Red=RoughGrass +Blue=Water +Green=Grass +DarkGreen=DarkGrass +Yellow=Sand +Gray=Pavement \ No newline at end of file diff --git a/src/TSMapEditor/Config/UI/Windows/CreateNewMapWindow.ini b/src/TSMapEditor/Config/UI/Windows/CreateNewMapWindow.ini index ba1d744c3..e4766f7a6 100644 --- a/src/TSMapEditor/Config/UI/Windows/CreateNewMapWindow.ini +++ b/src/TSMapEditor/Config/UI/Windows/CreateNewMapWindow.ini @@ -1,13 +1,25 @@ [CreateNewMapWindow] -Width=300 -$CC0=lblHeader:XNALabel -$CC1=ddTheater:XNADropDown -$CC2=lblTheater:XNALabel -$CC3=tbWidth:EditorNumberTextBox -$CC4=lblWidth:XNALabel -$CC5=tbHeight:EditorNumberTextBox -$CC6=lblHeight:XNALabel -$CC7=btnCreate:EditorButton +Width=500 +$CC00=lblHeader:XNALabel +$CC01=ddTheater:XNADropDown +$CC02=lblTheater:XNALabel +$CC03=tbWidth:EditorNumberTextBox +$CC04=lblWidth:XNALabel +$CC05=tbHeight:EditorNumberTextBox +$CC06=lblHeight:XNALabel +$CC07=tbBasicHeight:EditorNumberTextBox +$CC08=lblBasicHeight:XNALabel +$CC09=tbTerrainImage:EditorTextBox +$CC10=lblTerrainImage:XNALabel +$CC11=btnSelectTerrainImage:EditorButton +$CC12=tbHeightmap:EditorTextBox +$CC13=lblHeightmap:XNALabel +$CC14=btnSelectHeightmap:EditorButton +$CC15=tbImportConfig:EditorTextBox +$CC16=lblImportConfig:XNALabel +$CC17=btnSelectImportConfig:EditorButton +$CC18=btnCreate:EditorButton +$CC19=btnApplyTerrainImageRatio:EditorButton $Height=getBottom(btnCreate) + EMPTY_SPACE_BOTTOM @@ -43,7 +55,7 @@ Text=Width: [tbHeight] $X=getX(ddTheater) -$Width=getWidth(ddTheater) +$Width=getWidth(ddTheater) - 100 $Y=getBottom(tbWidth) + VERTICAL_SPACING Text=100 PreviousControl=tbWidth @@ -53,10 +65,81 @@ $X=getX(lblTheater) $Y=getY(tbHeight) + 1 Text=Height: +[tbBasicHeight] +$X=getX(ddTheater) +$Width=getWidth(ddTheater) +$Y=getBottom(tbHeight) + VERTICAL_SPACING +Text=0 +PreviousControl=tbHeight + +[lblBasicHeight] +$X=getX(lblTheater) +$Y=getY(tbBasicHeight) + 1 +Text=Base height: + +[tbTerrainImage] +$X=getX(ddTheater) +$Width=getWidth(ddTheater) - 100 +$Y=getBottom(tbBasicHeight) + VERTICAL_SPACING +PreviousControl=tbBasicHeight + +[lblTerrainImage] +$X=getX(lblTheater) +$Y=getY(tbTerrainImage) + 1 +Text=Terrain map: + +[btnSelectTerrainImage] +$Width=100 - HORIZONTAL_SPACING +$Height=getHeight(tbTerrainImage) +$Y=getY(tbTerrainImage) +$X=getX(tbTerrainImage) + getWidth(tbTerrainImage) + HORIZONTAL_SPACING +Text=... + +[tbHeightmap] +$X=getX(ddTheater) +$Width=getWidth(ddTheater) - 100 +$Y=getBottom(tbTerrainImage) + VERTICAL_SPACING +PreviousControl=tbTerrainImage + +[lblHeightmap] +$X=getX(lblTheater) +$Y=getY(tbHeightmap) + 1 +Text=Heightmap: + +[btnSelectHeightmap] +$Width=100 - HORIZONTAL_SPACING +$Height=getHeight(tbHeightmap) +$Y=getY(tbHeightmap) +$X=getX(tbHeightmap) + getWidth(tbHeightmap) + HORIZONTAL_SPACING +Text=... + +[tbImportConfig] +$X=getX(ddTheater) +$Width=getWidth(ddTheater) - 100 +$Y=getBottom(tbHeightmap) + VERTICAL_SPACING +PreviousControl=tbHeightmap + +[lblImportConfig] +$X=getX(lblTheater) +$Y=getY(tbImportConfig) + 1 +Text=Importer config: + +[btnSelectImportConfig] +$Width=100 - HORIZONTAL_SPACING +$Height=getHeight(tbImportConfig) +$Y=getY(tbImportConfig) +$X=getX(tbImportConfig) + getWidth(tbImportConfig) + HORIZONTAL_SPACING +Text=... + [btnCreate] $Width=100 -$Y=getBottom(tbHeight) + EMPTY_SPACE_TOP +$Y=getBottom(tbImportConfig) + EMPTY_SPACE_TOP $X=horizontalCenterOnParent() Text=Create - +[btnApplyTerrainImageRatio] +$Width=100 +$Height=getHeight(tbHeight) +$Y=getY(tbHeight) +$X=500 - getWidth(btnApplyTerrainImageRatio) - HORIZONTAL_SPACING +Text=Auto diff --git a/src/TSMapEditor/Constants.cs b/src/TSMapEditor/Constants.cs index 19e4699fb..8089d2e4b 100644 --- a/src/TSMapEditor/Constants.cs +++ b/src/TSMapEditor/Constants.cs @@ -8,6 +8,7 @@ public static class Constants public static int CellSizeX = 48; public static int CellSizeY = 24; public static int CellHeight => CellSizeY / 2; + public static double CellWHRatio = CellSizeX / CellSizeY; public static int TileColorBufferSize = 576; public static int RenderPixelPadding = 50; @@ -20,10 +21,13 @@ public static class Constants public static string ExpectedClientExecutableName = "DTA.exe"; public static string GameRegistryInstallPath = "SOFTWARE\\DawnOfTheTiberiumAge"; - public static string OpenFileDialogFilter = "TS maps|*.map|All files|*.*"; public static bool EnableIniInclude = false; + public static string OpenMapFileDialogFilter = "TS maps|*.map|All files|*.*"; + public static string OpenImageFileDialogFilter = "Images|*.bmp;*.png;*.jpg;*.jpeg|All files|*.*"; + public static bool EnableIniInheritance = false; + public static string OpenIniFileDialogFilter = "INI|*.ini|All files|*.*"; public static bool IntegerVariables = false; @@ -107,7 +111,7 @@ public static void Init() ExpectedClientExecutableName = constantsIni.GetStringValue(ConstantsSectionName, nameof(ExpectedClientExecutableName), ExpectedClientExecutableName); GameRegistryInstallPath = constantsIni.GetStringValue(ConstantsSectionName, nameof(GameRegistryInstallPath), GameRegistryInstallPath); - OpenFileDialogFilter = constantsIni.GetStringValue(ConstantsSectionName, nameof(OpenFileDialogFilter), OpenFileDialogFilter); + OpenMapFileDialogFilter = constantsIni.GetStringValue(ConstantsSectionName, nameof(OpenMapFileDialogFilter), OpenMapFileDialogFilter); EnableIniInclude = constantsIni.GetBooleanValue(ConstantsSectionName, nameof(EnableIniInclude), EnableIniInclude); EnableIniInheritance = constantsIni.GetBooleanValue(ConstantsSectionName, nameof(EnableIniInheritance), EnableIniInheritance); diff --git a/src/TSMapEditor/Misc/FileSystemExtensions.cs b/src/TSMapEditor/Misc/FileSystemExtensions.cs new file mode 100644 index 000000000..44b6a9f79 --- /dev/null +++ b/src/TSMapEditor/Misc/FileSystemExtensions.cs @@ -0,0 +1,41 @@ +using System; +using System.Windows.Forms; + +namespace TSMapEditor.Misc +{ + public static class FileSystemExtensions + { + public const string AllFilesFilter = "All files|*.*"; + + public static void OpenFile( + Action onOpened, + Action onAborted = null, + string filter = AllFilesFilter, + bool checkFileExist = true, + string initialDirectory = null + ) { +#if WINDOWS + using (OpenFileDialog openFileDialog = new OpenFileDialog()) + { + openFileDialog.InitialDirectory = string.IsNullOrEmpty(initialDirectory) ? Environment.CurrentDirectory : initialDirectory; + + openFileDialog.Filter = string.IsNullOrEmpty(filter) ? AllFilesFilter : filter; + openFileDialog.CheckFileExists = checkFileExist; + openFileDialog.RestoreDirectory = true; + + switch (openFileDialog.ShowDialog()) + { + case DialogResult.OK: + onOpened?.Invoke(openFileDialog.FileName); + break; + default: + onAborted?.Invoke(); + break; + } + } +#else + throw new NotImplementedException($"{nameof(FileSystemExtensions)}::{nameof(OpenFile)}"); +#endif + } + } +} diff --git a/src/TSMapEditor/Misc/TerrainImporter.cs b/src/TSMapEditor/Misc/TerrainImporter.cs new file mode 100644 index 000000000..b964f6ecc --- /dev/null +++ b/src/TSMapEditor/Misc/TerrainImporter.cs @@ -0,0 +1,143 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Rampastring.Tools; +using System; +using System.Collections.Generic; +using TSMapEditor.Models; +using TSMapEditor.Rendering; + +namespace TSMapEditor.Misc +{ + public class TerrainImporter + { + public class Configuration + { + public Dictionary Mapping { get; set; } + public int Default { get; set; } + + public Configuration() {} + public Configuration(string fileName) + { + var tileTypes = new Dictionary(); + var colorTypes = new Dictionary(); + + var iniFile = new IniFile(fileName); + var sTileTypes = iniFile.GetSection("Tiles"); + var sColorTypes = iniFile.GetSection("Colors"); + var sMapping = iniFile.GetSection("Mapping"); + + foreach (var tileType in sTileTypes.Keys) + tileTypes.Add(tileType.Key, int.Parse(tileType.Value)); + foreach (var colorType in sColorTypes.Keys) + colorTypes.Add(colorType.Key, Helpers.ColorFromString(colorType.Value)); + + Mapping = new Dictionary(); + foreach (var mapping in sMapping.Keys) + Mapping.Add(colorTypes[mapping.Key], tileTypes[mapping.Value]); + + Default = tileTypes["Default"]; + } + + public Dictionary ReadTheater(ITheater theater) + { + Dictionary mapping = new Dictionary(); + foreach (var pair in Mapping) + mapping.Add(pair.Key, theater.GetTile(pair.Value)); + return mapping; + } + } + + public Configuration Current { get; set; } + + public TerrainImporter(Configuration configuration) + { + Current = configuration; + } + + public static Color GetPixel(Color[] colors, int x, int y, int width) + { + return colors[x + (y * width)]; + } + public static Color[] GetPixels(Texture2D texture) + { + Color[] colors1D = new Color[texture.Width * texture.Height]; + texture.GetData(colors1D); + return colors1D; + } + + public void Import(Map map, Texture2D terrainMap, Texture2D heightMap, byte basicLevel) + { + Dictionary mapping = Current.ReadTheater(map.TheaterInstance); + var defaultTileImg = map.TheaterInstance.GetTile(Current.Default); + + short w = (short) map.Size.X; + short h = (short) map.Size.Y; + var tiStepX = terrainMap == null ? -1 : Math.Round((double)terrainMap.Width / w); + var tiStepY = terrainMap == null ? -1 : Math.Round((double)terrainMap.Height / h); + var hmStepX = heightMap == null ? -1 : Math.Round((double)heightMap.Width / w); + var hmStepY = heightMap == null ? -1 : Math.Round((double)heightMap.Height / h); + var terrainData = terrainMap == null ? null : GetPixels(terrainMap); + var heightData = heightMap == null ? null : GetPixels(heightMap); + + var offX = 0; + var offY = ((w + h) / -2); + + List tiles = new List(); + var createTile = (int x, int y, int bx, int by, int otx, int oty) => + { + var tileImg = defaultTileImg; + var height = basicLevel; + if (terrainMap != null) + { + var tiX = (int)Math.Clamp(tiStepX * (x + bx), 0, terrainMap.Width - 1); + var tiY = (int)Math.Clamp(tiStepY * (y + by), 0, terrainMap.Height - 1); + var terrainColor = GetPixel(terrainData, tiX, tiY, terrainMap.Width); + tileImg = mapping.ContainsKey(terrainColor) ? mapping[terrainColor] : defaultTileImg; + } + if (heightMap != null) + { + var hmX = (int)Math.Clamp(hmStepX * (x + bx), 0, heightMap.Width - 1); + var hmY = (int)Math.Clamp(hmStepY * (y + by), 0, heightMap.Height - 1); + var heightColor = GetPixel(heightData, hmX, hmY, heightMap.Width); + height += (byte)(((short)heightColor.R + heightColor.G + heightColor.B) / 3); + } + + { + var tileX = 1 + x + y + offX; + var tileY = 1 + h + w - x + y + offY; + var tile = new MapTile(); + + tile.Level = height; + tile.ChangeTileIndex(tileImg.TileID, 0); + + tile.X = (short)Math.Round((double)tileX + otx); tile.Y = (short)Math.Round((double)tileY + oty); + tiles.Add(tile); + } + }; + + for (int y = 0; y < map.Size.Y; y++) + for (int x = 0; x < map.Size.X; x++) + { + // here there is a problem + // if create tile only for (x, y) then it became like chessboard: + // line (x+1, y) will be skipped. + // the easiest way just create tile line for (x+1, y) seperately. + // + // About offset. Some experiments + // *50x*61 <=> *5x*6 + // 100x122 <=> 11x11 + // 150x183 <=> 18x17 + // 200x244 <=> 23x22 + // The conclusion: + // otx = 0 - because the y component can be found in both formulas + // oty = h / 10 + var otx = 0; + var oty = -((h / 6)); + createTile(x, y, 0, 0, otx, oty); + createTile(x, y, 1, 0, 1 + otx, oty); + } + + map.SetTileData(tiles); + } + } +} diff --git a/src/TSMapEditor/Models/Map.cs b/src/TSMapEditor/Models/Map.cs index 37ba5db09..d48bcdfb2 100644 --- a/src/TSMapEditor/Models/Map.cs +++ b/src/TSMapEditor/Models/Map.cs @@ -1786,6 +1786,38 @@ private void CheckForAITriggerTeamWithMaxZeroIssue(AITriggerType aiTrigger, Team } } + public bool ApplyHeightDeltaOnWholeMap(int delta) + { + var theater = TheaterInstance; + + for (int y = 0; y < Size.Y; y++) + for (int x = 0; x < Size.X; x++) + { + var point = new Point2D(x, y); + var tile = GetTile(point); + if (tile == null) + { + PlaceTerrainTileAt(theater.GetTile(0), point); + tile = GetTile(point); + } + + short level = tile.Level; + var newLevel = level + delta; + if (newLevel > Constants.MaxMapHeightLevel || newLevel < 0) + return false; + } + + for (int y = 0; y < Size.Y; y++) + for (int x = 0; x < Size.X; x++) + { + var point = new Point2D(x, y); + var tile = GetTile(point); + tile.Level = (byte)(tile.Level + delta); + } + + return true; + } + public void Clear() { LoadedINI = null; diff --git a/src/TSMapEditor/TSMapEditor.csproj b/src/TSMapEditor/TSMapEditor.csproj index 26e0a8bd9..a699902cb 100644 --- a/src/TSMapEditor/TSMapEditor.csproj +++ b/src/TSMapEditor/TSMapEditor.csproj @@ -62,6 +62,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -390,6 +393,7 @@ + diff --git a/src/TSMapEditor/UI/MainMenu.cs b/src/TSMapEditor/UI/MainMenu.cs index b20a1802d..f89565c4d 100644 --- a/src/TSMapEditor/UI/MainMenu.cs +++ b/src/TSMapEditor/UI/MainMenu.cs @@ -10,6 +10,7 @@ using TSMapEditor.UI.Windows; using TSMapEditor.UI.Windows.MainMenuWindows; using MessageBoxButtons = TSMapEditor.UI.Windows.MessageBoxButtons; +using TSMapEditor.Misc; #if WINDOWS using System.Windows.Forms; @@ -23,9 +24,7 @@ public class MainMenu : EditorPanel private const string DirectoryPrefix = " "; private const int BrowseButtonWidth = 70; - public MainMenu(WindowManager windowManager) : base(windowManager) - { - } + public MainMenu(WindowManager windowManager) : base(windowManager) { } private string gameDirectory; @@ -199,7 +198,18 @@ private void CreateMapWindow_OnCreateNewMap(object sender, CreateNewMapEventArgs throw new InvalidOperationException("Failed to create new map! Returned error message: " + error); MapSetup.LoadTheaterGraphics(WindowManager, gameDirectory); - ((CreateNewMapWindow)sender).OnCreateNewMap -= CreateMapWindow_OnCreateNewMap; + + if(!(e.TerrainImage == null && e.Heightmap != null && e.BasicLevel > 0)) + { + var configuration = new TerrainImporter.Configuration(string.IsNullOrEmpty(e.ImportConfig) ? + Environment.CurrentDirectory + "/Config/Importer/Default.ini" : e.ImportConfig + ); + var importer = new TerrainImporter(configuration); + + MapSetup.ImportTerrain(importer, e.TerrainImage, e.Heightmap, e.BasicLevel); + } + + ((CreateNewMapWindow) sender).OnCreateNewMap -= CreateMapWindow_OnCreateNewMap; } private void ReadGameInstallDirectoryFromRegistry() @@ -303,7 +313,7 @@ private void BtnBrowseMapPath_LeftClick(object sender, EventArgs e) using (OpenFileDialog openFileDialog = new OpenFileDialog()) { openFileDialog.InitialDirectory = tbMapPath.Text; - openFileDialog.Filter = Constants.OpenFileDialogFilter.Replace(':', ';'); + openFileDialog.Filter = Constants.OpenMapFileDialogFilter.Replace(':', ';'); openFileDialog.RestoreDirectory = true; if (openFileDialog.ShowDialog() == DialogResult.OK) diff --git a/src/TSMapEditor/UI/TopBar/TopBarMenu.cs b/src/TSMapEditor/UI/TopBar/TopBarMenu.cs index 9380ff755..2d4979735 100644 --- a/src/TSMapEditor/UI/TopBar/TopBarMenu.cs +++ b/src/TSMapEditor/UI/TopBar/TopBarMenu.cs @@ -265,7 +265,7 @@ private void Open() using (OpenFileDialog openFileDialog = new OpenFileDialog()) { openFileDialog.InitialDirectory = initialPath; - openFileDialog.Filter = Constants.OpenFileDialogFilter.Replace(':', ';'); + openFileDialog.Filter = Constants.OpenMapFileDialogFilter.Replace(':', ';'); openFileDialog.RestoreDirectory = true; if (openFileDialog.ShowDialog() == DialogResult.OK) @@ -287,7 +287,7 @@ private void SaveAs() { saveFileDialog.InitialDirectory = Path.GetDirectoryName(initialPath); saveFileDialog.FileName = Path.GetFileName(initialPath); - saveFileDialog.Filter = Constants.OpenFileDialogFilter.Replace(':', ';'); + saveFileDialog.Filter = Constants.OpenMapFileDialogFilter.Replace(':', ';'); saveFileDialog.RestoreDirectory = true; if (saveFileDialog.ShowDialog() == DialogResult.OK) diff --git a/src/TSMapEditor/UI/Windows/MainMenuWindows/CreateNewMapWindow.cs b/src/TSMapEditor/UI/Windows/MainMenuWindows/CreateNewMapWindow.cs index 1caca5a7a..ba08cac7f 100644 --- a/src/TSMapEditor/UI/Windows/MainMenuWindows/CreateNewMapWindow.cs +++ b/src/TSMapEditor/UI/Windows/MainMenuWindows/CreateNewMapWindow.cs @@ -1,21 +1,34 @@ -using Rampastring.XNAUI; +using Microsoft.Xna.Framework.Graphics; +using Rampastring.XNAUI; using Rampastring.XNAUI.XNAControls; using System; +using System.IO; using TSMapEditor.GameMath; +using TSMapEditor.Misc; using TSMapEditor.UI.Controls; namespace TSMapEditor.UI.Windows.MainMenuWindows { public class CreateNewMapEventArgs : EventArgs { - public CreateNewMapEventArgs(string theater, Point2D mapSize) + public CreateNewMapEventArgs(string theater, Point2D mapSize, Texture2D terrainImage = null, Texture2D heightmap = null, byte basicLevel = 0, string importConfig = null) { Theater = theater; MapSize = mapSize; + BasicLevel = basicLevel; + TerrainImage = terrainImage; + Heightmap = heightmap; + ImportConfig = importConfig; } public string Theater { get; } public Point2D MapSize { get; } + + public byte BasicLevel { get; } + + public Texture2D TerrainImage { get; } + public Texture2D Heightmap { get; } + public string ImportConfig { get; } } public class CreateNewMapWindow : INItializableWindow @@ -35,7 +48,14 @@ public CreateNewMapWindow(WindowManager windowManager, bool canExit) : base(wind private XNADropDown ddTheater; private EditorNumberTextBox tbWidth; private EditorNumberTextBox tbHeight; - + private EditorNumberTextBox tbBasicHeight; + private EditorButton btnSelectTerrainImage; + private EditorTextBox tbTerrainImage; + private EditorButton btnSelectHeightmap; + private EditorTextBox tbHeightmap; + private EditorButton btnSelectImportConfig; + private EditorTextBox tbImportConfig; + private EditorButton btnApplyTerrainImageRatio; public override void Initialize() { @@ -47,8 +67,24 @@ public override void Initialize() ddTheater = FindChild(nameof(ddTheater)); tbWidth = FindChild(nameof(tbWidth)); tbHeight = FindChild(nameof(tbHeight)); + tbBasicHeight = FindChild(nameof(tbBasicHeight)); + + btnSelectTerrainImage = FindChild(nameof(btnSelectTerrainImage)); + tbTerrainImage = FindChild(nameof(tbTerrainImage)); + + btnSelectHeightmap = FindChild(nameof(btnSelectHeightmap)); + tbHeightmap = FindChild(nameof(tbHeightmap)); + + btnSelectImportConfig = FindChild(nameof(btnSelectImportConfig)); + tbImportConfig = FindChild(nameof(tbImportConfig)); + + btnApplyTerrainImageRatio = FindChild(nameof(btnApplyTerrainImageRatio)); FindChild("btnCreate").LeftClick += BtnCreate_LeftClick; + btnSelectTerrainImage.LeftClick += BtnBrowseTerrainImage_LeftClick; + btnSelectHeightmap.LeftClick += BtnBrowseHeightmap_LeftClick; + btnSelectTerrainImage.LeftClick += BtnBrowseImportConfig_LeftClick; + btnApplyTerrainImageRatio.LeftClick += BtnApplyTerrainImageRatio_LeftClick; ddTheater.SelectedIndex = 0; @@ -92,8 +128,105 @@ private void BtnCreate_LeftClick(object sender, EventArgs e) return; } - OnCreateNewMap?.Invoke(this, new CreateNewMapEventArgs(ddTheater.SelectedItem.Text, new Point2D(tbWidth.Value, tbHeight.Value))); + var bmpTerrainImage = LoadTerrainImage(); + var bmpHeightmap = LoadHeightmap(); + + OnCreateNewMap?.Invoke(this, new CreateNewMapEventArgs( + ddTheater.SelectedItem.Text, + new Point2D(tbWidth.Value, tbHeight.Value), + bmpTerrainImage, bmpHeightmap, + (byte) tbBasicHeight.Value, + tbImportConfig.Text + )); WindowManager.RemoveControl(this); } + + private Texture2D LoadTerrainImage() + { + try + { + if (string.IsNullOrWhiteSpace(tbTerrainImage.Text)) + return null; + + Texture2D texture; + using (FileStream fileStream = new FileStream(tbTerrainImage.Text, FileMode.Open)) + { + texture = Texture2D.FromStream(GraphicsDevice, fileStream); + } + return texture; + } + catch (Exception ex) + { + EditorMessageBox.Show(WindowManager, "Import error", "File could not be open.", MessageBoxButtons.OK); + return null; + } + } + + private Texture2D LoadHeightmap() + { + try + { + if (string.IsNullOrWhiteSpace(tbHeightmap.Text)) + return null; + + Texture2D texture; + using (FileStream fileStream = new FileStream(tbHeightmap.Text, FileMode.Open)) + { + texture = Texture2D.FromStream(GraphicsDevice, fileStream); + } + return texture; + } + catch (Exception ex) + { + EditorMessageBox.Show(WindowManager, "Import error", "File could not be open.", MessageBoxButtons.OK); + return null; + } + } + + private void BtnBrowseTerrainImage_LeftClick(object sender, EventArgs e) + { + FileSystemExtensions.OpenFile( + onOpened: (fileName) => + { + tbTerrainImage.Text = fileName; + }, + filter: Constants.OpenImageFileDialogFilter + ); + } + private void BtnBrowseHeightmap_LeftClick(object sender, EventArgs e) + { + FileSystemExtensions.OpenFile( + onOpened: (fileName) => + { + tbHeightmap.Text = fileName; + }, + filter: Constants.OpenImageFileDialogFilter + ); + } + private void BtnBrowseImportConfig_LeftClick(object sender, EventArgs e) + { + FileSystemExtensions.OpenFile( + onOpened: (fileName) => + { + tbImportConfig.Text = fileName; + }, + filter: Constants.OpenIniFileDialogFilter + ); + } + + private void BtnApplyTerrainImageRatio_LeftClick(object sender, EventArgs e) + { + var img = LoadTerrainImage(); + if(img != null) + { + // w1 / h1 = w2 / h2 + // h1 / w1 = h2 / w2 + // w1 = w2 * (h1 / h2) + // h1 = h2 * (w1 / w2) + + tbHeight.Value = ((int)((float) img.Height * Constants.CellWHRatio * (tbWidth.Value) / (float) img.Width)); + //tbWidth.Value = ((int) ((float) bmpTerrainImage.Width * (float.Parse(tbHeight.Text) / (float) bmpTerrainImage.Height))); + } + } } } diff --git a/src/TSMapEditor/UI/Windows/MainMenuWindows/MapSetup.cs b/src/TSMapEditor/UI/Windows/MainMenuWindows/MapSetup.cs index 479f71bf4..a6eb41b44 100644 --- a/src/TSMapEditor/UI/Windows/MainMenuWindows/MapSetup.cs +++ b/src/TSMapEditor/UI/Windows/MainMenuWindows/MapSetup.cs @@ -1,13 +1,15 @@ +using Microsoft.Xna.Framework.Graphics; using Rampastring.Tools; using Rampastring.XNAUI; using System; using System.IO; using TSMapEditor.CCEngine; +using TSMapEditor.Extensions; using TSMapEditor.GameMath; using TSMapEditor.Initialization; +using TSMapEditor.Misc; using TSMapEditor.Models; using TSMapEditor.Rendering; -using TSMapEditor.Extensions; namespace TSMapEditor.UI.Windows.MainMenuWindows { @@ -82,6 +84,11 @@ public static string InitializeMap(string gameDirectory, bool createNew, string return null; } + public static void ImportTerrain(TerrainImporter importer, Texture2D terrainMap, Texture2D heightMap, byte basicLevel) + { + importer.Import(LoadedMap, terrainMap, heightMap, basicLevel); + } + /// /// Loads the theater graphics for the last-loaded map. ///