mirror of
https://github.com/kwsch/NHSE.git
synced 2026-08-22 10:35:15 -05:00
Support for 16x16px per tile and river editor (#668)
* Upgrade to .NET 8 + Nugets * Add support for tile 16x16px instead 1px * Rivers except 2B * River2B
This commit is contained in:
@@ -1,17 +1,20 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using static NHSE.Core.TerrainUnitModel;
|
||||
using static NHSE.Core.LandAngles;
|
||||
|
||||
namespace NHSE.Core
|
||||
{
|
||||
public static class TerrainTileColor
|
||||
{
|
||||
private static readonly Color River = Color.FromArgb(128, 215, 195);
|
||||
private static readonly Color Grass = Color.ForestGreen;
|
||||
|
||||
public static Color GetTileColor(TerrainTile tile)
|
||||
public static Color GetTileColor(TerrainTile tile, int relativeX, int relativeY)
|
||||
{
|
||||
if (tile.UnitModelRoad.IsRoad())
|
||||
return GetRoadColor(tile.UnitModelRoad);
|
||||
var baseColor = GetTileDefaultColor(tile.UnitModel);
|
||||
var baseColor = GetTileDefaultColor(tile.UnitModel, tile.LandMakingAngle, relativeX, relativeY);
|
||||
if (tile.Elevation == 0)
|
||||
return baseColor;
|
||||
|
||||
@@ -37,20 +40,195 @@ private static Color GetRoadColor(TerrainUnitModel mdl)
|
||||
return Color.BurlyWood;
|
||||
}
|
||||
|
||||
private static readonly Color CliffBase = ColorUtil.Blend(Color.ForestGreen, Color.Black, 0.6d);
|
||||
|
||||
private static Color GetTileDefaultColor(TerrainUnitModel mdl)
|
||||
/// <summary>Notes about rivers the number is how many sides / diagonals are water.</summary>
|
||||
private static Color GetRiverColor(TerrainUnitModel mdl, LandAngles landAngle, int relativeX, int relativeY)
|
||||
{
|
||||
return mdl switch
|
||||
{
|
||||
// River0A single "hole" of water land all sides. Rotation does nothing
|
||||
River0A when (relativeX < 4 || relativeX >= 12 || relativeY < 4 || relativeY >= 12) =>
|
||||
Grass,
|
||||
// River1A narrow channel end opening on bottom, land on other sides
|
||||
River1A => landAngle switch
|
||||
{
|
||||
Default when relativeX < 4 || relativeX >= 12 || relativeY < 4 => Grass,
|
||||
Rotate90ClockAnverse when relativeX < 4 || relativeY < 4 || relativeY >= 12 => Grass,
|
||||
Rotate180ClockAnverse when relativeX < 4 || relativeX >= 12 || relativeY >= 12 => Grass,
|
||||
Rotate270ClockAnverse when relativeY < 4 || relativeY >= 12 || relativeX >= 12 => Grass,
|
||||
_ => River
|
||||
},
|
||||
// River2A narrow water channel opening on top and bottom, land left and right
|
||||
River2A => landAngle switch
|
||||
{
|
||||
Default when relativeX is < 4 or >= 12 => Grass,
|
||||
Rotate90ClockAnverse when relativeY is >= 12 or < 4 => Grass,
|
||||
Rotate180ClockAnverse when relativeX is < 4 or >= 12 => Grass,
|
||||
Rotate270ClockAnverse when relativeY is < 4 or >= 12 => Grass,
|
||||
_ => River
|
||||
},
|
||||
// River2B narrow 45 channel angled land top left with nub bottom right
|
||||
River2B => landAngle switch
|
||||
{
|
||||
Default when IsPointInMultiTriangle(relativeX, relativeY, new(4, 15), new(0, 0), new(15, 4), new(0, 15), new(15, 0)) || IsNubOnBottomRight(relativeX, relativeY) || relativeX < 4 || relativeY < 4 => Grass,
|
||||
Rotate90ClockAnverse when IsPointInMultiTriangle(relativeX, relativeY, new(4, 0), new(0, 15), new(15, 12), new(0, 0), new(15, 15)) || IsNubOnTopRight(relativeX, relativeY) || relativeX < 4 || relativeY >= 12 => Grass,
|
||||
Rotate180ClockAnverse when IsPointInMultiTriangle(relativeX, relativeY, new(0, 12), new(15, 15), new(12, 0), new(0, 15), new(15, 0)) || IsNubOnTopLeft(relativeX, relativeY) || relativeX >= 12 || relativeY >= 12 => Grass,
|
||||
Rotate270ClockAnverse when IsPointInMultiTriangle(relativeX, relativeY, new(0, 4), new(15, 0), new(12, 15), new(0, 0), new(15, 15)) || IsNubOnBottomLeft(relativeX, relativeY) || relativeX >= 12 || relativeY < 4 => Grass,
|
||||
_ => River
|
||||
},
|
||||
// River2C narrow 90 channel corner land top left with nub bottom right
|
||||
River2C => landAngle switch
|
||||
{
|
||||
Default when relativeX < 4 || relativeY < 4 || IsNubOnBottomRight(relativeX, relativeY) => Grass,
|
||||
Rotate90ClockAnverse when relativeX < 4 || relativeY >= 12 || IsNubOnTopRight(relativeX, relativeY) => Grass,
|
||||
Rotate180ClockAnverse when relativeX >= 12 || relativeY >= 12 || IsNubOnTopLeft(relativeX, relativeY) => Grass,
|
||||
Rotate270ClockAnverse when relativeX >= 12 || relativeY < 4 || IsNubOnBottomLeft(relativeX, relativeY) => Grass,
|
||||
_ => River
|
||||
},
|
||||
// River3A narrow 3 way land left side, nub top right and bottom right
|
||||
River3A => landAngle switch
|
||||
{
|
||||
Default when relativeX < 4 || IsNubOnTopRight(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) => Grass,
|
||||
Rotate90ClockAnverse when relativeY >= 12 || IsNubOnTopLeft(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY) => Grass,
|
||||
Rotate180ClockAnverse when relativeX >= 12 || IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnTopLeft(relativeX, relativeY) => Grass,
|
||||
Rotate270ClockAnverse when relativeY < 4 || IsNubOnBottomRight(relativeX, relativeY) || IsNubOnBottomLeft(relativeX, relativeY) => Grass,
|
||||
_ => River
|
||||
},
|
||||
// River3B river 45 corner angled land top left, no nub
|
||||
River3B => landAngle switch
|
||||
{
|
||||
Default when IsPointInMultiTriangle(relativeX, relativeY, new(4, 15), new(0, 0), new(15, 4), new(0, 15), new(15, 0)) => Grass,
|
||||
Rotate90ClockAnverse when IsPointInMultiTriangle(relativeX, relativeY, new(4, 0), new(0, 15), new(15, 12), new(0, 0), new(15, 15)) => Grass,
|
||||
Rotate180ClockAnverse when IsPointInMultiTriangle(relativeX, relativeY, new(0, 12), new(15, 15), new(12, 0), new(0, 15), new(15, 0)) => Grass,
|
||||
Rotate270ClockAnverse when IsPointInMultiTriangle(relativeX, relativeY, new(0, 4), new(15, 0), new(12, 15), new(0, 0), new(15, 15)) => Grass,
|
||||
_ => River
|
||||
},
|
||||
// River3C river 90 corner corner land top left, no nub
|
||||
River3C => landAngle switch
|
||||
{
|
||||
Default when relativeX < 4 || relativeY < 4 => Grass,
|
||||
Rotate90ClockAnverse when relativeX < 4 || relativeY >= 12 => Grass,
|
||||
Rotate180ClockAnverse when relativeX >= 12 || relativeY >= 12 => Grass,
|
||||
Rotate270ClockAnverse when relativeX >= 12 || relativeY < 4 => Grass,
|
||||
_ => River
|
||||
},
|
||||
// River4A river side with nub top land left side with nub top right only
|
||||
River4A => landAngle switch
|
||||
{
|
||||
Default when relativeX < 4 || IsNubOnTopRight(relativeX, relativeY) => Grass,
|
||||
Rotate90ClockAnverse when relativeY >= 12 || IsNubOnTopLeft(relativeX, relativeY) => Grass,
|
||||
Rotate180ClockAnverse when relativeX >= 12 || IsNubOnBottomLeft(relativeX, relativeY) => Grass,
|
||||
Rotate270ClockAnverse when relativeY < 4 || IsNubOnBottomRight(relativeX, relativeY) => Grass,
|
||||
_ => River
|
||||
},
|
||||
// River4B river side with nub bottom land left side with nub bottom right only
|
||||
River4B => landAngle switch
|
||||
{
|
||||
Default when relativeX < 4 || IsNubOnBottomRight(relativeX, relativeY) => Grass,
|
||||
Rotate90ClockAnverse when relativeY >= 12 || IsNubOnTopRight(relativeX, relativeY) => Grass,
|
||||
Rotate180ClockAnverse when relativeX >= 12 || IsNubOnTopLeft(relativeX, relativeY) => Grass,
|
||||
Rotate270ClockAnverse when relativeY < 4 || IsNubOnBottomLeft(relativeX, relativeY) => Grass,
|
||||
_ => River
|
||||
},
|
||||
// River4C narrow 4 way nub on all 4 corners, 4 sides water. rotation does nothing
|
||||
River4C when (IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) || IsNubOnTopLeft(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY)) => Grass,
|
||||
// River5A river corner to 2 narrow Nub on top left, top right, and bottom right. 2 narrows meet a river
|
||||
River5A => landAngle switch
|
||||
{
|
||||
Default when IsNubOnTopLeft(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) => Grass,
|
||||
Rotate90ClockAnverse when IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnTopLeft(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY) => Grass,
|
||||
Rotate180ClockAnverse when IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) || IsNubOnTopLeft(relativeX, relativeY) => Grass,
|
||||
Rotate270ClockAnverse when IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY) => Grass,
|
||||
_ => River
|
||||
},
|
||||
// River5B river side land on left side
|
||||
River5B => landAngle switch
|
||||
{
|
||||
Default when relativeX < 4 => Grass,
|
||||
Rotate90ClockAnverse when relativeY >= 12 => Grass,
|
||||
Rotate180ClockAnverse when relativeX >= 12 => Grass,
|
||||
Rotate270ClockAnverse when relativeY < 4 => Grass,
|
||||
_ => River
|
||||
},
|
||||
// River6A river 2 opposing nubs nub on top left and bottom right
|
||||
River6A => landAngle switch
|
||||
{
|
||||
Default when IsNubOnTopLeft(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) => Grass,
|
||||
Rotate90ClockAnverse when IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY) => Grass,
|
||||
Rotate180ClockAnverse when IsNubOnTopLeft(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) => Grass,
|
||||
Rotate270ClockAnverse when IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY) => Grass,
|
||||
_ => River
|
||||
},
|
||||
// River6B river 2 nubs same side nub on bottom left and bottom right corner, where 1 narrow meets river bottom side
|
||||
River6B => landAngle switch
|
||||
{
|
||||
Default when IsNubOnBottomLeft(relativeX, relativeY) || IsNubOnBottomRight(relativeX, relativeY) => Grass,
|
||||
Rotate90ClockAnverse when IsNubOnBottomRight(relativeX, relativeY) || IsNubOnTopRight(relativeX, relativeY) => Grass,
|
||||
Rotate180ClockAnverse when IsNubOnTopRight(relativeX, relativeY) || IsNubOnTopLeft(relativeX, relativeY) => Grass,
|
||||
Rotate270ClockAnverse when IsNubOnTopLeft(relativeX, relativeY) || IsNubOnBottomLeft(relativeX, relativeY) => Grass,
|
||||
_ => River
|
||||
},
|
||||
// River7A river 1 nub nub on bottom left corner, fills gaps of diagonal bank
|
||||
River7A => landAngle switch
|
||||
{
|
||||
Default when IsNubOnBottomLeft(relativeX, relativeY) => Grass,
|
||||
Rotate90ClockAnverse when IsNubOnBottomRight(relativeX, relativeY) => Grass,
|
||||
Rotate180ClockAnverse when IsNubOnTopRight(relativeX, relativeY) => Grass,
|
||||
Rotate270ClockAnverse when IsNubOnTopLeft(relativeX, relativeY) => Grass,
|
||||
_ => River
|
||||
},
|
||||
// River8A river is no land, just water. Rotation doesn't matter
|
||||
River8A => River,
|
||||
_ => River
|
||||
};
|
||||
}
|
||||
|
||||
private static bool IsNubOnTopLeft(int relativeX, int relativeY) => IsPointInTriangle(relativeX, relativeY, new(0, 4), new(0, 0), new(4, 0));
|
||||
private static bool IsNubOnTopRight(int relativeX, int relativeY) => IsPointInTriangle(relativeX, relativeY, new(12, 0), new(15, 0), new(15, 4));
|
||||
private static bool IsNubOnBottomLeft(int relativeX, int relativeY) => IsPointInTriangle(relativeX, relativeY, new(0, 12), new(0, 15), new(4, 15));
|
||||
private static bool IsNubOnBottomRight(int relativeX, int relativeY) => IsPointInTriangle(relativeX, relativeY, new(12, 15), new(15, 15), new(15, 12));
|
||||
|
||||
private static bool IsPointInMultiTriangle(int px, int py, Coordinate a, Coordinate b, Coordinate c, Coordinate vortexA, Coordinate vortexB)
|
||||
{
|
||||
return IsPointInTriangle(px, py, a, vortexA, b)
|
||||
|| IsPointInTriangle(px, py, a, b, c)
|
||||
|| IsPointInTriangle(px, py, c, b, vortexB);
|
||||
}
|
||||
|
||||
private static bool IsPointInTriangle(int px, int py, Coordinate a, Coordinate b, Coordinate c)
|
||||
{
|
||||
Coordinate p = new(px, py);
|
||||
float areaTotal = GetTriangleArea(a, b, c);
|
||||
float area1 = GetTriangleArea(p, b, c);
|
||||
float area2 = GetTriangleArea(a, p, c);
|
||||
float area3 = GetTriangleArea(a, b, p);
|
||||
|
||||
return Math.Abs(areaTotal - (area1 + area2 + area3)) < 0.0001f;
|
||||
}
|
||||
|
||||
private static float GetTriangleArea(Coordinate A, Coordinate B, Coordinate C)
|
||||
{
|
||||
return Math.Abs((A.X * (B.Y - C.Y) +
|
||||
B.X * (C.Y - A.Y) +
|
||||
C.X * (A.Y - B.Y)) / 2.0f);
|
||||
}
|
||||
|
||||
private readonly record struct Coordinate(int X, int Y);
|
||||
|
||||
private static readonly Color CliffBase = ColorUtil.Blend(Grass, Color.Black, 0.6d);
|
||||
|
||||
private static Color GetTileDefaultColor(TerrainUnitModel mdl, ushort landAngle, int relativeX, int relativeY)
|
||||
{
|
||||
var angle = (LandAngles)landAngle;
|
||||
if (mdl.IsRiver())
|
||||
return River;
|
||||
return GetRiverColor(mdl, angle, relativeX, relativeY);
|
||||
if (mdl.IsFall())
|
||||
return Color.DeepSkyBlue;
|
||||
if (mdl.IsCliff())
|
||||
return CliffBase;
|
||||
return Color.ForestGreen;
|
||||
return Grass;
|
||||
}
|
||||
|
||||
private static readonly char[] Numbers = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
|
||||
private static readonly char[] Numbers = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
|
||||
|
||||
public static string GetTileName(TerrainTile tile)
|
||||
{
|
||||
|
||||
@@ -8,8 +8,8 @@ namespace NHSE.Core
|
||||
/// </summary>
|
||||
public class TerrainLayer : MapGrid
|
||||
{
|
||||
public readonly TerrainTile[] Tiles;
|
||||
public readonly byte[] BaseAcres;
|
||||
public TerrainTile[] Tiles { get; init; }
|
||||
public byte[] BaseAcres { get; init; }
|
||||
|
||||
public TerrainLayer(TerrainTile[] tiles, byte[] acres) : base(16, 16, AcreWidth * 16, AcreHeight * 16)
|
||||
{
|
||||
@@ -46,6 +46,7 @@ public byte[] DumpAcre(int acre)
|
||||
var bytes = tile.ToBytesClass();
|
||||
bytes.CopyTo(result, i * TerrainTile.SIZE);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -138,7 +139,7 @@ public bool IsWithinGrid(int acreScale, int relX, int relY)
|
||||
return true;
|
||||
}
|
||||
|
||||
public int GetTileColor(int x, in int y)
|
||||
public int GetTileColor(int x, in int y, int relativeX, int relativeY)
|
||||
{
|
||||
var acre = GetTileAcre(x, y);
|
||||
if (acre != 0)
|
||||
@@ -149,7 +150,7 @@ public int GetTileColor(int x, in int y)
|
||||
}
|
||||
|
||||
var tile = GetTile(x, y);
|
||||
return TerrainTileColor.GetTileColor(tile).ToArgb();
|
||||
return TerrainTileColor.GetTileColor(tile, relativeX, relativeY).ToArgb();
|
||||
}
|
||||
|
||||
private ushort GetTileAcre(int x, int y)
|
||||
|
||||
@@ -255,6 +255,14 @@ public enum TerrainUnitModel : ushort
|
||||
RoadWood8A = 0x111,
|
||||
}
|
||||
|
||||
public enum LandAngles
|
||||
{
|
||||
Default = 0,
|
||||
Rotate90ClockAnverse = 1,
|
||||
Rotate180ClockAnverse = 2,
|
||||
Rotate270ClockAnverse = 3,
|
||||
}
|
||||
|
||||
public static class TerrainUnitModelExtensions
|
||||
{
|
||||
public static bool IsRoad(this TerrainUnitModel t) => t >= RoadBrick0A || (RoadSoil0A <= t && t <= RoadStone8A);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="LibUsbDotNet" Version="2.2.29" />
|
||||
<PackageReference Include="LibUsbDotNet" Version="2.2.75" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -30,7 +30,7 @@ public MapViewer(MapManager m, int scale) : base(m, scale)
|
||||
PixelsItemMap = new int[l1.MaxWidth * l1.MaxHeight * MapScale * MapScale];
|
||||
MapReticle = new Bitmap(l1.MaxWidth * MapScale, l1.MaxHeight * MapScale);
|
||||
|
||||
PixelsBackgroundAcre1 = new int[16 * 16];
|
||||
PixelsBackgroundAcre1 = new int[(int)Math.Pow(16, 4)];
|
||||
PixelsBackgroundAcreX = new int[PixelsItemAcreX.Length];
|
||||
BackgroundAcre = new Bitmap(ScaleAcre.Width, ScaleAcre.Height);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using NHSE.Core;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using NHSE.Core;
|
||||
|
||||
namespace NHSE.Sprites
|
||||
{
|
||||
@@ -23,19 +23,11 @@ public static void CreateMap(TerrainLayer mgr, int[] pixels)
|
||||
{
|
||||
for (int x = 0; x < mgr.MaxWidth; x++, i++)
|
||||
{
|
||||
pixels[i] = mgr.GetTileColor(x, y);
|
||||
pixels[i] = mgr.GetTileColor(x, y, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Bitmap CreateMap(TerrainLayer mgr, int scale, int x, int y, int[] scale1, int[] scaleX, Bitmap map)
|
||||
{
|
||||
CreateMap(mgr, scale1);
|
||||
ImageUtil.ScalePixelImage(scale1, scaleX, map.Width, map.Height, scale);
|
||||
ImageUtil.SetBitmapData(map, scaleX);
|
||||
return DrawReticle(map, mgr, x, y, scale);
|
||||
}
|
||||
|
||||
public static Bitmap CreateMap(TerrainLayer mgr, int[] scale1, int[] scaleX, Bitmap map, int scale, int acreIndex = -1)
|
||||
{
|
||||
CreateMap(mgr, scale1);
|
||||
@@ -111,17 +103,28 @@ private static void DrawBuilding(Graphics gfx, Font? f, int scale, Brush pen, in
|
||||
private static void SetAcreTerrainPixels(int x, int y, TerrainLayer t, int[] data, int[] scaleX, int scale)
|
||||
{
|
||||
GetAcre1(x, y, t, data);
|
||||
ImageUtil.ScalePixelImage(data, scaleX, 16 * scale, 16 * scale, scale);
|
||||
ImageUtil.ScalePixelImage(data, scaleX, 16 * scale, 16 * scale, scale / 16);
|
||||
}
|
||||
|
||||
private static void GetAcre1(int topX, int topY, TerrainLayer t, int[] data)
|
||||
private static void GetAcre1(int tileTopX, int tileTopY, TerrainLayer t, int[] data)
|
||||
{
|
||||
int index = 0;
|
||||
for (int y = 0; y < 16; y++)
|
||||
|
||||
for (int tileY = 0; tileY < 16; tileY++)
|
||||
{
|
||||
var yi = y + topY;
|
||||
for (int x = 0; x < 16; x++, index++)
|
||||
data[index] = t.GetTileColor(x + topX, yi);
|
||||
var tileYIx = tileY + tileTopY;
|
||||
for (int pixelY = 0; pixelY < 16; pixelY++)
|
||||
{
|
||||
for (int tileX = 0; tileX < 16; tileX++)
|
||||
{
|
||||
var tileXIx = tileX + tileTopX;
|
||||
for (int pixelX = 0; pixelX < 16; pixelX++)
|
||||
{
|
||||
data[index] = t.GetTileColor(tileXIx, tileYIx, pixelX, pixelY);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,9 +152,10 @@ public static Bitmap GetAcre(MapView m, Font f, int[] scale1, int[] scaleX, Bitm
|
||||
var pen = index == i ? Selected : Others;
|
||||
if (tbuild != byte.MaxValue)
|
||||
{
|
||||
var orig = ((SolidBrush) pen).Color;
|
||||
var orig = ((SolidBrush)pen).Color;
|
||||
pen = new SolidBrush(Color.FromArgb(tbuild, orig));
|
||||
}
|
||||
|
||||
DrawBuilding(gfx, null, m.TerrainScale, pen, x, y, b, Text);
|
||||
}
|
||||
|
||||
@@ -177,7 +181,7 @@ public static Bitmap GetAcre(MapView m, Font f, int[] scale1, int[] scaleX, Bitm
|
||||
|
||||
private static void DrawTerrainTileNames(int topX, int topY, Graphics gfx, TerrainLayer t, Font f, int scale, byte transparency)
|
||||
{
|
||||
var pen= transparency != byte.MaxValue ? new SolidBrush(Color.FromArgb(transparency, Color.Black)) : Tile;
|
||||
var pen = transparency != byte.MaxValue ? new SolidBrush(Color.FromArgb(transparency, Color.Black)) : Tile;
|
||||
|
||||
for (int y = 0; y < 16; y++)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net46;net6.0-windows</TargetFrameworks>
|
||||
<TargetFrameworks>net46;net8.0-windows</TargetFrameworks>
|
||||
<NeutralLanguage>en</NeutralLanguage>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
<Folder Include="Resources\Villagers\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith('net6'))">
|
||||
<PackageReference Include="System.Drawing.Common" Version="6.0.0" />
|
||||
<PackageReference Include="System.Resources.Extensions" Version="6.0.0" />
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith('net8'))">
|
||||
<PackageReference Include="System.Drawing.Common" Version="8.0.18" />
|
||||
<PackageReference Include="System.Resources.Extensions" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -99,16 +99,18 @@ public static int[] ScalePixelImage(int[] data, int scale, int w, int h, out int
|
||||
public static void ScalePixelImage(int[] data, int[] scaled, int fW, int fH, int scale)
|
||||
{
|
||||
// For each pixel, copy to the X indexes, then block copy the row to the other rows.
|
||||
for (int y = 0, i = 0; y < fH; y += scale)
|
||||
int i = 0;
|
||||
for (int y = 0; y < fH; y += scale)
|
||||
{
|
||||
// Fill the X pixels
|
||||
var baseIndex = y * fW;
|
||||
for (int x = 0; x < fW; x += scale, i++)
|
||||
for (int x = 0; x < fW; x += scale)
|
||||
{
|
||||
var v = data[i];
|
||||
var xi = baseIndex + x;
|
||||
for (int x1 = 0; x1 < scale; x1++)
|
||||
scaled[xi + x1] = v;
|
||||
i++;
|
||||
}
|
||||
|
||||
// Copy entire pixel row down
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" Version="5.10.3" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
|
||||
<PackageReference Include="FluentAssertions" Version="8.5.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net46;net6.0-windows</TargetFrameworks>
|
||||
<TargetFrameworks>net46;net8.0-windows</TargetFrameworks>
|
||||
<NeutralLanguage>en</NeutralLanguage>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith('net6'))">
|
||||
<PackageReference Include="System.Drawing.Common" Version="6.0.0" />
|
||||
<PackageReference Include="System.Resources.Extensions" Version="6.0.0" />
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith('net8'))">
|
||||
<PackageReference Include="System.Drawing.Common" Version="8.0.18" />
|
||||
<PackageReference Include="System.Resources.Extensions" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFrameworks>net46;net6.0-windows</TargetFrameworks>
|
||||
<TargetFrameworks>net46;net8.0-windows</TargetFrameworks>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<Description>Animal Crossing - New Horizons Save Editor</Description>
|
||||
<StartupObject>NHSE.WinForms.Program</StartupObject>
|
||||
|
||||
@@ -726,11 +726,11 @@ private void Menu_SavePNG_Click(object sender, EventArgs e)
|
||||
}
|
||||
else if (!Menu_SavePNGItems.Checked)
|
||||
{
|
||||
PB_Map.BackgroundImage.Save(sfd.FileName, ImageFormat.Png);
|
||||
PB_Map.BackgroundImage!.Save(sfd.FileName, ImageFormat.Png);
|
||||
}
|
||||
else
|
||||
{
|
||||
var img = (Bitmap)PB_Map.BackgroundImage.Clone();
|
||||
var img = (Bitmap)PB_Map.BackgroundImage!.Clone();
|
||||
using var gfx = Graphics.FromImage(img);
|
||||
gfx.DrawImage(PB_Map.Image, new Point(0, 0));
|
||||
img.Save(sfd.FileName, ImageFormat.Png);
|
||||
|
||||
@@ -50,7 +50,7 @@ private void B_Add_Click(object sender, EventArgs e)
|
||||
{ WinFormsUtil.Alert("Invalid Property"); return; }
|
||||
|
||||
var prefix = StringInstruction.Prefixes;
|
||||
string s = prefix[CB_Require.SelectedIndex] + CB_Property.Items[CB_Property.SelectedIndex].ToString() + StringInstruction.SplitInstruction;
|
||||
string s = prefix[CB_Require.SelectedIndex] + CB_Property.Items[CB_Property.SelectedIndex]!.ToString() + StringInstruction.SplitInstruction;
|
||||
if (RTB_Instructions.Lines.Length != 0 && RTB_Instructions.Lines.Last().Length > 0)
|
||||
s = Environment.NewLine + s;
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ private static void TranslateForm(Control form, TranslationContext context)
|
||||
}
|
||||
else if (c is ToolStripItem t)
|
||||
{
|
||||
var current = t.Text;
|
||||
var current = t.Text!;
|
||||
var updated = context.GetTranslatedText($"{formname}.{t.Name}", current);
|
||||
if (!ReferenceEquals(current, updated))
|
||||
t.Text = updated;
|
||||
|
||||
@@ -47,15 +47,15 @@ internal static DialogResult Prompt(MessageBoxButtons btn, params string[] lines
|
||||
switch (sender)
|
||||
{
|
||||
case ToolStripItem t:
|
||||
sender = t.Owner;
|
||||
sender = t.Owner!;
|
||||
continue;
|
||||
case ContextMenuStrip c:
|
||||
sender = c.SourceControl;
|
||||
sender = c.SourceControl!;
|
||||
continue;
|
||||
case T p:
|
||||
return p;
|
||||
default:
|
||||
return default;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user