ServerGridEditor/Src/ServerGridEditor/Forms/MainForm.cs
Andrew DeLisa bc0b7b70ba WinForms cleanup, fix #38 (#39)
* fix spelling of "CreateIslndForm"

* sync up values of MinimizeBox, MaximizeBox, ShowInTaskbar, FormBorderStyle, and StartPosition properties on forms

* enable menu items after creating a new project

* improve form names

* add some clarity to warning/question MessageBox.Show text

* invert if statement to reduce nesting and change OKCancel to YesNo
2019-01-07 14:24:32 -05:00

2406 lines
No EOL
100 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using Newtonsoft.Json;
using System.Reflection;
using ImageMagick;
using System.Threading;
using System.Diagnostics;
using ServerGridEditor.Properties;
using System.Runtime.InteropServices;
using ServerGridEditor.Forms;
using ServerGridEditor.Code;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using AtlasGridDataLibrary;
namespace ServerGridEditor
{
public partial class MainForm : Form
{
public static string imgsDir = "./IslandImages";
public static string waterTilesDir = "./WaterTiles";
public static string foregroundTilesDir = "./Foregrounds";
public static string dataDir = "./Data";
public static string exportDir = "./Export";
public static string configSaveFile = dataDir + "/config.json";
public static string islandsSaveFile = dataDir + "/islands.json";
public static string spawnersSaveFile = dataDir + "/spawners.json";
public static string islandsSaveFileBackup = dataDir + "/islands-backup.json";
public void InvalidateMapPanel() { mapPanel.Invalidate(); }
public static string lifecycleBucketsPrefix = "SeamlessTravelData";
public static string lifecycleRuleName = "ExpireRule";
public static string rootDir = "../..";
public static string gameDir = rootDir + "/Projects/ShooterGame";
public static string gameMapsRelativePath = gameDir + "/Content/Maps"; //This is relative to the current location of this directory, and will be overwritten by the saved location in the config
public static string tempJsonFile = "TempGridData.json";
public static string actualJsonFile = "ServerGrid.json";
public static string cellImageNameTemplate = "/{0}_{1}-{2}{3}";
public static string engineExe = rootDir + "/Engine/Binaries/Win64/UE4Editor.exe";
public static string serverArgs = "\"ShooterGame/ShooterGame.uproject\" Ocean?listen?ServerX={0}?ServerY={1}?AltSaveDirectoryName=Server{2}?MapPlayerLocation=true?GridConfig=\"" + tempJsonFile + "\" -log -server -SkipSeamlessTravelCloudBackup -disablesaveload";
public static string serverArgsWithAws = "\"ShooterGame/ShooterGame.uproject\" Ocean?listen?ServerX={0}?ServerY={1}?AltSaveDirectoryName=Server{2}?MapPlayerLocation=true -log -server";
public static string clientArgs = "\"ShooterGame/ShooterGame.uproject\" {0}:{1} -game -Log";
public static string clearSaveDataArg = " -ClearSaveData";
public static string ImageOverridesDirectoryName = "ImageOverrides";
public static int lifecycleDays = 8;
public static float scrollSpeed = 1.5f;
public static float outlineShift = 0.07f;
public static int maxImageSize = 4096;
public static string defaultDiscoImagePath = "Resources/discoZoneBox.png";
public static float lockImgRatio = 0.05f;
public static float bezierNodeRatio = 0.05f;
public static float islandNameScale = 0.01f;
public static float useFullIslandRes = 5000;
public static float islandsNamesMaxRes = 10000;
public Cursor editCursor;
public Project currentProject = null;
public Dictionary<string, Island> islands = new Dictionary<string, Island>();
Image tile = null;
TextureBrush tileBrush = null;
static Image lockImg = null;
public Image foreground = null;
public TextureBrush foregroundBrush = null;
MoveableObjectData CurrentHeldMoveableObject = null;
MoveableObjectData CurrentRotatedMoveableObject = null;
bool bResizingDiscoZone = false;
Point LastMouseLocation;
public Config editorConfig;
public Spawners spawners;
public MainForm()
{
//DoubleBuffered = true;
InitializeComponent();
//replace map panel with a custom one
Panel originalPanel = mapPanel;
Bitmap bmp = (Bitmap)Bitmap.FromFile("Resources/pencur.png");
bmp.MakeTransparent(Color.Black);
IntPtr ptr1 = bmp.GetHicon();
editCursor = new Cursor(ptr1);
lockImg = Image.FromFile("Resources/lock.png");
if (File.Exists(spawnersSaveFile))
spawners = JsonConvert.DeserializeObject<Spawners>(File.ReadAllText(spawnersSaveFile));
else
spawners = new Spawners();
mapPanel = new MapPanel();
mapPanel.AllowDrop = originalPanel.AllowDrop;
mapPanel.BackColor = originalPanel.BackColor;
mapPanel.Location = originalPanel.Location;
mapPanel.Name = originalPanel.Name;
mapPanel.Size = originalPanel.Size;
mapPanel.TabIndex = originalPanel.TabIndex;
mapPanel.Anchor = originalPanel.Anchor;
mapPanel.DragDrop += new System.Windows.Forms.DragEventHandler(this.mapPanel_DragDrop);
mapPanel.DragOver += new System.Windows.Forms.DragEventHandler(this.mapPanel_DragOver);
mapPanel.MouseDown += new System.Windows.Forms.MouseEventHandler(this.mapPanel_MouseDown);
mapPanel.MouseMove += new System.Windows.Forms.MouseEventHandler(this.mapPanel_MouseMove);
mapPanel.MouseUp += new System.Windows.Forms.MouseEventHandler(this.mapPanel_MouseUp);
mapPanel.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.mapPanel_MouseWheel);
((MapPanel)mapPanel).mainForm = this;
Controls.Remove(originalPanel);
Controls.Add(mapPanel);
//Create local dirctories if not found
if (!Directory.Exists(imgsDir))
Directory.CreateDirectory(imgsDir);
if (!Directory.Exists(dataDir))
Directory.CreateDirectory(dataDir);
if (!Directory.Exists(waterTilesDir))
Directory.CreateDirectory(waterTilesDir);
if (!Directory.Exists(foregroundTilesDir))
Directory.CreateDirectory(foregroundTilesDir);
//if (!Directory.Exists(exportDir))
// Directory.CreateDirectory(exportDir);
if (File.Exists(configSaveFile))
{
try
{
editorConfig = JsonConvert.DeserializeObject<Config>(File.ReadAllText(configSaveFile));
}
catch
{
editorConfig = new Config();
}
}
else
editorConfig = new Config();
cellImageSizetxtbox.Text = editorConfig.CellImagesRes + "";
atlasImageSizeTxtBox.Text = editorConfig.AtlasImagesRes + "";
imageQualityTxtbox.Text = editorConfig.ImageQuality + "";
LoadIslands();
SetToolsVisibility(false);
}
public void SaveConfig()
{
string json = JsonConvert.SerializeObject(editorConfig, Formatting.Indented);
File.WriteAllText(configSaveFile, json);
}
public void SetToolsVisibility(bool isVisible)
{
//Hide everything prior to loading
foreach (Control Cont in Controls)
{
if (!(Cont is MenuStrip))
{
Cont.Visible = isVisible;
}
}
loadProjBtn.Visible = !isVisible;
createProjBtn.Visible = !isVisible;
}
public void EnableProjectMenuItems()
{
editToolStripMenuItem.Enabled = true;
saveToolStripMenuItem.Enabled = true;
mapImageToolStripMenuItem.Enabled = true;
slippyMapToolStripMenuItem.Enabled = true;
cellImagesToolStripMenuItem.Enabled = true;
localExportToolStripMenuItem.Enabled = true;
editServerTemplatesToolStripMenuItem.Enabled = true;
testAllServersWithoutDataClearToolStripMenuItem.Enabled = true;
}
public void SetScaleTxt(float unrealUnits)
{
scaleLbl.Text = "1 pixel = " + unrealUnits + " unreal units";
}
public void RefreshIslandList()
{
ImageList imgList = new ImageList();
imgList.ImageSize = new Size(64, 64);
imgList.ColorDepth = ColorDepth.Depth32Bit;
int selectedIndex = islandListBox.SelectedItems.Count > 0 ? islandListBox.SelectedItems[0].Index : 0;
int topItemIndex = islandListBox.TopItem != null ? islandListBox.TopItem.Index : selectedIndex;
islandListBox.Items.Clear();
islandListBox.LargeImageList = imgList;
islandListBox.SmallImageList = imgList;
int i = 0;
List<string> SortedIslands = islands.Keys.ToList();
SortedIslands.Sort();
foreach (string islandKey in SortedIslands)
{
Island island = islands[islandKey];
imgList.Images.Add(island.GetImage());
ListViewItem listItem = new ListViewItem();
listItem.ImageIndex = i;
listItem.SubItems.Add(island.x + "x" + island.y);
listItem.SubItems.Add(island.name);
islandListBox.Items.Add(listItem);
i++;
}
islandListBox.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
if (topItemIndex < islandListBox.Items.Count)
islandListBox.TopItem = islandListBox.Items[topItemIndex];
islandListBox.Select();
islandListBox.HideSelection = false;
ListViewItem item = null;
if (selectedIndex < islandListBox.Items.Count)
item = islandListBox.Items[selectedIndex];
else if (islandListBox.Items.Count > 0)
item = islandListBox.Items[islandListBox.Items.Count - 1];
if (item != null)
{
item.EnsureVisible();
islandListBox.FocusedItem = item;
item.Selected = true;
}
}
public void mapPanel_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
DrawMapToGraphics(ref g, true);
}
public void UpdateScrollBars()
{
if (currentProject == null)
return;
float cellSize = currentProject.cellSize * currentProject.coordsScaling;
float maxX = currentProject.numOfCellsX * cellSize;
float maxY = currentProject.numOfCellsY * cellSize;
//mapHScrollBar.Maximum = 1;
mapHScrollBar.Enabled = maxX > mapPanel.Width;
if (mapHScrollBar.Enabled)
mapHScrollBar.Maximum = (int)Math.Ceiling(maxX - mapPanel.Width);
mapVScrollBar.Enabled = maxY > mapPanel.Height;
if (mapVScrollBar.Enabled)
mapVScrollBar.Maximum = (int)Math.Ceiling(maxY - mapPanel.Height);
}
public void DrawMapToGraphics(ref Graphics g, bool cull = false, bool ignoreTranslation = false, bool forExport = false)
{
if (currentProject == null)
return;
UpdateScrollBars();
RectangleF? culling = null;
if (cull)
{
float cullMargin = 10;
culling = new RectangleF(mapHScrollBar.Value - cullMargin, mapVScrollBar.Value - cullMargin, mapPanel.Size.Width + 2 * cullMargin, mapPanel.Size.Height + 2 * cullMargin);
}
Color? alphaBackground = null;
if (!alphaBgCheckbox.Checked)
{
alphaBackground = mapPanel.BackColor;
}
DrawMap(
this, islands, g,
showLinesCheckbox.Checked, showServerInfoCheckbox.Checked, showDiscoZoneInfoCheckbox.Checked,
culling, alphaBackground,
tiledBackgroundCheckbox.Checked ? tile : null,
tiledBackgroundCheckbox.Checked ? tileBrush: null,
tileScaleBox.Value,
!ignoreTranslation ? mapHScrollBar.Value : 0,
!ignoreTranslation ? mapVScrollBar.Value : 0,
forExport);
}
static StringFormat centeredStringFormat = new StringFormat
{
LineAlignment = StringAlignment.Center,
Alignment = StringAlignment.Center
};
public static void DrawMap(
MainForm mainForm, IDictionary<string, Island> islands,
Graphics g, bool showLines, bool showServerInfo, bool showDiscoZoneInfo,
RectangleF? culling, Color? alphaBackground,
Image tile, TextureBrush tileBrush, decimal tileScale,
int translateH, int translateV, bool forExport)
{
g.InterpolationMode = InterpolationMode.High;
Project currentProject = mainForm.currentProject;
bool getOptimizedImage = !forExport && (1 / currentProject.coordsScaling > useFullIslandRes);
if(getOptimizedImage)
{
g.InterpolationMode = InterpolationMode.Low;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
//g.CompositingMode = CompositingMode.SourceCopy;
g.SmoothingMode = SmoothingMode.HighSpeed;
g.CompositingQuality = CompositingQuality.HighSpeed;
}
float cellSize = Math.Max(currentProject.cellSize * currentProject.coordsScaling, 0.00001f);
float maxX = currentProject.numOfCellsX * cellSize;
float maxY = currentProject.numOfCellsY * cellSize;
bool cull = culling.HasValue;
RectangleF canvasRect = culling.GetValueOrDefault();
if (alphaBackground.HasValue)
{
g.Clear(alphaBackground.Value);
}
Pen p = new Pen(Color.Black);
if (translateH != 0 || translateV != 0)
{
g.TranslateTransform(-translateH, -translateV);
}
//Draw background
if (tile != null && tileBrush != null)
{
tileBrush.ResetTransform();
tileBrush.ScaleTransform((float)tileScale * currentProject.coordsScaling * 1000, (float)tileScale * currentProject.coordsScaling * 1000);
g.FillRectangle(tileBrush, new Rectangle(0, 0, (int)maxX, (int)maxY));
}
//Draw grid
if (showLines)
{
//horizontal lines
for (int y = 0; y < currentProject.numOfCellsY + 1; ++y)
{
float drawY = y * cellSize;
if (!cull || (drawY >= canvasRect.Top && drawY <= canvasRect.Bottom))
g.DrawLine(p, 0, drawY, currentProject.numOfCellsX * cellSize, drawY);
}
//vertical lines
for (int x = 0; x < currentProject.numOfCellsX + 1; ++x)
{
float drawX = x * cellSize;
if (!cull || (drawX >= canvasRect.Left && drawX <= canvasRect.Right))
g.DrawLine(p, drawX, 0, drawX, currentProject.numOfCellsY * cellSize);
}
}
//Draw islands
float maxWorldX = currentProject.numOfCellsX * currentProject.cellSize;
float maxWorldY = currentProject.numOfCellsY * currentProject.cellSize;
bool optimizeOutIslandNames = !forExport && (1 / currentProject.coordsScaling > islandsNamesMaxRes);
foreach (IslandInstanceData instance in currentProject.islandInstances)
{
Island referencedIsland = instance.GetReferencedIsland(islands);
//Clamp to map
instance.SetWorldLocation(mainForm, new PointF(instance.worldX, instance.worldY));
//Reverse translation to rotate around self
g.TranslateTransform(instance.worldX * currentProject.coordsScaling, instance.worldY * currentProject.coordsScaling);
g.RotateTransform(instance.rotation, System.Drawing.Drawing2D.MatrixOrder.Prepend);
Rectangle drawRect = instance.GetRect(currentProject, islands);
if (!cull || canvasRect.IntersectsWith(drawRect))
{
drawRect.X = -drawRect.Width / 2;
drawRect.Y = -drawRect.Height / 2;
g.DrawImage(referencedIsland.GetImage(getOptimizedImage), drawRect);
if (currentProject.showIslandNames)
{
g.RotateTransform(-instance.rotation);
drawRect.X += drawRect.Width / 2;
drawRect.Y += drawRect.Height / 2;
float IslandSize = Math.Max(Math.Min(referencedIsland.x, referencedIsland.y) * currentProject.coordsScaling, 0.00001f);
Font font = new Font(SystemFonts.DefaultFont.FontFamily, DefaultFont.SizeInPoints * IslandSize * islandNameScale, FontStyle.Regular);
SizeF stringSize = g.MeasureString("T", font);
float dynamicOutlineShift = stringSize.Height * outlineShift;
if (!optimizeOutIslandNames)
{
g.DrawString(referencedIsland.name, font, Brushes.Black, new PointF(drawRect.X + dynamicOutlineShift, drawRect.Y + dynamicOutlineShift), centeredStringFormat);
g.DrawString(referencedIsland.name, font, Brushes.White, new PointF(drawRect.X, drawRect.Y), centeredStringFormat);
}
g.RotateTransform(instance.rotation, System.Drawing.Drawing2D.MatrixOrder.Prepend);
}
}
g.RotateTransform(-instance.rotation);
g.TranslateTransform(-instance.worldX * currentProject.coordsScaling, -instance.worldY * currentProject.coordsScaling);
}
//Draw foreground
if(currentProject.showForeground && mainForm.foregroundBrush != null)
{
mainForm.foregroundBrush.ResetTransform();
mainForm.foregroundBrush.ScaleTransform((float)mainForm.foregroundScaleBox.Value * currentProject.coordsScaling * 1000, (float)mainForm.foregroundScaleBox.Value * currentProject.coordsScaling * 1000);
g.FillRectangle(mainForm.foregroundBrush, new Rectangle(0, 0, (int)maxX, (int)maxY));
}
if (currentProject.DiscoveryZoneImage != null && showDiscoZoneInfo)
{
//Draw Discovery Zones
foreach (DiscoveryZoneData discoInst in currentProject.discoZones)
{
if (discoInst.bIsManuallyPlaced)
continue;
//Clamp to map
discoInst.SetWorldLocation(mainForm, new PointF(discoInst.worldX, discoInst.worldY));
//Reverse translation to rotate around self
g.TranslateTransform(discoInst.worldX * currentProject.coordsScaling, discoInst.worldY * currentProject.coordsScaling);
g.RotateTransform(discoInst.rotation, System.Drawing.Drawing2D.MatrixOrder.Prepend);
Rectangle drawRect = discoInst.GetRect(currentProject);
if (drawRect.Width < 0)
drawRect.Width *= -1;
if (drawRect.Height < 0)
drawRect.Height *= -1;
if (!cull || canvasRect.IntersectsWith(drawRect))
{
drawRect.X = -drawRect.Width / 2;
drawRect.Y = -drawRect.Height / 2;
g.DrawImage(currentProject.DiscoveryZoneImage, drawRect);
}
g.RotateTransform(-discoInst.rotation);
g.TranslateTransform(-discoInst.worldX * currentProject.coordsScaling, -discoInst.worldY * currentProject.coordsScaling);
}
//Draw discoZone info
// if (showDiscoZoneInfo)
{
foreach (DiscoveryZoneData zoneInst in currentProject.discoZones)
{
float zoneSize = Math.Max(zoneInst.sizeX * currentProject.coordsScaling, 0.00001f);
Font font = new Font(SystemFonts.DefaultFont.FontFamily, DefaultFont.SizeInPoints * zoneSize / 200, FontStyle.Regular);
SizeF stringSize = g.MeasureString("T", font);
float dynamicOutlineShift = stringSize.Height * outlineShift;
PointF zoneCenter = new PointF(zoneInst.worldX, zoneInst.worldY);
zoneCenter = new PointF(zoneCenter.X * currentProject.coordsScaling, zoneCenter.Y * currentProject.coordsScaling);
if (cull)
{
RectangleF drawRect = new RectangleF(zoneCenter.X - stringSize.Width / 2, zoneCenter.Y - stringSize.Width / 2, stringSize.Width, 3.3f * stringSize.Height);
if (RectangleF.Intersect(canvasRect, drawRect).IsEmpty)
continue;
}
g.DrawString("name: " + zoneInst.name, font, Brushes.Black, new PointF(zoneCenter.X + dynamicOutlineShift, zoneCenter.Y + dynamicOutlineShift), centeredStringFormat);
zoneCenter.Y += stringSize.Height * 1.1f;
g.DrawString("xp: " + zoneInst.xp, font, Brushes.White, zoneCenter, centeredStringFormat);
}
}
}
//Draw server info
if (showServerInfo)
{
Font font = new Font(SystemFonts.DefaultFont.FontFamily, DefaultFont.SizeInPoints * cellSize / 200, FontStyle.Regular);
SizeF stringSize = g.MeasureString("T", font);
float dynamicOutlineShift = stringSize.Height * outlineShift;
float lockImgSize = lockImgRatio * cellSize;
foreach (Server s in currentProject.servers)
{
PointF serverCenter = new PointF(s.gridX * cellSize + cellSize / 2f, s.gridY * cellSize + cellSize / 2f);
serverCenter.Y -= cellSize * 0.15f;
//Draw locks
if (!forExport)
{
float locksShift = 0;
if (s.islandLocked)
{
var cm = new ColorMatrix(new float[][]
{
new float[] {1, 0, 0, 0, 0},
new float[] {0, 1, 0, 0, 0},
new float[] {0, 0, 1, 0, 0},
new float[] {0, 0, 0, 1, 0},
new float[] {0, 1, 0, 0, 1}
});
var ia = new ImageAttributes();
ia.SetColorMatrix(cm);
g.DrawImage(lockImg, new Rectangle((int)(serverCenter.X + cellSize / 2 - lockImgSize), (int)(serverCenter.Y - cellSize / 2), (int)lockImgSize, (int)lockImgSize),
0, 0, lockImg.Width, lockImg.Height, GraphicsUnit.Pixel, ia);
locksShift += lockImgSize;
}
if (s.discoLocked)
{
var cm = new ColorMatrix(new float[][]
{
new float[] {1, 0, 0, 0, 0},
new float[] {0, 1, 0, 0, 0},
new float[] {0, 0, 1, 0, 0},
new float[] {0, 0, 0, 1, 0},
new float[] {1, 0.5f, 0, 0, 1}
});
var ia = new ImageAttributes();
ia.SetColorMatrix(cm);
g.DrawImage(lockImg, new Rectangle((int)(serverCenter.X + cellSize / 2 - lockImgSize), (int)(serverCenter.Y - cellSize / 2 + locksShift), (int)lockImgSize, (int)lockImgSize),
0, 0, lockImg.Width, lockImg.Height, GraphicsUnit.Pixel, ia);
locksShift += lockImgSize;
}
if (s.pathsLocked)
{
var cm = new ColorMatrix(new float[][]
{
new float[] {1, 0, 0, 0, 0},
new float[] {0, 1, 0, 0, 0},
new float[] {0, 0, 1, 0, 0},
new float[] {0, 0, 0, 1, 0},
new float[] {0, 0, 2, 0, 1}
});
var ia = new ImageAttributes();
ia.SetColorMatrix(cm);
g.DrawImage(lockImg, new Rectangle((int)(serverCenter.X + cellSize / 2 - lockImgSize), (int)(serverCenter.Y - cellSize / 2 + locksShift), (int)lockImgSize, (int)lockImgSize),
0, 0, lockImg.Width, lockImg.Height, GraphicsUnit.Pixel, ia);
locksShift += lockImgSize;
}
}
if (cull)
{
RectangleF drawRect = new RectangleF(serverCenter.X - stringSize.Width / 2, serverCenter.Y - stringSize.Width / 2, stringSize.Width, 3.3f * stringSize.Height);
if (RectangleF.Intersect(canvasRect, drawRect).IsEmpty) //not being drawn, cull
continue;
}
if (!string.IsNullOrWhiteSpace(s.MachineIdTag))
{
string nameToDraw = "(MachineId: " + s.MachineIdTag + ")";
g.DrawString(nameToDraw, font, Brushes.Black, new PointF(serverCenter.X + dynamicOutlineShift, serverCenter.Y + dynamicOutlineShift), centeredStringFormat);
g.DrawString(nameToDraw, font, Brushes.White, serverCenter, centeredStringFormat);
serverCenter.Y += stringSize.Height * 1.1f;
}
if (!string.IsNullOrWhiteSpace(s.name))
{
string nameToDraw = "Name: " + s.name;
g.DrawString(nameToDraw, font, Brushes.Black, new PointF(serverCenter.X + dynamicOutlineShift, serverCenter.Y + dynamicOutlineShift), centeredStringFormat);
g.DrawString(nameToDraw, font, (s.isHomeServer) ? Brushes.Lime : Brushes.White, serverCenter, centeredStringFormat);
serverCenter.Y += stringSize.Height * 1.1f;
}
g.DrawString(string.Format("({0},{1})", s.gridX, s.gridY), font, Brushes.Black, new PointF(serverCenter.X + dynamicOutlineShift, serverCenter.Y + dynamicOutlineShift), centeredStringFormat);
g.DrawString(string.Format("({0},{1})", s.gridX, s.gridY), font, Brushes.White, serverCenter, centeredStringFormat);
serverCenter.Y += stringSize.Height * 1.1f;
g.DrawString("ip: " + s.ip, font, Brushes.Black, new PointF(serverCenter.X + dynamicOutlineShift, serverCenter.Y + dynamicOutlineShift), centeredStringFormat);
g.DrawString("ip: " + s.ip, font, Brushes.White, serverCenter, centeredStringFormat);
serverCenter.Y += stringSize.Height * 1.1f;
g.DrawString("port: " + s.port, font, Brushes.Black, new PointF(serverCenter.X + dynamicOutlineShift, serverCenter.Y + dynamicOutlineShift), centeredStringFormat);
g.DrawString("port: " + s.port, font, Brushes.White, serverCenter, centeredStringFormat);
serverCenter.Y += stringSize.Height * 1.1f;
g.DrawString("gamePort: " + s.gamePort, font, Brushes.Black, new PointF(serverCenter.X + dynamicOutlineShift, serverCenter.Y + dynamicOutlineShift), centeredStringFormat);
g.DrawString("gamePort: " + s.gamePort, font, Brushes.White, serverCenter, centeredStringFormat);
serverCenter.Y += stringSize.Height * 1.1f;
if (!string.IsNullOrWhiteSpace(s.serverTemplateName))
{
ServerTemplateData sT = mainForm.currentProject.GetServerTemplateByName(s.serverTemplateName);
if (sT != null)
{
string templateName = "Template: " + s.serverTemplateName;
g.DrawString(templateName, font, Brushes.Black, new PointF(serverCenter.X + dynamicOutlineShift, serverCenter.Y + dynamicOutlineShift), centeredStringFormat);
g.DrawString(templateName, font, new SolidBrush(sT.GetTemplateColor()), serverCenter, centeredStringFormat);
serverCenter.Y += stringSize.Height * 1.1f;
}
}
}
}
//Draw Ship Paths
if (mainForm.showShipPathsInfoChckBox.Checked)
{
foreach (ShipPathData shipPath in currentProject.shipPaths)
{
List<PointF> bezierPoints = new List<PointF>();
if (shipPath.isLooping)
{
BezierNodeData lastNode = shipPath.Nodes[shipPath.Nodes.Count - 1];
PointF NodeCenter = mainForm.UnrealToMapPoint(new PointF(lastNode.worldX - mainForm.currentProject.cellSize * mainForm.currentProject.numOfCellsX, lastNode.worldY));
bezierPoints.Add(NodeCenter);
PointF NextControlCenter = lastNode.GetNextControlPoint();
NextControlCenter.X -= mainForm.currentProject.cellSize * mainForm.currentProject.numOfCellsX;
NextControlCenter = mainForm.UnrealToMapPoint(NextControlCenter);
if (lastNode.GetNextNode() != null)
{
bezierPoints.Add(NextControlCenter);
bezierPoints.Add(mainForm.UnrealToMapPoint(lastNode.GetNextNode().GetPrevControlPoint()));
}
}
for (int i = 0; i < shipPath.Nodes.Count; i++)
{
BezierNodeData node = shipPath.Nodes[i];
//Draw control nodes
Rectangle nodeRect = node.GetRect(currentProject);
Pen pen = new Pen(i == 0 ? Color.Blue : Color.Black, 5f);
if (!forExport)
g.DrawEllipse(pen, nodeRect);
//Draw the control points as half the size
PointF NodeCenter = mainForm.UnrealToMapPoint(new PointF(node.worldX, node.worldY));
PointF NextControlCenter = mainForm.UnrealToMapPoint(node.GetNextControlPoint());
PointF PrevControlCenter = mainForm.UnrealToMapPoint(node.GetPrevControlPoint());
nodeRect.Width /= 2;
nodeRect.Height /= 2;
nodeRect.Offset(nodeRect.Width / 2, nodeRect.Height / 2);
pen.Width = 2.5f;
pen.Color = Color.Red;
nodeRect.Offset((int)(NextControlCenter.X - NodeCenter.X), (int)(NextControlCenter.Y - NodeCenter.Y));
if (!forExport)
g.DrawEllipse(pen, nodeRect);
nodeRect.Offset((int)(PrevControlCenter.X - NextControlCenter.X), (int)(PrevControlCenter.Y - NextControlCenter.Y));
if (!forExport)
g.DrawEllipse(pen, nodeRect);
bezierPoints.Add(NodeCenter);
if (node.GetNextNode() != null)
{
bezierPoints.Add(NextControlCenter);
if(i == shipPath.Nodes.Count - 1 && shipPath.isLooping)
{
PointF PrevControl = node.GetNextNode().GetPrevControlPoint();
PrevControl.X += mainForm.currentProject.cellSize * mainForm.currentProject.numOfCellsX;
bezierPoints.Add(mainForm.UnrealToMapPoint(PrevControl));
}
else
bezierPoints.Add(mainForm.UnrealToMapPoint(node.GetNextNode().GetPrevControlPoint()));
}
}
if (shipPath.isLooping)
{
BezierNodeData firstNode = shipPath.Nodes[0];
PointF NodeCenter = mainForm.UnrealToMapPoint(new PointF(firstNode.worldX + mainForm.currentProject.cellSize * mainForm.currentProject.numOfCellsX, firstNode.worldY));
bezierPoints.Add(NodeCenter);
}
else
{
//Re add the starting point to close loop
if (shipPath.Nodes.Count > 0)
bezierPoints.Add(shipPath.Nodes[0].GetMapLocation(mainForm));
}
g.DrawBeziers(p, bezierPoints.ToArray());
}
}
}
private void mapPanel_DragDrop(object sender, DragEventArgs e)
{
if (currentProject == null)
return;
Point p = new Point(e.X, e.Y);
p = mapPanel.PointToClient(p);
p = GetTarnsformedMapPoint(p);
PointF worldPoint = MapToUnrealPoint(p);
int id = currentProject.GenerateNewId();
currentProject.islandInstances.Add(new IslandInstanceData().SetFrom((string)e.Data.GetData("".GetType()), worldPoint.X, worldPoint.Y, 0, id));
currentProject.islandInstances.Last().SetDirty(this);
islandListBox.Invalidate();
mapPanel.Invalidate();
}
Point previousMousePos = new Point(0, 0);
float? startRotation = null;
float islandStartRotation = 0;
private void mapPanel_MouseMove(object sender, MouseEventArgs e)
{
if (e.Location == previousMousePos)
return;
Point moveDelta = new Point(e.Location.X - previousMousePos.X, e.Location.Y - previousMousePos.Y);
if (CurrentHeldMoveableObject != null)
{
if (CurrentHeldMoveableObject is DiscoveryZoneData && bResizingDiscoZone)
{
DiscoveryZoneData CurrentHeldDiscoZoneInstance = (DiscoveryZoneData)CurrentHeldMoveableObject;
Point p = e.Location;
p = GetTarnsformedMapPoint(p);
PointF worldPoint = MapToUnrealPoint(p);
PointF MouseDelta = new PointF(CurrentHeldDiscoZoneInstance.startWorldX - worldPoint.X, CurrentHeldDiscoZoneInstance.startWorldY - worldPoint.Y);
CurrentHeldDiscoZoneInstance.sizeX = MouseDelta.X;
CurrentHeldDiscoZoneInstance.sizeY = MouseDelta.Y;
CurrentHeldDiscoZoneInstance.SetWorldLocation(
this, new PointF(CurrentHeldDiscoZoneInstance.startWorldX - CurrentHeldDiscoZoneInstance.sizeX / 2,
CurrentHeldDiscoZoneInstance.startWorldY - CurrentHeldDiscoZoneInstance.sizeY / 2));
}
else
{
CurrentHeldMoveableObject.SetWorldLocation(
this,
new PointF(CurrentHeldMoveableObject.worldX + moveDelta.X / currentProject.coordsScaling,
CurrentHeldMoveableObject.worldY + moveDelta.Y / currentProject.coordsScaling)
);
}
this.Cursor = Cursor.Current = Cursors.SizeAll;
mapPanel.Invalidate();
}
else if (CurrentRotatedMoveableObject != null)
{
float angleToCenter = StaticHelpers.GetAngleOfPoint(new Point((int)(CurrentRotatedMoveableObject.worldX * currentProject.coordsScaling), (int)(CurrentRotatedMoveableObject.worldY * currentProject.coordsScaling)), GetTarnsformedMapPoint(e.Location));
if (startRotation.HasValue)
CurrentRotatedMoveableObject.rotation = islandStartRotation + angleToCenter - startRotation.Value;
else
{
startRotation = angleToCenter;
islandStartRotation = CurrentRotatedMoveableObject.rotation;
}
if(CurrentRotatedMoveableObject is BezierNodeData)
{
float distanceFromCenter = StaticHelpers.GetDistance(GetTarnsformedMapPoint(e.Location), CurrentRotatedMoveableObject.GetMapLocation(this));
BezierNodeData scaledNode = (BezierNodeData)CurrentRotatedMoveableObject;
scaledNode.controlPointsDistance = MapToUnrealDistance(distanceFromCenter);
scaledNode.controlPointsDistance = Math.Max(BezierNodeEx.GetBezierNodeSize(currentProject), scaledNode.controlPointsDistance);
}
CurrentRotatedMoveableObject.SetDirty(this);
this.Cursor = Cursor.Current = Cursors.UpArrow;
mapPanel.Invalidate();
}
else if (e.Button == MouseButtons.Middle)
{
if (mapHScrollBar.Enabled)
mapHScrollBar.Value = Math.Max(mapHScrollBar.Minimum, Math.Min(mapHScrollBar.Maximum, mapHScrollBar.Value - moveDelta.X));
if (mapVScrollBar.Enabled)
mapVScrollBar.Value = Math.Max(mapVScrollBar.Minimum, Math.Min(mapVScrollBar.Maximum, mapVScrollBar.Value - moveDelta.Y));
this.Cursor = Cursor.Current = Cursors.NoMove2D;
mapPanel.Invalidate();
}
else
{
if (mapPanel.Visible && GetFirstMoveableObjectAtLocation(GetTarnsformedMapPoint(e.Location)) != null)
this.Cursor = Cursor.Current = (ModifierKeys == Keys.Control) ? editCursor : Cursors.Hand;
else
this.Cursor = Cursor.Current = Cursors.Default;
}
previousMousePos = e.Location;
Point atlasPoint = GetTarnsformedMapPoint(e.Location);
double LocX = atlasPoint.X / currentProject.coordsScaling;
double LocY = atlasPoint.Y / currentProject.coordsScaling;
if( LocX <= currentProject.cellSize * currentProject.numOfCellsX && LocY <= currentProject.cellSize * currentProject.numOfCellsY)
atlasLocation.Text = "X: " + LocX + " Y: " + LocY;
}
Point middlePressLocation;
private void mapPanel_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
if (ModifierKeys == Keys.Control)
{
IslandInstanceData IslandInst = GetFirstInstanceAtLocation(GetTarnsformedMapPoint(e.Location));
if (IslandInst != null)
{
var editForm = new EditIslandInstance(this, IslandInst);
if (editForm.ShowDialog() == DialogResult.OK)
{
mapPanel.Invalidate();
}
}
else
{
BezierNodeData node = GetFirstBezierNodeAtLocation(GetTarnsformedMapPoint(e.Location));
if (node != null)
{
var editForm = new EditShipPath(node.shipPath);
editForm.ShowDialog();
mapPanel.Invalidate();
}
else
{
Server s = GetServerAtPoint(GetTarnsformedMapPoint(e.Location));
if (s != null)
{
var editForm = new EditServerForm(this);
editForm.targetServer = s;
if (editForm.ShowDialog() == DialogResult.OK)
{
mapPanel.Invalidate();
}
}
}
}
}
else if(ModifierKeys == Keys.Shift)
{
if (currentProject == null || currentProject.DiscoveryZoneImage == null)
return;
LastMouseLocation = e.Location;
DiscoveryZoneData ZoneInst = GetFirstDiscoZoneAtLocation(GetTarnsformedMapPoint(e.Location));
if (ZoneInst != null)
{
CurrentHeldMoveableObject = ZoneInst;
ZoneInst.startWorldX = ZoneInst.worldX - ZoneInst.sizeX / 2;
ZoneInst.startWorldY = ZoneInst.worldY - ZoneInst.sizeX / 2;
bResizingDiscoZone = true;
mapPanel.Invalidate();
}
else
{
Point p = e.Location;
p = GetTarnsformedMapPoint(p);
PointF worldPoint = MapToUnrealPoint(p);
int id = currentProject.GenerateNewId();
currentProject.discoZones.Add(new DiscoveryZoneData().SetFrom("", worldPoint.X, worldPoint.Y, 0.0f, 0.0f, 0, id));
CurrentHeldMoveableObject = currentProject.discoZones[currentProject.discoZones.Count - 1];
bResizingDiscoZone = true;
mapPanel.Invalidate();
}
}
else
{
CurrentHeldMoveableObject = GetFirstMoveableObjectAtLocation(GetTarnsformedMapPoint(e.Location));
if (CurrentHeldMoveableObject != null)
CurrentHeldMoveableObject.SetDirty(this);
}
}
else if (e.Button == MouseButtons.Right)
{
Server s = GetServerAtPoint(GetTarnsformedMapPoint(e.Location));
if (ModifierKeys == Keys.Control)
{
if (s != null)
{
var editForm = new EditDiscoZonesForm(this, s);
editForm.ShowDialog();
}
}
else
{
CurrentRotatedMoveableObject = GetFirstMoveableObjectAtLocation(GetTarnsformedMapPoint(e.Location));
startRotation = null;
}
}
else if (e.Button == MouseButtons.Middle)
{
middlePressLocation.X = mapHScrollBar.Value;
middlePressLocation.Y = mapVScrollBar.Value;
}
}
private void MainForm_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Delete)
{
Point cursorMapPoint = GetTarnsformedMapPoint(mapPanel.PointToClient(Cursor.Position));
IslandInstanceData islandInst = GetFirstInstanceAtLocation(cursorMapPoint);
DiscoveryZoneData discoInst;
BezierNodeData bezierNode;
if (islandInst != null)
{
islandInst.SetDirty(this);
currentProject.islandInstances.Remove(islandInst);
islandListBox.Invalidate();
mapPanel.Invalidate();
}
else if ((discoInst = GetFirstDiscoZoneAtLocation(cursorMapPoint)) != null)
{
currentProject.discoZones.Remove(discoInst);
mapPanel.Invalidate();
}
else if ((bezierNode = GetFirstBezierNodeAtLocation(cursorMapPoint)) != null)
{
if (ModifierKeys == Keys.Shift)
{
currentProject.shipPaths.Remove(bezierNode.shipPath);
mapPanel.Invalidate();
}
else
{
if (!bezierNode.shipPath.DeleteNode(bezierNode))
MessageBox.Show("A bezier path can't have less than 2 points\nTo delete the whole path use Shift + Delete");
else
mapPanel.Invalidate();
}
}
}
if (mapPanel.Visible)
{
if (GetFirstInstanceAtLocation(GetTarnsformedMapPoint(previousMousePos)) != null || GetFirstDiscoZoneAtLocation(GetTarnsformedMapPoint(previousMousePos)) != null)
this.Cursor = Cursor.Current = (ModifierKeys == Keys.Control) ? editCursor : Cursors.Hand;
}
if (e.KeyCode == Keys.L)
{
Server server = GetServerAtPoint(GetTarnsformedMapPoint(previousMousePos));
if (server != null)
{
var locksForm = new LocksForm(this, server);
locksForm.ShowDialog();
mapPanel.Invalidate();
}
}
else if (e.KeyCode == Keys.P)
{
//Create new ship path
if (currentProject != null)
{
Server server = GetServerAtPoint(GetTarnsformedMapPoint(previousMousePos));
if (server != null) //To ensure being in-grid
{
PointF unrealPoint = MapToUnrealPoint(GetTarnsformedMapPoint(previousMousePos));
currentProject.shipPaths.Add(new ShipPathData().SetFrom(this, unrealPoint.X, unrealPoint.Y));
mapPanel.Invalidate();
}
}
}
else if (e.KeyCode == Keys.Add || e.KeyCode == Keys.Oemplus)
{
//Create new ship path
BezierNodeData selectedBezierNode = GetFirstBezierNodeAtLocation(GetTarnsformedMapPoint(previousMousePos));
if (selectedBezierNode != null) //To ensure being in-grid
{
selectedBezierNode.shipPath.AddNode(selectedBezierNode);
mapPanel.Invalidate();
}
}
}
private void MainForm_KeyUp(object sender, KeyEventArgs e)
{
if (mapPanel.Visible)
{
if (GetFirstInstanceAtLocation(GetTarnsformedMapPoint(previousMousePos)) != null || GetFirstDiscoZoneAtLocation(GetTarnsformedMapPoint(previousMousePos)) != null)
this.Cursor = Cursor.Current = (ModifierKeys == Keys.Control) ? editCursor : Cursors.Hand;
}
}
private void mapPanel_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
if (CurrentHeldMoveableObject != null)
{
if(CurrentHeldMoveableObject is DiscoveryZoneData)
{
DiscoveryZoneData DiscoZoneInst = (DiscoveryZoneData)CurrentHeldMoveableObject;
if (e.Location == LastMouseLocation)
{
var editForm = new EditDiscoveryZoneInstance(this, DiscoZoneInst);
if (editForm.ShowDialog() == DialogResult.OK)
{
mapPanel.Invalidate();
}
bResizingDiscoZone = false;
}
else
{
if (bResizingDiscoZone)
{
// Fix image if size is -ve
if (DiscoZoneInst.sizeX < 0)
DiscoZoneInst.sizeX *= -1;
if (DiscoZoneInst.sizeY < 0)
DiscoZoneInst.sizeY *= -1;
mapPanel.Invalidate();
}
bResizingDiscoZone = false;
}
}
CurrentHeldMoveableObject.SetDirty(this);
CurrentHeldMoveableObject = null;
}
}
else if (e.Button == MouseButtons.Right)
{
CurrentRotatedMoveableObject = null;
}
else if (e.Button == MouseButtons.Middle)
{
if (Math.Abs(middlePressLocation.X - mapHScrollBar.Value) < 10 && Math.Abs(middlePressLocation.Y - mapVScrollBar.Value) < 10)
{
IslandInstanceData selectedIsland = GetFirstInstanceAtLocation(GetTarnsformedMapPoint(e.Location), true);
if (selectedIsland != null)
{
EditIsland(selectedIsland.GetReferencedIsland(islands));
}
}
}
}
private void mapPanel_MouseWheel(object sender, MouseEventArgs e)
{
Point mouseLocation = e.Location;
PointF desiredMouseLocation = e.Location;
float desiredHScroll = mapHScrollBar.Value;
float desiredVScroll = mapVScrollBar.Value;
if (e.Delta > 0)
{
currentProject.coordsScaling *= scrollSpeed;
UpdateScrollBars();
desiredMouseLocation.X *= scrollSpeed;
desiredMouseLocation.Y *= scrollSpeed;
desiredHScroll *= scrollSpeed;
desiredVScroll *= scrollSpeed;
}
else
{
currentProject.coordsScaling /= scrollSpeed;
UpdateScrollBars();
desiredMouseLocation.X /= scrollSpeed;
desiredMouseLocation.Y /= scrollSpeed;
desiredHScroll /= scrollSpeed;
desiredVScroll /= scrollSpeed;
}
SetScaleTxt(1 / currentProject.coordsScaling);
if (mapHScrollBar.Enabled)
mapHScrollBar.Value = Math.Max(0, Math.Min(mapHScrollBar.Maximum, (int)(desiredHScroll + desiredMouseLocation.X - mouseLocation.X)));
else
mapHScrollBar.Value = 0;
if (mapVScrollBar.Enabled)
mapVScrollBar.Value = Math.Max(0, Math.Min(mapVScrollBar.Maximum, (int)(desiredVScroll + desiredMouseLocation.Y - mouseLocation.Y)));
else
mapVScrollBar.Value = 0;
mapPanel.Invalidate();
}
public void SaveIslands()
{
//Take backup
if (File.Exists(islandsSaveFile))
File.Copy(islandsSaveFile, islandsSaveFileBackup, true);
string json = JsonConvert.SerializeObject(islands, Formatting.Indented);
File.WriteAllText(islandsSaveFile, json);
}
public void LoadIslands()
{
if (File.Exists(islandsSaveFile))
{
islands = JsonConvert.DeserializeObject<Dictionary<string, Island>>(File.ReadAllText(islandsSaveFile));
RefreshIslandList();
}
}
public void SaveProject()
{
JsonSerializerSettings settings = new JsonSerializerSettings();
string json = JsonConvert.SerializeObject(islands, Formatting.Indented);
File.WriteAllText(islandsSaveFile, json);
}
/// <summary>
/// Creats a completely new project replacing the current one if already there
/// </summary>
public void CreateProject(float CellSize, int xCells, int yCells, string worldFriendlyName, string worldAtlasId, string worldAtlasPassword)
{
currentProject = new Project(CellSize, xCells, yCells);
currentProject.WorldFriendlyName = worldFriendlyName;
currentProject.WorldAtlasPassword = worldAtlasPassword;
currentProject.WorldAtlasId = worldAtlasId;
currentProject.TribeLogConfig = new TribeLogConfigInfo();
currentProject.TravelDataConfig = new BackupConfigInfo();
currentProject.SharedLogConfig = new SharedLogConfigInfo();
SetScaleTxt(1 / currentProject.coordsScaling);
showServerInfoCheckbox.Checked = currentProject.showServerInfo;
showDiscoZoneInfoCheckbox.Checked = currentProject.showDiscoZoneInfo;
showIslandNamesChckBox.Checked = currentProject.showIslandNames;
showShipPathsInfoChckBox.Checked = currentProject.showShipPathsInfo;
disableImageExportingCheckBox.Checked = currentProject.disableImageExporting;
showLinesCheckbox.Checked = currentProject.showLines;
alphaBgCheckbox.Checked = currentProject.alphaBackground;
tiledBackgroundCheckbox.Checked = currentProject.showBackground;
SetTileImage(currentProject.backgroundImgPath);
showForegroundChckBox.Checked = currentProject.showForeground;
SetForegroundImage(currentProject.foregroundImgPath);
SetDiscoverZoneImage(currentProject.discoZonesImagePath);
mapPanel.Invalidate();
mapPanel.Update();
SetToolsVisibility(true);
}
/// <summary>
/// Takes a point relative to the map panel and returns a point with the scrolling transformations applied
/// </summary>
public Point GetTarnsformedMapPoint(Point p)
{
return new Point(p.X + mapHScrollBar.Value, p.Y + mapVScrollBar.Value);
}
/// <summary>
/// Takes a panel point and returns an unreal world point
/// </summary>
public PointF MapToUnrealPoint(Point p)
{
return new PointF(p.X / currentProject.coordsScaling, p.Y / currentProject.coordsScaling);
}
/// <summary>
/// Takes a panel point and returns an unreal world point
/// </summary>
public PointF UnrealToMapPoint(PointF p)
{
return new PointF(p.X * currentProject.coordsScaling, p.Y * currentProject.coordsScaling);
}
/// <summary>
/// Takes a panel point and returns an unreal world point
/// </summary>
public float MapToUnrealDistance(float dist)
{
return dist / currentProject.coordsScaling;
}
/// <summary>
/// Takes a panel point and returns an unreal world point
/// </summary>
public float UnrealToMapDistance(float dist)
{
return dist * currentProject.coordsScaling;
}
/// <summary>
/// Gets the first island instance at a map location
/// </summary>
public IslandInstanceData GetFirstInstanceAtLocation(Point p, bool includeLocked = false)
{
if (currentProject == null)
return null;
Server s = GetServerAtPoint(p);
if (s != null && s.islandLocked && !includeLocked)
return null;
for (int i = currentProject.islandInstances.Count - 1; i >= 0; i--)
{
IslandInstanceData instance = currentProject.islandInstances[i];
if (instance.ContainsPoint(p, this))
{
return instance;
}
}
return null;
}
/// <summary>
/// Gets the first discovery zone instance at a map location
/// </summary>
public DiscoveryZoneData GetFirstDiscoZoneAtLocation(Point p)
{
if (currentProject == null)
return null;
Server s = GetServerAtPoint(p);
if (s != null && s.discoLocked)
return null;
for (int i = currentProject.discoZones.Count - 1; i >= 0; i--)
{
DiscoveryZoneData instance = currentProject.discoZones[i];
if (instance.ContainsPoint(p, this))
{
return instance;
}
}
return null;
}
/// <summary>
/// Gets the first discovery zone instance at a map location
/// </summary>
public BezierNodeData GetFirstBezierNodeAtLocation(Point p)
{
if (currentProject == null)
return null;
Server s = GetServerAtPoint(p);
if (s != null && s.pathsLocked)
return null;
foreach (ShipPathData shipPath in currentProject.shipPaths)
{
foreach (BezierNodeData node in shipPath.Nodes)
{
if(node.ContainsPoint(p, this))
{
return node;
}
}
}
return null;
}
/// <summary>
/// Gets the first Moveable Object at a map location
/// </summary>
public MoveableObjectData GetFirstMoveableObjectAtLocation(Point p)
{
MoveableObjectData foundObj = GetFirstInstanceAtLocation(p);
if (foundObj == null)
foundObj = GetFirstDiscoZoneAtLocation(p);
if (foundObj == null)
foundObj = GetFirstBezierNodeAtLocation(p);
return foundObj;
}
/// <summary>
/// Gets the server by index
/// </summary>
public Server GetServerByIndex(Point idx)
{
if (currentProject == null)
return null;
foreach (Server server in currentProject.servers)
{
if (server.gridX == idx.X && server.gridY == idx.Y)
return server;
}
return null;
}
/// <summary>
/// Gets the server at map point
/// </summary>
public Server GetServerAtPoint(PointF p)
{
if (currentProject == null)
return null;
Point? idx = GetGridIndexAtPoint(p);
if (idx.HasValue)
{
return GetServerByIndex(idx.Value);
}
return null;
}
/// <summary>
/// Gets the grid index of a map point
/// </summary>
public Point? GetGridIndexAtPoint(PointF p)
{
if (currentProject == null)
return null;
float cellSize = currentProject.cellSize * currentProject.coordsScaling;
int x = (int)(p.X / cellSize);
int y = (int)(p.Y / cellSize);
x = Math.Min(currentProject.numOfCellsX - 1, x);
y = Math.Min(currentProject.numOfCellsY - 1, y);
return new Point(x, y);
}
public Bitmap DrawMapToImage(int cellX = -1, int cellY = -1, float resOverride = -1, bool forceResForSingleCell = false)
{
if (currentProject == null || ((cellX == -1 || cellY == -1) && cellX != cellY))
return null;
bool isSingleCell = cellX > -1;
float originalCoordScale = currentProject.coordsScaling;
if (resOverride > -1)
{
float totalUnrealSize = currentProject.cellSize;
if (!isSingleCell)
{
resOverride -= 2; //these pixels are added below in calculations
totalUnrealSize *= Math.Max(currentProject.numOfCellsX, currentProject.numOfCellsY);
}
currentProject.coordsScaling = resOverride / totalUnrealSize;
}
int startX = isSingleCell ? (int)(cellX * currentProject.cellSize * currentProject.coordsScaling) : 0;
int startY = isSingleCell ? (int)(cellY * currentProject.cellSize * currentProject.coordsScaling) : 0;
int sizeX;
int sizeY;
if (isSingleCell)
{
if(forceResForSingleCell && resOverride > -1)
sizeY = sizeX = Math.Min(maxImageSize, (int)resOverride) - 2;
else
sizeY = sizeX = Math.Min(maxImageSize, editorConfig.CellImagesRes) - 2;
}
else
{
sizeX = (int)(currentProject.numOfCellsX * currentProject.cellSize * currentProject.coordsScaling);
sizeY = (int)(currentProject.numOfCellsY * currentProject.cellSize * currentProject.coordsScaling);
}
Rectangle imgSize = new Rectangle(startX, startY, sizeX, sizeY);
float largerDimension = Math.Max(imgSize.Width, imgSize.Height);
float scale = (maxImageSize - 2) / largerDimension;
if (largerDimension > maxImageSize)
{
//Rescale img to avoid memory exceptions
imgSize.Width = Convert.ToInt32(imgSize.Width * scale);
imgSize.Height = Convert.ToInt32(imgSize.Height * scale);
}
imgSize.Width += 2;
imgSize.Height += 2;
//borders margin, add an extra pixel that will be subtracted from the montage export
if (forceResForSingleCell && resOverride > -1)
{
imgSize.Width += 2;
imgSize.Height += 2;
}
Bitmap image = new Bitmap(imgSize.Width, imgSize.Height, PixelFormat.Format16bppRgb555);
Graphics g = Graphics.FromImage(image);
if (isSingleCell)
{
float scaleToFixRes;
if (forceResForSingleCell && resOverride > -1)
scaleToFixRes = (Math.Min(maxImageSize, resOverride) - 2) / (currentProject.cellSize * currentProject.coordsScaling);
else
scaleToFixRes = (Math.Min(maxImageSize, editorConfig.CellImagesRes) - 2) / (currentProject.cellSize * currentProject.coordsScaling);
g.ScaleTransform(scaleToFixRes, scaleToFixRes);
g.TranslateTransform(-startX, -startY);
}
if (largerDimension > maxImageSize)
{
g.ScaleTransform(scale, scale);
}
int previousH = mapHScrollBar.Value;
int previousV = mapVScrollBar.Value;
mapVScrollBar.Value = mapHScrollBar.Value = 0;
DrawMapToGraphics(ref g, false, isSingleCell, true);
mapHScrollBar.Value = previousH;
mapVScrollBar.Value = previousV;
currentProject.coordsScaling = originalCoordScale;
//g.DrawImage(image, imgSize);
return image;
}
public void ExportImage(string filePath, int cellX = -1, int cellY = -1, bool exportOverrides = true, float resOverride = -1)
{
Bitmap image = null;
//if (exportOverrides)
//{
// if (cellX == -1 && cellY == -1)
// {
// image = currentProject.GetImageOverride();
// }
// else
// {
// Server correspondingServer = GetServerByIndex(new Point(cellX, cellY));
// image = correspondingServer.GetImageOverride(currentProject);
// }
//}
if (image == null)
{
if(cellX == -1 && cellY == -1 && resOverride > maxImageSize)
{
//Using a large resolution, combine cell images instead of exporting a huge one at once
int maxCells = Math.Max(currentProject.numOfCellsX, currentProject.numOfCellsY);
float resPerCell = (float)Math.Round(resOverride / currentProject.numOfCellsX);
Bitmap[,] cellImages = new Bitmap[currentProject.numOfCellsX, currentProject.numOfCellsY];
string dir = Path.GetDirectoryName(filePath);
MagickAnyCPU.CacheDirectory = dir;
if (!Directory.Exists(dir + "/magicktemp"))
Directory.CreateDirectory(dir + "/magicktemp");
MagickNET.SetTempDirectory(dir+"/magicktemp");
ImageMagick.ResourceLimits.Memory = 8388608;
for (int i = 0; i < currentProject.numOfCellsX; i++)
for (int j = 0; j < currentProject.numOfCellsY; j++)
{
//Bitmap drawnCell = DrawMapToImage(i, j, resPerCell, true);
//MagickImage mgickCell = new MagickImage(drawnCell);
//mgickCell.Format = MagickFormat.Bmp;
//mgickCell.Write(dir + "/tmpimgCompImg" + i + "-" + j + ".bmp");
//drawnCell.Dispose();
cellImages[i, j] = DrawMapToImage(i, j, resPerCell, true);
}
using (MagickImageCollection images = new MagickImageCollection())
{
for (int i = 0; i < currentProject.numOfCellsY; i++)
for (int j = 0; j < currentProject.numOfCellsX; j++)
{
//images.Add(new MagickImage(dir + "/tmpimgCompImg" + j + "-" + i + ".bmp"));
images.Add(new MagickImage(cellImages[j, i]));
cellImages[j, i].Dispose();
cellImages[j, i] = null;
}
MontageSettings montageSettings = new MontageSettings()
{
BackgroundColor = MagickColors.Black,
Geometry = new MagickGeometry(-1, -1, 0, 0),
TileGeometry = new MagickGeometry(currentProject.numOfCellsX, currentProject.numOfCellsY),
BorderWidth = 0,
FrameGeometry = new MagickGeometry(0, 0, 0, 0)
};
IMagickImage atlasMontage = images.Montage(montageSettings);
atlasMontage.Format = MagickFormat.Png;
atlasMontage.Depth = 16;
atlasMontage.Quality = editorConfig.ImageQuality;
//filePath = filePath.Replace(".png", ".tiff").Replace(".jpg", ".tiff");
filePath = filePath.Replace(".jpg", ".png");
atlasMontage.Write(filePath);
}
for (int i = 0; i < currentProject.numOfCellsX; i++)
for (int j = 0; j < currentProject.numOfCellsY; j++)
{
string fName = dir + "/tmpimgCompImg" + i + "-" + j + ".bmp";
if (File.Exists(fName))
File.Delete(fName);
}
return;
}
else
image = DrawMapToImage(cellX, cellY, resOverride);
}
if (image == null)
return;
MagickImage tgaImg = new MagickImage(image);
tgaImg.Format = MagickFormat.Jpeg;
tgaImg.Quality = editorConfig.ImageQuality;
tgaImg.Write(filePath);
tgaImg.Dispose();
}
public void ExportCellImages(string path)
{
if (currentProject == null)
return;
string FullPath = Path.GetDirectoryName(path);
string Extension = Path.GetExtension(path);
string FilenameWithoutExtension = Path.GetFileNameWithoutExtension(path);
for (int i = 0; i < currentProject.numOfCellsX; i++)
{
for (int j = 0; j < currentProject.numOfCellsY; j++)
{
string CellFile = FullPath + string.Format(cellImageNameTemplate, FilenameWithoutExtension , i, j, Extension);
ExportImage(CellFile, i, j, true, editorConfig.CellImagesRes);
}
}
}
///////////////////////////Action Handlers///////////////////////////////////
private void addIslandBtn_Click(object sender, EventArgs e)
{
var createForm = new CreateIslandForm();
createForm.mainForm = this;
createForm.ShowDialog();
}
private void islandListBox_ItemDrag(object sender, ItemDragEventArgs e)
{
if (islandListBox.SelectedItems.Count > 0)
islandListBox.DoDragDrop(islandListBox.SelectedItems[0].SubItems[2].Text, DragDropEffects.All);
}
private void mapPanel_DragOver(object sender, DragEventArgs e)
{
if (currentProject == null)
e.Effect = DragDropEffects.None;
else
e.Effect = DragDropEffects.All;
}
private void mapHScrollBar_Scroll(object sender, ScrollEventArgs e)
{
mapPanel.Invalidate();
mapPanel.Update();
}
private void mapVScrollBar_Scroll(object sender, ScrollEventArgs e)
{
mapPanel.Invalidate();
mapPanel.Update();
}
private void createToolStripMenuItem_Click(object sender, EventArgs e)
{
if (currentProject != null)
{
MessageBox.Show("If you create a new project, any unsaved changes to your current project will be LOST!");
}
var createForm = new CreateProjectForm();
createForm.mainForm = this;
createForm.ShowDialog();
}
private void saveToolStripMenuItem_Click(object sender, EventArgs e)
{
if (currentProject == null)
return;
saveFileDialog.Filter = "json files (*.json)|*.json";
saveFileDialog.FileName = actualJsonFile;
saveFileDialog.InitialDirectory = GlobalSettings.Instance.ProjectsDir;
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
File.WriteAllText(saveFileDialog.FileName, currentProject.Serialize(this));
}
}
void LoadProject()
{
if (currentProject != null)
{
var confirmResult = MessageBox.Show("If you click OK, any unsaved changes to your current project will be LOST!",
"Warning",
MessageBoxButtons.OKCancel);
if (confirmResult != DialogResult.OK)
return;
}
openFileDialog.Filter = "json files (*.json)|*.json";
openFileDialog.InitialDirectory = GlobalSettings.Instance.ProjectsDir;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
string fileName = openFileDialog.FileName;
Project loadedProj = new Project(File.ReadAllText(fileName), this);
if (loadedProj.successfullyLoaded)
{
EnableProjectMenuItems();
actualJsonFile = openFileDialog.SafeFileName;
currentProject = loadedProj;
SetScaleTxt(1 / currentProject.coordsScaling);
SetToolsVisibility(true);
showServerInfoCheckbox.Checked = currentProject.showServerInfo;
showDiscoZoneInfoCheckbox.Checked = currentProject.showDiscoZoneInfo;
showIslandNamesChckBox.Checked = currentProject.showIslandNames;
showShipPathsInfoChckBox.Checked = currentProject.showShipPathsInfo;
disableImageExportingCheckBox.Checked = currentProject.disableImageExporting;
showLinesCheckbox.Checked = currentProject.showLines;
alphaBgCheckbox.Checked = currentProject.alphaBackground;
tiledBackgroundCheckbox.Checked = currentProject.showBackground;
SetTileImage(currentProject.backgroundImgPath);
showForegroundChckBox.Checked = currentProject.showForeground;
SetForegroundImage(currentProject.foregroundImgPath);
SetDiscoverZoneImage(currentProject.discoZonesImagePath);
mapPanel.Invalidate();
mapPanel.Update();
}
}
}
private void mapImageToolStripMenuItem_Click(object sender, EventArgs e)
{
if (currentProject == null)
return;
saveFileDialog.Filter = "jpg files (*.jpg)|*.jpg";
string ExportPath = Path.GetFullPath(GlobalSettings.Instance.ExportDir + actualJsonFile.Replace(".json", ""));
if (!Directory.Exists(ExportPath))
Directory.CreateDirectory(ExportPath);
saveFileDialog.InitialDirectory = ExportPath;
saveFileDialog.FileName = "MapImg.jpg";
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
ExportImage(saveFileDialog.FileName, -1, -1, true, editorConfig.AtlasImagesRes);
}
}
private void controlsToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show("Hold Left click (Move island)\n" +
"Hold Right click (Rotate island)\n" +
"Mouse wheel (Zoom)\n" +
"Delete button (Remove island)\n" +
"Ctrl + click on grid (Edit server info)\n" +
"Ctrl + click on island (Edit island info)\n" +
"Hold middle mouse + drag (Scroll map)\n" +
"Shift + drag (Create discovery zone)\n" +
"Shift + click on discovery zone (Edit discovery zone)\n" +
"L while hovered on cell (Open locks form)\n"+
"P while on map (Spawn ship path)\n" +
"Delete on path nodes (Delete node)\n" +
"Ctrl + click on path node (Edit path)\n" +
"Shift + Delete on path nodes (Delete whole path)\n", "Controls");
}
private void customRatioTxtBox_KeyPress(object sender, KeyPressEventArgs e)
{
StaticHelpers.ForceNumericKeypress(sender, e);
}
private void setRatioBtn_Click(object sender, EventArgs e)
{
float newScaling;
if (float.TryParse(customRatioTxtBox.Text, out newScaling))
{
float desiredHScroll = mapHScrollBar.Value;
float desiredVScroll = mapVScrollBar.Value;
float oldScaling = currentProject.coordsScaling;
PointF centerPoint = GetTarnsformedMapPoint(new Point(mapPanel.Width / 2, mapPanel.Height / 2));
PointF topLeftPoint = GetTarnsformedMapPoint(new Point(0, 0));
PointF centerPointOffset = new PointF(centerPoint.X - topLeftPoint.X, centerPoint.Y - topLeftPoint.Y);
PointF originalCenterPointOffset = new PointF(centerPointOffset.X, centerPointOffset.Y);
currentProject.coordsScaling = 1 / newScaling;
SetScaleTxt(newScaling);
float changeRatio = currentProject.coordsScaling / oldScaling;
desiredHScroll *= changeRatio;
desiredVScroll *= changeRatio;
centerPointOffset.X *= changeRatio;
centerPointOffset.X -= originalCenterPointOffset.X;
centerPointOffset.Y *= changeRatio;
centerPointOffset.Y -= originalCenterPointOffset.Y;
UpdateScrollBars();
float centerChange = (mapPanel.Width / 2) * changeRatio;
if (mapHScrollBar.Enabled)
mapHScrollBar.Value = Math.Max(0, Math.Min(mapHScrollBar.Maximum, (int)(desiredHScroll + centerPointOffset.X)));
else
mapHScrollBar.Value = 0;
if (mapVScrollBar.Enabled)
mapVScrollBar.Value = Math.Max(0, Math.Min(mapVScrollBar.Maximum, (int)(desiredVScroll + centerPointOffset.Y)));
else
mapVScrollBar.Value = 0;
mapPanel.Invalidate();
}
}
private void removeIslandBtn_Click(object sender, EventArgs e)
{
var confirmResult = MessageBox.Show("Removing an island will remove all its instances in the map!\n\nAre you sure?",
"Warning",
MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (confirmResult != DialogResult.Yes)
return;
List<string> islandsToRemove = new List<string>();
foreach (ListViewItem item in islandListBox.SelectedItems)
{
islandsToRemove.Add(item.SubItems[2].Text);
}
if (currentProject != null)
{
for (int i = 0; i < currentProject.islandInstances.Count; i++)
foreach (string islandToRemove in islandsToRemove)
if (currentProject.islandInstances[i].name == islandToRemove)
{
currentProject.islandInstances[i].SetDirty(this);
currentProject.islandInstances.RemoveAt(i);
i--;
}
}
foreach (string islandToRemove in islandsToRemove)
{
//delete the image
islands[islandToRemove].InvalidateImage();
File.Delete(islands[islandToRemove].imagePath);
islands.Remove(islandToRemove);
}
RefreshIslandList();
mapPanel.Invalidate();
SaveIslands();
}
private void showServerInfoCheckbox_CheckedChanged(object sender, EventArgs e)
{
if (currentProject != null)
currentProject.showServerInfo = showServerInfoCheckbox.Checked;
mapPanel.Invalidate();
}
private void showDiscoZoneInfoCheckbox_CheckedChanged(object sender, EventArgs e)
{
if (currentProject != null)
currentProject.showDiscoZoneInfo = showDiscoZoneInfoCheckbox.Checked;
mapPanel.Invalidate();
}
private void showLinesCheckbox_CheckedChanged(object sender, EventArgs e)
{
if (currentProject != null)
currentProject.showLines = showLinesCheckbox.Checked;
mapPanel.Invalidate();
}
private void editToolStripMenuItem_Click(object sender, EventArgs e)
{
if (currentProject == null)
return;
var createForm = new CreateProjectForm();
createForm.mainForm = this;
createForm.editedProject = currentProject;
createForm.ShowDialog();
mapPanel.Invalidate();
}
private void editIslandBtn_Click(object sender, EventArgs e)
{
if (islandListBox.SelectedItems.Count == 0)
return;
Island selectedIsland = islands[islandListBox.SelectedItems[0].SubItems[2].Text];
EditIsland(selectedIsland);
}
private void EditIsland(Island isle)
{
if (isle == null)
return;
var createForm = new CreateIslandForm();
createForm.mainForm = this;
createForm.editedIsland = isle;
if(createForm.ShowDialog() != DialogResult.Cancel && createForm.bIslandNameChanged)
RefreshIslandList();
mapPanel.Invalidate();
}
private void chooseTileBtn_Click(object sender, EventArgs e)
{
if (currentProject == null)
return;
openFileDialog.Filter = "png files (*.png)|*.png|All files (*.*)|*.*";
openFileDialog.FileName = "";
openFileDialog.InitialDirectory = GlobalSettings.Instance.BaseDir + waterTilesDir.Replace("./","");
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
string imgName = waterTilesDir + "/";// + "/" + currentProject.SeamlessWorldId;
if (tileBrush != null)
tileBrush.Dispose();
if (tile != null)
tile.Dispose();
//File.Copy(openFileDialog.FileName, imgName + openFileDialog.SafeFileName, true);
currentProject.showBackground = true;
currentProject.backgroundImgPath = imgName + openFileDialog.SafeFileName;
SetTileImage(currentProject.backgroundImgPath);
tiledBackgroundCheckbox.Checked = true;
}
}
private void chooseDiscoZoneBtn_Click(object sender, EventArgs e)
{
if (currentProject == null)
return;
openFileDialog.Filter = "png files (*.png)|*.png";
openFileDialog.InitialDirectory = GlobalSettings.Instance.BaseDir + "Resources";
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
string imgName = "Resources/discoZoneBox.png";
if (currentProject.DiscoveryZoneImage != null)
currentProject.DiscoveryZoneImage.Dispose();
File.Copy(openFileDialog.FileName, imgName, true);
SetDiscoverZoneImage(openFileDialog.FileName);
currentProject.discoZonesImagePath = imgName;
}
}
void SetTileImage(string fileName)
{
if (tileBrush != null)
tileBrush.Dispose();
tileBrush = null;
if (tile != null)
tile.Dispose();
tile = null;
if (File.Exists(fileName))
{
tile = Image.FromFile(fileName);
tileBrush = new TextureBrush(tile);
}
mapPanel.Invalidate();
}
void SetForegroundImage(string fileName)
{
if (foregroundBrush != null)
foregroundBrush.Dispose();
foregroundBrush = null;
if (foreground != null)
foreground.Dispose();
foreground = null;
if (File.Exists(fileName))
{
foreground = Image.FromFile(fileName);
foregroundBrush = new TextureBrush(foreground);
}
mapPanel.Invalidate();
}
void SetDiscoverZoneImage(string fileName)
{
if (currentProject == null)
return;
if (currentProject.DiscoveryZoneImage != null)
currentProject.DiscoveryZoneImage.Dispose();
currentProject.DiscoveryZoneImage = null;
if (File.Exists(fileName))
{
currentProject.DiscoveryZoneImage = Image.FromFile(fileName);
}
mapPanel.Invalidate();
}
private void tileScaleBox_ValueChanged(object sender, EventArgs e)
{
mapPanel.Invalidate();
}
private void tiledBackgroundCheckbox_CheckedChanged(object sender, EventArgs e)
{
currentProject.showBackground = tiledBackgroundCheckbox.Checked;
mapPanel.Invalidate();
}
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (currentProject != null)
{
var confirmResult = MessageBox.Show("All unsaved changes to your current project will be LOST!", "Warning", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation);
e.Cancel = confirmResult == DialogResult.Cancel;
}
}
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
LoadProject();
}
private void loadProjBtn_Click(object sender, EventArgs e)
{
LoadProject();
}
private void createProjBtn_Click(object sender, EventArgs e)
{
if (currentProject != null)
{
MessageBox.Show("If you create a new project, any unsaved changes to your current project will be LOST!");
}
var createForm = new CreateProjectForm();
createForm.mainForm = this;
createForm.ShowDialog();
}
private void alphaBgCheckbox_CheckedChanged(object sender, EventArgs e)
{
if (currentProject != null)
currentProject.alphaBackground = alphaBgCheckbox.Checked;
}
private void testAllServersWithoutDataClearToolStripMenuItem_Click(object sender, EventArgs e)
{
TestAllServers();
}
void TestAllServers(bool clearSaveData = false)
{
if (currentProject == null)
return;
string jsonFileName = MainForm.gameDir + "/" + MainForm.actualJsonFile;
var enclosingDirectory = Path.GetDirectoryName(jsonFileName);
if (!Directory.Exists(enclosingDirectory))
{
MessageBox.Show($"Asked to create {MainForm.actualJsonFile} in non-existent directory:\n{enclosingDirectory}", "Test Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
File.WriteAllText(jsonFileName, currentProject.Serialize(this));
int i = 0;
foreach (Server server in currentProject.servers)
{
ProcessStartInfo serverStartInfo, clientStartInfo;
server.LaunchPreview(out serverStartInfo, out clientStartInfo, false, clearSaveData, false, ++i);
}
}
private void editSpawnerTemplatesToolStripMenuItem_Click(object sender, EventArgs e)
{
var editForm = new EditSpawnerTemplatesForm(this);
editForm.ShowDialog();
}
//private void editImageOverridesToolStripMenuItem_Click(object sender, EventArgs e)
//{
// if (currentProject == null)
// return;
//
// var imageOverridesForm = new ImageOverridesForm(this);
// imageOverridesForm.ShowDialog();
//}
private void cellImagesToolStripMenuItem_Click(object sender, EventArgs e)
{
if (currentProject == null)
return;
saveFileDialog.Filter = "jpg files (*.jpg)|*.jpg";
string ExportPath = Path.GetFullPath(GlobalSettings.Instance.ExportDir + actualJsonFile.Replace(".json", ""));
if (!Directory.Exists(ExportPath))
Directory.CreateDirectory(ExportPath);
saveFileDialog.InitialDirectory = ExportPath;
saveFileDialog.FileName = "CellImg";
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
ExportCellImages(saveFileDialog.FileName);
}
}
private void cellImageSizeTxtBox_KeyPress(object sender, KeyPressEventArgs e)
{
StaticHelpers.ForceNumericKeypress(sender, e, false);
}
private void cellImageSizeTxtBox_TextChanged(object sender, EventArgs e)
{
int parsed;
if (int.TryParse(cellImageSizetxtbox.Text, out parsed))
editorConfig.CellImagesRes = parsed;
SaveConfig();
}
private void atlasImageSizeTxtBox_KeyPress(object sender, KeyPressEventArgs e)
{
StaticHelpers.ForceNumericKeypress(sender, e, false);
}
private void atlasImageSizeTxtBox_TextChanged(object sender, EventArgs e)
{
int parsed;
if (int.TryParse(atlasImageSizeTxtBox.Text, out parsed))
editorConfig.AtlasImagesRes = parsed;
SaveConfig();
}
private void slippyMapToolStripMenuItem_Click(object sender, EventArgs e)
{
if (currentProject == null)
return;
string outpath;
using (var win = new FolderBrowserDialog())
{
var result = win.ShowDialog(this);
if (result != DialogResult.OK)
return;
outpath = win.SelectedPath;
}
if (string.IsNullOrWhiteSpace(outpath))
return;
try
{
using (var progressForm = new ProgressForm())
{
progressForm.Initialize(SlippyMap.maximumZoomLevel + 2, "Starting...");
progressForm.Show();
this.ExportSlippyMap(
islands, showLinesCheckbox.Checked, showServerInfoCheckbox.Checked, showDiscoZoneInfoCheckbox.Checked,
tile, tileBrush, mapPanel.BackColor, outpath,
(string text) =>
{
Console.WriteLine(text);
progressForm.NextStep(text);
});
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Export Failed",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
MessageBox.Show("Slippy Map exported.", "Slippy Map Exported",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void localExportToolStripMenuItem_Click(object sender, EventArgs e)
{
if (currentProject == null)
return;
try
{
using (FolderBrowserDialog fbd = new FolderBrowserDialog())
{
fbd.SelectedPath = GlobalSettings.Instance.ExportDir;
//if (string.IsNullOrWhiteSpace(editorConfig.LastOpenedFolder) || !Directory.Exists(editorConfig.LastOpenedFolder))
// fbd.SelectedPath = Path.GetFullPath(exportDir);
//else
// fbd.SelectedPath = editorConfig.LastOpenedFolder;
DialogResult result = fbd.ShowDialog();
if (result == DialogResult.OK && !string.IsNullOrWhiteSpace(fbd.SelectedPath))
{
//editorConfig.LastOpenedFolder = exportDir = fbd.SelectedPath;
SaveConfig();
}
else
return;
}
string JsonNameNoExtension = "";
string[] strAr = actualJsonFile.Split('.');
if (strAr.Length > 0)
JsonNameNoExtension = "/" + strAr[0];
string mapExportDir = exportDir + JsonNameNoExtension;
if (!Directory.Exists(mapExportDir))
Directory.CreateDirectory(mapExportDir);
string imgPath = mapExportDir + "/MapImg.jpg";
string cellImgName = "CellImg";
string serverConfigPath = exportDir + "/" + actualJsonFile;
//ServerGrid.json
File.WriteAllText(serverConfigPath, currentProject.Serialize(this, true));
//ServerGrid.ServerOnly.json
ServerGrid_ServerOnlyData ServerOnlyObject = new ServerGrid_ServerOnlyData().SetFromProject(currentProject);//(currentProject);
string serverConfigPathServerOnly = serverConfigPath.Replace(".json", ".ServerOnly.json");
File.WriteAllText(serverConfigPathServerOnly, JsonConvert.SerializeObject(ServerOnlyObject, Formatting.Indented)); //ServerGrid.ServerOnly.json
string gameMapExportDir = Path.GetFullPath(GlobalSettings.Instance.ExportDir + "/" + JsonNameNoExtension);
//Copy to Project/ShooterGame/
if (Directory.Exists(gameDir + "/Build")) //Just end client folder people are unlikely to have for now
{
string path = Path.GetFullPath(gameDir + "/" + Path.GetFileName(serverConfigPath));
if (path != Path.GetFullPath(serverConfigPath))
{
File.Copy(serverConfigPath, path, true);
path = Path.GetFullPath(gameDir + "/" + Path.GetFileName(serverConfigPathServerOnly));
File.Copy(serverConfigPathServerOnly, path, true);
//Overwrite where to export images
gameMapExportDir = Path.GetFullPath(gameDir + "/" + JsonNameNoExtension);
}
}
if (!disableImageExportingCheckBox.Checked)
{
if (!Directory.Exists(gameMapExportDir))
Directory.CreateDirectory(gameMapExportDir);
ExportImage(gameMapExportDir + "/MapImg.jpg", -1, -1, true, editorConfig.AtlasImagesRes);
ExportCellImages(gameMapExportDir + string.Format("/{0}.jpg", cellImgName));
}
MessageBox.Show("Export successful!\nFiles in " + exportDir, "Success");
}
catch (System.Exception ex)
{
MessageBox.Show("Export failed!! Ex: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void editAllDiscoveryZonesToolStripMenuItem_Click(object sender, EventArgs e)
{
var editForm = new EditDiscoZonesForm(this);
editForm.ShowDialog();
}
private void editSpawnPointsToolStripMenuItem_Click(object sender, EventArgs e)
{
var editForm = new EditSpawnRegions(this, null);
editForm.ShowDialog();
}
private void showShipPathsInfoChckBox_CheckedChanged(object sender, EventArgs e)
{
if (currentProject != null)
currentProject.showShipPathsInfo = showShipPathsInfoChckBox.Checked;
mapPanel.Invalidate();
}
public void ShowServerEditSpawnRegionsForm(Server TargetServer)
{
var editForm = new EditSpawnRegions(this, TargetServer);
editForm.ShowDialog();
}
private void disableImageExportingCheckBox_CheckedChanged(object sender, EventArgs e)
{
if (currentProject != null)
currentProject.disableImageExporting = disableImageExportingCheckBox.Checked;
}
private void imageQualityTxtbox_TextChanged(object sender, EventArgs e)
{
int parsed;
if (int.TryParse(imageQualityTxtbox.Text, out parsed))
editorConfig.ImageQuality = parsed;
SaveConfig();
}
private void imageQualityTxtbox_KeyPress(object sender, KeyPressEventArgs e)
{
StaticHelpers.ForceNumericKeypress(sender, e, false);
}
private void showIslandNamesChckBox_CheckedChanged(object sender, EventArgs e)
{
if (currentProject != null)
currentProject.showIslandNames = showIslandNamesChckBox.Checked;
mapPanel.Invalidate();
}
private void showForegroundChckBox_CheckedChanged(object sender, EventArgs e)
{
currentProject.showForeground = showForegroundChckBox.Checked;
mapPanel.Invalidate();
}
private void chooseForegroundBtn_Click(object sender, EventArgs e)
{
if (currentProject == null)
return;
openFileDialog.Filter = "png files (*.png)|*.png";
openFileDialog.InitialDirectory = GlobalSettings.Instance.BaseDir + foregroundTilesDir.Replace("./", "");
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
string imgName = foregroundTilesDir;// + "/" + currentProject.SeamlessWorldId;
if (foregroundBrush != null)
foregroundBrush.Dispose();
if (foreground != null)
foreground.Dispose();
File.Copy(openFileDialog.FileName, imgName, true);
SetForegroundImage(openFileDialog.FileName);
currentProject.showForeground = true;
currentProject.foregroundImgPath = imgName;
showForegroundChckBox.Checked = true;
}
}
private void foregroundScaleBox_ValueChanged(object sender, EventArgs e)
{
mapPanel.Invalidate();
}
private void editServerTemplatesToolStripMenuItem_Click(object sender, EventArgs e)
{
var editForm = new EditServerTemplates(this);
editForm.ShowDialog();
}
static Font astrixFont = new Font(SystemFonts.DefaultFont.FontFamily, DefaultFont.SizeInPoints * 1.5f, FontStyle.Bold);
private void islandListBox_DrawItem(object sender, DrawListViewItemEventArgs e)
{
if (e.Item.Selected)
{
Rectangle rowBounds = e.Bounds;
int leftMargin = e.Item.GetBounds(ItemBoundsPortion.Entire).Left;
Rectangle bounds = new Rectangle(leftMargin, rowBounds.Top, rowBounds.Width - leftMargin, rowBounds.Height);
e.Graphics.FillRectangle(SystemBrushes.Highlight, bounds);
}
//e.DrawDefault = true;
//e.DrawFocusRectangle();
e.DrawText();
}
private void islandListBox_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
if (e.ColumnIndex == 0)
{
Point p = e.Bounds.Location;
p.X += 20;
e.Item.ImageList.Draw(e.Graphics, p, e.ItemIndex);
int instanceCount = 0;
if (currentProject != null)
foreach (IslandInstanceData islandInstance in currentProject.islandInstances)
if (islandInstance.name == e.Item.SubItems[2].Text)
instanceCount++;
if (instanceCount > 0)
{
e.Graphics.DrawString("*" + instanceCount, astrixFont, new SolidBrush(Color.Red), e.Bounds.X + 10, e.Bounds.Y + e.Bounds.Height / 2, centeredStringFormat);
return;
}
}
e.DrawText(TextFormatFlags.VerticalCenter);
//e.DrawFocusRectangle(e.Bounds);
//e.DrawDefault = true;
}
private void islandListBox_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
e.DrawDefault = true;
}
private void editLocksToolStripMenuItem_Click(object sender, EventArgs e)
{
var editForm = new EditAllLocksForm(this);
editForm.ShowDialog();
}
private void cullInvalidPathsToolStripMenuItem_Click(object sender, EventArgs e)
{
if (currentProject == null)
return;
// hold on to the count of culled paths for display purposes
var invalidCount = 0;
// determine the maximum X and Y coordinate that would be valid for this grid
var maxWidth = currentProject.cellSize * currentProject.numOfCellsX;
var maxHeight = currentProject.cellSize * currentProject.numOfCellsY;
var maxDimensions = new PointF(maxWidth, maxHeight);
// remove any path with any node with a coordinate below origin or above the calculated maximum
currentProject.shipPaths.RemoveAll((path) =>
{
foreach (var node in path.Nodes)
{
if (node.worldX < 0 || node.worldX > maxDimensions.X || node.worldY < 0 ||
node.worldY > maxDimensions.Y)
{
invalidCount++;
return true;
}
}
return false;
});
if (invalidCount > 0)
{
MessageBox.Show($"Found and removed {invalidCount} invalid paths!", "Invalid Paths Culled", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show("Did not find any invalid paths to cull!", "No Invalid Paths", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
public class Config
{
//public string LastOpenedFolder = "";
//public string LastMapsFolder = "";
public int CellImagesRes = 2048;
public int AtlasImagesRes = 2048;
public int ImageQuality = 75;
}
}