Skip to content
2 changes: 1 addition & 1 deletion Database/GameDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ public static class GameDatabase
},
new() {
Game = "Abiotic Factor",
AppID = "2816220",
AppID = "2857200",
ExeName = @"AbioticFactor\Binaries\Win64\AbioticFactorServer-Win64-Shipping.exe",
RequiredArgs = "{map}?Listen -log -MaxPlayers={MaxPlayers} -Port={port} -QueryPort={query} -ServerPassword=\"{pass}\" -SteamAppId={steamAppID}",
RelativeConfigPath = @"AbioticFactor\Saved\Config\WindowsServer\GameUserSettings.ini",
Expand Down
284 changes: 283 additions & 1 deletion Design/GridStyler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// ============================================================================
using System.Windows.Forms.DataVisualization.Charting;
using static Synix_Control_Panel.SynixEngine.Core;
using System.Drawing.Drawing2D;

namespace Synix_Control_Panel.Design
{
Expand All @@ -35,11 +36,13 @@ public static void DarkTheme(DataGridView dgv)
dgv.AutoGenerateColumns = false;

// Map Columns to Class Properties
if (dgv.Columns.Contains("colIcon")) dgv.Columns["colIcon"].DataPropertyName = "";
if (dgv.Columns.Contains("colName")) dgv.Columns["colName"].DataPropertyName = "ServerName";
if (dgv.Columns.Contains("colGame")) dgv.Columns["colGame"].DataPropertyName = "Game";
if (dgv.Columns.Contains("colPort")) dgv.Columns["colPort"].DataPropertyName = "Port";
if (dgv.Columns.Contains("colStatus")) dgv.Columns["colStatus"].DataPropertyName = "Status";
dgv.Columns["PlayerCountDisplay"].DefaultCellStyle.ForeColor = Color.Cyan;
if (dgv.Columns.Contains("colPlayerCount")) dgv.Columns["colPlayerCount"].DataPropertyName = "PlayerCount";
if (dgv.Columns.Contains("colUptime")) dgv.Columns["colUptime"].DataPropertyName = "Uptime";

// Header Style (Kills the blue Game column)
dgv.EnableHeadersVisualStyles = false;
Expand All @@ -57,8 +60,246 @@ public static void DarkTheme(DataGridView dgv)
}
}

public static void StyleMinimizeButton(Button btn)
{
// Strip the default UI
btn.FlatStyle = FlatStyle.Flat;
btn.FlatAppearance.BorderSize = 0;
btn.BackColor = Color.Transparent;
btn.FlatAppearance.MouseOverBackColor = Color.Transparent;
btn.FlatAppearance.MouseDownBackColor = Color.Transparent;

btn.Text = "";
btn.TabStop = false;

// Override the Paint event for the smooth pill shape
btn.Paint += (s, e) =>
{
Button b = (Button)s;
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

Point mousePos = b.PointToClient(System.Windows.Forms.Cursor.Position);
bool isHovering = b.ClientRectangle.Contains(mousePos);
bool isPressed = isHovering && (Control.MouseButtons & MouseButtons.Left) == MouseButtons.Left;

Color bgColor = Color.WhiteSmoke;
Color fgColor = Color.Black;

// UPDATED: Much darker, highly visible gray hover colors
if (isPressed)
{
bgColor = Color.FromArgb(160, 160, 160); // Darker gray for click
}
else if (isHovering)
{
bgColor = Color.FromArgb(200, 200, 200); // Noticeable gray for hover
}

// Draw the smooth background curve
using (var path = GetRoundedPath(b.ClientRectangle, 6))
using (var brush = new SolidBrush(bgColor))
{
e.Graphics.FillPath(brush, path);
}

// Draw a perfect, crisp minimize line
int lineWidth = 12;
int lineThickness = 2;

// Calculate exact center
int xPos = (b.Width / 2) - (lineWidth / 2);
int yPos = (b.Height / 2) - (lineThickness / 2) + 2;

using (SolidBrush lineBrush = new SolidBrush(fgColor))
{
e.Graphics.FillRectangle(lineBrush, xPos, yPos, lineWidth, lineThickness);
}
};

// Force instant redraws on mouse interaction
btn.MouseEnter += (s, e) => btn.Invalidate();
btn.MouseLeave += (s, e) => btn.Invalidate();
btn.MouseDown += (s, e) => btn.Invalidate();
btn.MouseUp += (s, e) => btn.Invalidate();
}

public static void StyleIconButton(Button btn, Image icon, Color hoverColor)
{
// 1. Strip the default UI
btn.FlatStyle = FlatStyle.Flat;
btn.FlatAppearance.BorderSize = 0;
btn.BackColor = Color.Transparent;
btn.FlatAppearance.MouseOverBackColor = Color.Transparent;
btn.FlatAppearance.MouseDownBackColor = Color.Transparent;

btn.Text = "";
btn.TabStop = false;

// 2. Override the Paint event for the smooth pill shape and image
btn.Paint += (s, e) =>
{
Button b = (Button)s;
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

// This makes sure the PNG scales down smoothly without looking pixelated
e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

Point mousePos = b.PointToClient(System.Windows.Forms.Cursor.Position);
bool isHovering = b.ClientRectangle.Contains(mousePos);
bool isPressed = isHovering && (Control.MouseButtons & MouseButtons.Left) == MouseButtons.Left;

Color bgColor = Color.WhiteSmoke; // Default background to match your other buttons

// Apply custom hover/click colors
if (isPressed)
{
bgColor = Color.DarkGray;
}
else if (isHovering)
{
bgColor = hoverColor;
}

// Draw the smooth background curve
using (var path = GetRoundedPath(b.ClientRectangle, 6))
using (var brush = new SolidBrush(bgColor))
{
e.Graphics.FillPath(brush, path);
}

// 3. Draw the Icon perfectly centered
if (icon != null)
{
// Calculate a size that fits comfortably inside the pill with a 4px padding
int iconSize = Math.Min(b.Width, b.Height) - 8;
int x = (b.Width - iconSize) / 2;
int y = (b.Height - iconSize) / 2;

e.Graphics.DrawImage(icon, new Rectangle(x, y, iconSize, iconSize));
}
};

// 4. Force instant redraws on mouse interaction
btn.MouseEnter += (s, e) => btn.Invalidate();
btn.MouseLeave += (s, e) => btn.Invalidate();
btn.MouseDown += (s, e) => btn.Invalidate();
btn.MouseUp += (s, e) => btn.Invalidate();
}

public static void StyleCloseButton(Button btn)
{
// 1. Strip the default UI and make it perfectly transparent
btn.FlatStyle = FlatStyle.Flat;
btn.FlatAppearance.BorderSize = 0;
btn.BackColor = Color.Transparent;
btn.FlatAppearance.MouseOverBackColor = Color.Transparent;
btn.FlatAppearance.MouseDownBackColor = Color.Transparent;

// Clear the standard text because we will draw it manually to layer it correctly
btn.Text = "";
btn.TabStop = false;

// 2. Override the Paint event to draw a high-quality smooth shape
btn.Paint += (s, e) =>
{
Button b = (Button)s;

// Turn on high-quality edge smoothing
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

// Determine if the mouse is hovering or actively clicking
Point mousePos = b.PointToClient(System.Windows.Forms.Cursor.Position);
bool isHovering = b.ClientRectangle.Contains(mousePos);
bool isPressed = isHovering && (Control.MouseButtons & MouseButtons.Left) == MouseButtons.Left;

Color bgColor = Color.WhiteSmoke;
Color fgColor = Color.Black;

if (isPressed)
{
bgColor = Color.FromArgb(178, 11, 22); // Dark Red (Click)
fgColor = Color.White;
}
else if (isHovering)
{
bgColor = Color.FromArgb(232, 17, 35); // Bright Red (Hover)
fgColor = Color.White;
}

// Draw the smooth background
using (var path = GetRoundedPath(b.ClientRectangle, 6))
using (var brush = new SolidBrush(bgColor))
{
e.Graphics.FillPath(brush, path);
}

// Draw the text exactly in the center
TextRenderer.DrawText(
e.Graphics,
"✕",
new Font("Segoe UI", 10, FontStyle.Bold),
b.ClientRectangle,
fgColor,
TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter
);
};

// 3. Force the button to redraw itself instantly when the mouse interacts with it
btn.MouseEnter += (s, e) => btn.Invalidate();
btn.MouseLeave += (s, e) => btn.Invalidate();
btn.MouseDown += (s, e) => btn.Invalidate();
btn.MouseUp += (s, e) => btn.Invalidate();
}

private static System.Drawing.Drawing2D.GraphicsPath GetRoundedPath(Rectangle rect, int radius)
{
System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
int d = radius * 2;
path.StartFigure();
path.AddArc(rect.X, rect.Y, d, d, 180, 90);
path.AddArc(rect.Width - d - 1, rect.Y, d, d, 270, 90);
path.AddArc(rect.Width - d - 1, rect.Height - d - 1, d, d, 0, 90);
path.AddArc(rect.X, rect.Height - d - 1, d, d, 90, 90);
path.CloseFigure();
return path;
}

public static void ApplyRoundedCorners(DataGridView dgv, int radius)
{
// Apply the rounded corners immediately
UpdateGridRegion(dgv, radius);

// Ensure the rounded corners recalculate if the form is resized
dgv.Resize += (s, e) => UpdateGridRegion(dgv, radius);
}

private static void UpdateGridRegion(DataGridView dgv, int radius)
{
if (dgv == null || dgv.Width == 0 || dgv.Height == 0) return;

int diameter = radius * 2;
GraphicsPath path = new GraphicsPath();

path.StartFigure();
// Top Left Corner
path.AddArc(new Rectangle(0, 0, diameter, diameter), 180, 90);
// Top Right Corner
path.AddArc(new Rectangle(dgv.Width - diameter, 0, diameter, diameter), 270, 90);
// Bottom Right Corner
path.AddArc(new Rectangle(dgv.Width - diameter, dgv.Height - diameter, diameter, diameter), 0, 90);
// Bottom Left Corner
path.AddArc(new Rectangle(0, dgv.Height - diameter, diameter, diameter), 90, 90);
path.CloseFigure();

// Apply the new region and dispose of the old one to prevent memory leaks
Region oldRegion = dgv.Region;
dgv.Region = new Region(path);
oldRegion?.Dispose();
}

public static void ApplyTransparentTheme(DataGridView dgv)
{
dgv.RowHeadersVisible = false;
dgv.BackgroundColor = BackgroundBlack;
dgv.BorderStyle = BorderStyle.None;

Expand All @@ -70,6 +311,47 @@ public static void ApplyTransparentTheme(DataGridView dgv)

dgv.GridColor = Color.FromArgb(45, 45, 45);
dgv.SelectionMode = DataGridViewSelectionMode.FullRowSelect;

// Add this line to trigger the custom border drawing
dgv.RowPostPaint -= Dgv_PaintGlowingSelection; // Prevent multiple subscriptions
dgv.RowPostPaint += Dgv_PaintGlowingSelection;
}

private static void Dgv_PaintGlowingSelection(object sender, DataGridViewRowPostPaintEventArgs e)
{
DataGridView dgv = sender as DataGridView;
if (dgv == null) return;

if ((e.State & DataGridViewElementStates.Selected) == DataGridViewElementStates.Selected)
{
// 1. Get the exact width of the data columns, skipping the row header
int startX = dgv.RowHeadersVisible ? dgv.RowHeadersWidth : 0;
int width = dgv.Columns.GetColumnsWidth(DataGridViewElementStates.Visible) - dgv.HorizontalScrollingOffset;

// 2. Define the bounds. We inset by 2 pixels so the thickest pen doesn't get clipped.
Rectangle bounds = new Rectangle(startX + 2, e.RowBounds.Y + 2, width - 5, e.RowBounds.Height - 5);

Color neonColor = Color.DarkCyan; // The color of the glow

// LAYER 1: The wide, faint blur (Width 5)
using (Pen outerGlow = new Pen(Color.FromArgb(40, neonColor), 5))
{
e.Graphics.DrawRectangle(outerGlow, bounds);
}

// LAYER 2: The tighter, brighter blur (Width 3)
using (Pen innerGlow = new Pen(Color.FromArgb(100, neonColor), 3))
{
e.Graphics.DrawRectangle(innerGlow, bounds);
}

// LAYER 3: The intense hot core (Width 1)
// Using White makes it look like actual glowing gas, but you can change this back to Lime if you prefer.
using (Pen corePen = new Pen(Color.White, 1))
{
e.Graphics.DrawRectangle(corePen, bounds);
}
}
}

public static void PaintTransparentRows(DataGridView dgv, DataGridViewCellPaintingEventArgs e)
Expand Down
13 changes: 13 additions & 0 deletions FileFolderHandler/FileHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,26 @@ public static void LoadServers()
MainGUI.serverList.Clear();
foreach (var server in loadedServers)
{
// 1. Grab the hardcoded data from the switch statement in your screenshot
var masterData = GameDatabase.GetGame(server.Game);
if (masterData != null)
{
server.AppID = masterData.AppID;
server.ExeName = masterData.ExeName;
server.RequiredArgs = masterData.RequiredArgs;
server.Maps = masterData.Maps.ToList();

// 2. Smash the JSON path and Hardcoded ExeName together
string fullExePath = Path.Combine(server.InstallPath, server.ExeName);

// 3. Extract the icon
string iconPath = Synix_Control_Panel.SynixEngine.Core.GetLocalServerIcon(server.AppID, fullExePath);

// 4. Attach it permanently to the object
if (File.Exists(iconPath))
{
server.DisplayIcon = System.Drawing.Image.FromFile(iconPath);
}
}
MainGUI.serverList.Add(server);
}
Expand Down
Binary file added Images/discord.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Images/github.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading