* Progress on classic color management
* Added cleanup routines for tilesets and object type previews.
This commit is contained in:
parent
02d1992055
commit
303762eb31
@ -618,6 +618,8 @@
|
|||||||
<Compile Include="Utility\SteamworksUGC.cs" />
|
<Compile Include="Utility\SteamworksUGC.cs" />
|
||||||
<Compile Include="Utility\TeamColor.cs" />
|
<Compile Include="Utility\TeamColor.cs" />
|
||||||
<Compile Include="Utility\TeamColorManager.cs" />
|
<Compile Include="Utility\TeamColorManager.cs" />
|
||||||
|
<Compile Include="Utility\TeamRemap.cs" />
|
||||||
|
<Compile Include="Utility\TeamRemapManager.cs" />
|
||||||
<Compile Include="Utility\TextureManager.cs" />
|
<Compile Include="Utility\TextureManager.cs" />
|
||||||
<Compile Include="Utility\TGASharpLib.cs" />
|
<Compile Include="Utility\TGASharpLib.cs" />
|
||||||
<Compile Include="Utility\Tileset.cs" />
|
<Compile Include="Utility\Tileset.cs" />
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
// distributed with this program. You should have received a copy of the
|
// distributed with this program. You should have received a copy of the
|
||||||
// GNU General Public License along with permitted additional restrictions
|
// GNU General Public License along with permitted additional restrictions
|
||||||
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
|
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
|
||||||
|
using MobiusEditor.Model;
|
||||||
|
using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
|
|
||||||
namespace MobiusEditor.Interface
|
namespace MobiusEditor.Interface
|
||||||
@ -20,5 +22,6 @@ namespace MobiusEditor.Interface
|
|||||||
{
|
{
|
||||||
string DisplayName { get; }
|
string DisplayName { get; }
|
||||||
Bitmap Thumbnail { get; }
|
Bitmap Thumbnail { get; }
|
||||||
|
void Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,8 +14,6 @@ namespace MobiusEditor.Interface
|
|||||||
{
|
{
|
||||||
/// <summary>Name of the color, used as identifier.</summary>
|
/// <summary>Name of the color, used as identifier.</summary>
|
||||||
string Name { get; }
|
string Name { get; }
|
||||||
/// <summary>A general color representing this team color.</summary>
|
|
||||||
Color BaseColor { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Apply this color to a given image.
|
/// Apply this color to a given image.
|
||||||
|
@ -15,7 +15,12 @@ namespace MobiusEditor.Interface
|
|||||||
Color RemapBaseColor { get; }
|
Color RemapBaseColor { get; }
|
||||||
ITeamColor this[string key] { get; }
|
ITeamColor this[string key] { get; }
|
||||||
|
|
||||||
|
/// <summary>Gets a general color representing this team color.</summary>
|
||||||
|
/// <param name="key">Color key</param>
|
||||||
|
/// <returns>The basic color for this team color.</returns>
|
||||||
|
Color GetBaseColor(string key);
|
||||||
|
|
||||||
void Load(string path);
|
void Load(string path);
|
||||||
void Reset(GameType gameType);
|
void Reset(GameType gameType, string theater);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1059,7 +1059,7 @@ namespace MobiusEditor
|
|||||||
{
|
{
|
||||||
var fileInfo = new FileInfo(fileName);
|
var fileInfo = new FileInfo(fileName);
|
||||||
String name = fileInfo.FullName;
|
String name = fileInfo.FullName;
|
||||||
if (!IdentifyMap(name, out FileType fileType, out GameType gameType, out bool isTdMegaMap))
|
if (!IdentifyMap(name, out FileType fileType, out GameType gameType, out bool isTdMegaMap, out string theater))
|
||||||
{
|
{
|
||||||
string extension = Path.GetExtension(name).TrimStart('.');
|
string extension = Path.GetExtension(name).TrimStart('.');
|
||||||
// No point in supporting jpeg here; the mapping needs distinct colours without fades.
|
// No point in supporting jpeg here; the mapping needs distinct colours without fades.
|
||||||
@ -1092,7 +1092,7 @@ namespace MobiusEditor
|
|||||||
ModPaths.TryGetValue(gameType, out modPaths);
|
ModPaths.TryGetValue(gameType, out modPaths);
|
||||||
}
|
}
|
||||||
loadMultiThreader.ExecuteThreaded(
|
loadMultiThreader.ExecuteThreaded(
|
||||||
() => LoadFile(name, fileType, gameType, isTdMegaMap, modPaths),
|
() => LoadFile(name, fileType, gameType, theater, isTdMegaMap, modPaths),
|
||||||
PostLoad, true,
|
PostLoad, true,
|
||||||
(e,l) => LoadUnloadUi(e, l, loadMultiThreader),
|
(e,l) => LoadUnloadUi(e, l, loadMultiThreader),
|
||||||
"Loading map");
|
"Loading map");
|
||||||
@ -1138,10 +1138,11 @@ namespace MobiusEditor
|
|||||||
"Saving map");
|
"Saving map");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Boolean IdentifyMap(String loadFilename, out FileType fileType, out GameType gameType, out bool isTdMegaMap)
|
private Boolean IdentifyMap(String loadFilename, out FileType fileType, out GameType gameType, out bool isTdMegaMap, out string theater)
|
||||||
{
|
{
|
||||||
fileType = FileType.None;
|
fileType = FileType.None;
|
||||||
gameType = GameType.None;
|
gameType = GameType.None;
|
||||||
|
theater = null;
|
||||||
isTdMegaMap = false;
|
isTdMegaMap = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -1212,6 +1213,7 @@ namespace MobiusEditor
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
theater = (iniContents["Map"].TryGetValue("Theater") ?? "temperate").ToLower();
|
||||||
switch (fileType)
|
switch (fileType)
|
||||||
{
|
{
|
||||||
case FileType.INI:
|
case FileType.INI:
|
||||||
@ -1308,20 +1310,20 @@ namespace MobiusEditor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IGamePlugin LoadNewPlugin(GameType gameType, bool isTdMegaMap, string[] modPaths)
|
private static IGamePlugin LoadNewPlugin(GameType gameType, string theater, bool isTdMegaMap, string[] modPaths)
|
||||||
{
|
{
|
||||||
return LoadNewPlugin(gameType, isTdMegaMap, modPaths, false);
|
return LoadNewPlugin(gameType, theater, isTdMegaMap, modPaths, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IGamePlugin LoadNewPlugin(GameType gameType, bool isTdMegaMap, string[] modPaths, bool noImage)
|
private static IGamePlugin LoadNewPlugin(GameType gameType, string theater, bool isTdMegaMap, string[] modPaths, bool noImage)
|
||||||
{
|
{
|
||||||
// Resetting to a specific game type will take care of classic mode.
|
// Resetting to a specific game type will take care of classic mode.
|
||||||
Globals.TheArchiveManager.ExpandModPaths = modPaths;
|
Globals.TheArchiveManager.ExpandModPaths = modPaths;
|
||||||
Globals.TheArchiveManager.Reset(gameType);
|
Globals.TheArchiveManager.Reset(gameType);
|
||||||
Globals.TheGameTextManager.Reset(gameType);
|
Globals.TheGameTextManager.Reset(gameType);
|
||||||
Globals.TheTextureManager.Reset();
|
Globals.TheTextureManager.Reset(gameType, theater);
|
||||||
Globals.TheTilesetManager.Reset();
|
Globals.TheTilesetManager.Reset();
|
||||||
Globals.TheTeamColorManager.Reset(gameType);
|
Globals.TheTeamColorManager.Reset(gameType, theater);
|
||||||
IGamePlugin plugin = null;
|
IGamePlugin plugin = null;
|
||||||
if (gameType == GameType.TiberianDawn)
|
if (gameType == GameType.TiberianDawn)
|
||||||
{
|
{
|
||||||
@ -1334,6 +1336,7 @@ namespace MobiusEditor
|
|||||||
else if (gameType == GameType.RedAlert)
|
else if (gameType == GameType.RedAlert)
|
||||||
{
|
{
|
||||||
Globals.TheTeamColorManager.Load(@"DATA\XML\CNCRATEAMCOLORS.XML");
|
Globals.TheTeamColorManager.Load(@"DATA\XML\CNCRATEAMCOLORS.XML");
|
||||||
|
Globals.TheTeamColorManager.Load("palette.cps");
|
||||||
plugin = new RedAlert.GamePluginRA(!noImage);
|
plugin = new RedAlert.GamePluginRA(!noImage);
|
||||||
}
|
}
|
||||||
else if (gameType == GameType.SoleSurvivor)
|
else if (gameType == GameType.SoleSurvivor)
|
||||||
@ -1358,35 +1361,26 @@ namespace MobiusEditor
|
|||||||
new Vector3(0, 1, 1), new Vector2(0, 1), Color.FromArgb(61, 61, 59));
|
new Vector3(0, 1, 1), new Vector2(0, 1), Color.FromArgb(61, 61, 59));
|
||||||
tcm.AddTeamColor(teamColorNone);
|
tcm.AddTeamColor(teamColorNone);
|
||||||
}
|
}
|
||||||
else // if (teamColorManager is TeamRemapManager tcc)
|
|
||||||
{
|
|
||||||
// TODO classic team color
|
|
||||||
//TeamRemap teamColorNone = new TeamRemap(tcc);
|
|
||||||
//teamColorNone.Load(/*TODO*/);
|
|
||||||
//tcc.AddTeamColor(teamColorNone);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AddTeamColorPurple(ITeamColorManager teamColorManager)
|
private static void AddTeamColorPurple(ITeamColorManager teamColorManager)
|
||||||
{
|
{
|
||||||
if (teamColorManager is TeamColorManager tcm)
|
if (teamColorManager is TeamColorManager tcm)
|
||||||
{
|
{
|
||||||
// Add extra purple for flag..
|
// Add extra colors for flags.
|
||||||
TeamColor teamColorPurple = new TeamColor(tcm);
|
TeamColor teamColorSeven = new TeamColor(tcm);
|
||||||
teamColorPurple.Load("PURPLE", "BASE_TEAM",
|
teamColorSeven.Load(tcm.GetItem("BAD_UNIT"), "MULTI7");
|
||||||
|
tcm.AddTeamColor(teamColorSeven);
|
||||||
|
|
||||||
|
TeamColor teamColorEight = new TeamColor(tcm);
|
||||||
|
teamColorEight.Load("MULTI8", "BASE_TEAM",
|
||||||
Color.FromArgb(66, 255, 0), Color.FromArgb(0, 255, 56), 0,
|
Color.FromArgb(66, 255, 0), Color.FromArgb(0, 255, 56), 0,
|
||||||
new Vector3(0.410f, 0.300f, 0.000f), new Vector3(0f, 1f, 1f), new Vector2(0.0f, 1.0f),
|
new Vector3(0.410f, 0.300f, 0.000f), new Vector3(0f, 1f, 1f), new Vector2(0.0f, 1.0f),
|
||||||
new Vector3(0, 1, 1), new Vector2(0, 1), Color.FromArgb(77, 13, 255));
|
new Vector3(0, 1, 1), new Vector2(0, 1), Color.FromArgb(77, 13, 255));
|
||||||
tcm.AddTeamColor(teamColorPurple);
|
tcm.AddTeamColor(teamColorEight);
|
||||||
}
|
|
||||||
else // if (teamColorManager is TeamRemapManager tcc)
|
|
||||||
{
|
|
||||||
// TODO classic team color
|
|
||||||
//TeamRemap teamColorPurple = new TeamRemap(tcc);
|
|
||||||
//teamColorPurple.Load(/*TODO*/);
|
|
||||||
//tcc.AddTeamColor(teamColorPurple);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The separate-threaded part for making a new map.
|
/// The separate-threaded part for making a new map.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -1424,7 +1418,7 @@ namespace MobiusEditor
|
|||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
IGamePlugin plugin = LoadNewPlugin(gameType, isTdMegaMap, modPaths);
|
IGamePlugin plugin = LoadNewPlugin(gameType, theater, isTdMegaMap, modPaths);
|
||||||
// This initialises the theater
|
// This initialises the theater
|
||||||
plugin.New(theater);
|
plugin.New(theater);
|
||||||
if (SteamworksUGC.IsInit)
|
if (SteamworksUGC.IsInit)
|
||||||
@ -1488,11 +1482,11 @@ namespace MobiusEditor
|
|||||||
/// <param name="isTdMegaMap"></param>
|
/// <param name="isTdMegaMap"></param>
|
||||||
/// <param name="modPaths"></param>
|
/// <param name="modPaths"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private static MapLoadInfo LoadFile(string loadFilename, FileType fileType, GameType gameType, bool isTdMegaMap, string[] modPaths)
|
private static MapLoadInfo LoadFile(string loadFilename, FileType fileType, GameType gameType, string theater, bool isTdMegaMap, string[] modPaths)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
IGamePlugin plugin = LoadNewPlugin(gameType, isTdMegaMap, modPaths);
|
IGamePlugin plugin = LoadNewPlugin(gameType, theater, isTdMegaMap, modPaths);
|
||||||
string[] errors = plugin.Load(loadFilename, fileType).ToArray();
|
string[] errors = plugin.Load(loadFilename, fileType).ToArray();
|
||||||
return new MapLoadInfo(loadFilename, fileType, plugin, errors);
|
return new MapLoadInfo(loadFilename, fileType, plugin, errors);
|
||||||
}
|
}
|
||||||
@ -1650,7 +1644,7 @@ namespace MobiusEditor
|
|||||||
}
|
}
|
||||||
// Unload graphics
|
// Unload graphics
|
||||||
Globals.TheTilesetManager.Reset();
|
Globals.TheTilesetManager.Reset();
|
||||||
Globals.TheTextureManager.Reset();
|
Globals.TheTextureManager.Reset(GameType.None, null);
|
||||||
// Clean up loaded file status
|
// Clean up loaded file status
|
||||||
filename = null;
|
filename = null;
|
||||||
loadedFileType = FileType.None;
|
loadedFileType = FileType.None;
|
||||||
|
@ -64,7 +64,7 @@ namespace MobiusEditor.Model
|
|||||||
|
|
||||||
public int Storage { get; set; }
|
public int Storage { get; set; }
|
||||||
|
|
||||||
public Rectangle OverlapBounds => new Rectangle(Point.Empty, new Size(OccupyMask.GetLength(1), OccupyMask.GetLength(0)));
|
public Rectangle OverlapBounds => new Rectangle(Point.Empty, new Size(this.OccupyMask.GetLength(1), this.OccupyMask.GetLength(0)));
|
||||||
public bool[,] OpaqueMask { get; private set; }
|
public bool[,] OpaqueMask { get; private set; }
|
||||||
|
|
||||||
public bool[,] OccupyMask { get; private set; }
|
public bool[,] OccupyMask { get; private set; }
|
||||||
@ -76,19 +76,19 @@ namespace MobiusEditor.Model
|
|||||||
|
|
||||||
public bool HasBib
|
public bool HasBib
|
||||||
{
|
{
|
||||||
get { return (Flag & BuildingTypeFlag.Bib) == BuildingTypeFlag.Bib; }
|
get { return (this.Flag & BuildingTypeFlag.Bib) == BuildingTypeFlag.Bib; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
// Bibs are only supported for widths 2 to 4
|
// Bibs are only supported for widths 2 to 4
|
||||||
if (value && Size.Width >= 2 && Size.Width <= 4)
|
if (value && this.Size.Width >= 2 && this.Size.Width <= 4)
|
||||||
{
|
{
|
||||||
Flag |= BuildingTypeFlag.Bib;
|
this.Flag |= BuildingTypeFlag.Bib;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Flag &= ~BuildingTypeFlag.Bib;
|
this.Flag &= ~BuildingTypeFlag.Bib;
|
||||||
}
|
}
|
||||||
RecalculateBibs();
|
this.RecalculateBibs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,14 +101,14 @@ namespace MobiusEditor.Model
|
|||||||
public bool IsAircraft => false;
|
public bool IsAircraft => false;
|
||||||
public bool IsFixedWing => false;
|
public bool IsFixedWing => false;
|
||||||
|
|
||||||
public bool IsFake => (Flag & BuildingTypeFlag.Fake) == BuildingTypeFlag.Fake;
|
public bool IsFake => (this.Flag & BuildingTypeFlag.Fake) == BuildingTypeFlag.Fake;
|
||||||
public bool HasTurret => (Flag & BuildingTypeFlag.Turret) == BuildingTypeFlag.Turret;
|
public bool HasTurret => (this.Flag & BuildingTypeFlag.Turret) == BuildingTypeFlag.Turret;
|
||||||
public bool IsSingleFrame => (Flag & BuildingTypeFlag.SingleFrame) == BuildingTypeFlag.SingleFrame;
|
public bool IsSingleFrame => (this.Flag & BuildingTypeFlag.SingleFrame) == BuildingTypeFlag.SingleFrame;
|
||||||
public bool CanRemap => (Flag & BuildingTypeFlag.NoRemap) != BuildingTypeFlag.NoRemap;
|
public bool CanRemap => (this.Flag & BuildingTypeFlag.NoRemap) != BuildingTypeFlag.NoRemap;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates buildings that have pieces sticking out at the top that should not overlap the objects on these cells.
|
/// Indicates buildings that have pieces sticking out at the top that should not overlap the objects on these cells.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsFlat => (Flag & BuildingTypeFlag.Flat) == BuildingTypeFlag.Flat;
|
public bool IsFlat => (this.Flag & BuildingTypeFlag.Flat) == BuildingTypeFlag.Flat;
|
||||||
|
|
||||||
public BuildingType(sbyte id, string name, string textId, int powerProd, int powerUse, int storage, int width, int height, string occupyMask, string ownerHouse, TheaterType[] theaters, string factoryOverlay, int frameOffset, String graphicsSource, BuildingTypeFlag flag)
|
public BuildingType(sbyte id, string name, string textId, int powerProd, int powerUse, int storage, int width, int height, string occupyMask, string ownerHouse, TheaterType[] theaters, string factoryOverlay, int frameOffset, String graphicsSource, BuildingTypeFlag flag)
|
||||||
{
|
{
|
||||||
@ -118,7 +118,7 @@ namespace MobiusEditor.Model
|
|||||||
this.Name = name;
|
this.Name = name;
|
||||||
this.GraphicsSource = graphicsSource ?? name;
|
this.GraphicsSource = graphicsSource ?? name;
|
||||||
this.DisplayName = !String.IsNullOrEmpty(textId) && !String.IsNullOrEmpty(Globals.TheGameTextManager[textId])
|
this.DisplayName = !String.IsNullOrEmpty(textId) && !String.IsNullOrEmpty(Globals.TheGameTextManager[textId])
|
||||||
? Globals.TheGameTextManager[textId] + " (" + Name.ToUpperInvariant() + ")"
|
? Globals.TheGameTextManager[textId] + " (" + this.Name.ToUpperInvariant() + ")"
|
||||||
: name.ToUpperInvariant();
|
: name.ToUpperInvariant();
|
||||||
this.PowerProduction = powerProd;
|
this.PowerProduction = powerProd;
|
||||||
this.PowerUsage = powerUse;
|
this.PowerUsage = powerUse;
|
||||||
@ -184,30 +184,30 @@ namespace MobiusEditor.Model
|
|||||||
|
|
||||||
private void RecalculateBibs()
|
private void RecalculateBibs()
|
||||||
{
|
{
|
||||||
int maskY = BaseOccupyMask.GetLength(0);
|
int maskY = this.BaseOccupyMask.GetLength(0);
|
||||||
int maskX = BaseOccupyMask.GetLength(1);
|
int maskX = this.BaseOccupyMask.GetLength(1);
|
||||||
if (HasBib)
|
if (this.HasBib)
|
||||||
{
|
{
|
||||||
OccupyMask = new bool[maskY + 1, maskX];
|
this.OccupyMask = new bool[maskY + 1, maskX];
|
||||||
for (var y = 0; y < maskY; ++y)
|
for (int y = 0; y < maskY; ++y)
|
||||||
{
|
{
|
||||||
for (var x = 0; x < maskX; ++x)
|
for (int x = 0; x < maskX; ++x)
|
||||||
{
|
{
|
||||||
OccupyMask[y, x] = BaseOccupyMask[y, x];
|
this.OccupyMask[y, x] = this.BaseOccupyMask[y, x];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Globals.BlockingBibs)
|
if (Globals.BlockingBibs)
|
||||||
{
|
{
|
||||||
for (var x = 0; x < maskX; ++x)
|
for (int x = 0; x < maskX; ++x)
|
||||||
{
|
{
|
||||||
OccupyMask[maskY, x] = true;
|
this.OccupyMask[maskY, x] = true;
|
||||||
OccupyMask[maskY - 1, x] = true;
|
this.OccupyMask[maskY - 1, x] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OccupyMask = BaseOccupyMask;
|
this.OccupyMask = this.BaseOccupyMask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,15 +218,15 @@ namespace MobiusEditor.Model
|
|||||||
int baseMaskX = this.BaseOccupyMask.GetLength(1);
|
int baseMaskX = this.BaseOccupyMask.GetLength(1);
|
||||||
string occupyMask = GeneralUtils.GetStringFromMask(this.BaseOccupyMask);
|
string occupyMask = GeneralUtils.GetStringFromMask(this.BaseOccupyMask);
|
||||||
TheaterType[] theaters = null;
|
TheaterType[] theaters = null;
|
||||||
if (Theaters != null)
|
if (this.Theaters != null)
|
||||||
{
|
{
|
||||||
int thLen = Theaters.Length;
|
int thLen = this.Theaters.Length;
|
||||||
theaters = new TheaterType[thLen];
|
theaters = new TheaterType[thLen];
|
||||||
Array.Copy(Theaters, theaters, thLen);
|
Array.Copy(this.Theaters, theaters, thLen);
|
||||||
}
|
}
|
||||||
// Don't do lookup of the UI name. We don't have the original lookup ID at this point, so don't bother, and just restore the name afterwards.
|
// Don't do lookup of the UI name. We don't have the original lookup ID at this point, so don't bother, and just restore the name afterwards.
|
||||||
BuildingType newBld = new BuildingType(ID, Name, null, PowerProduction, PowerUsage, Storage, baseMaskX, baseMaskY, occupyMask, OwnerHouse, theaters, FactoryOverlay, FrameOFfset, GraphicsSource, Flag);
|
BuildingType newBld = new BuildingType(this.ID, this.Name, null, this.PowerProduction, this.PowerUsage, this.Storage, baseMaskX, baseMaskY, occupyMask, this.OwnerHouse, theaters, this.FactoryOverlay, this.FrameOFfset, this.GraphicsSource, this.Flag);
|
||||||
newBld.DisplayName = DisplayName;
|
newBld.DisplayName = this.DisplayName;
|
||||||
return newBld;
|
return newBld;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,11 +238,11 @@ namespace MobiusEditor.Model
|
|||||||
}
|
}
|
||||||
else if (obj is sbyte)
|
else if (obj is sbyte)
|
||||||
{
|
{
|
||||||
return ID == (sbyte)obj;
|
return this.ID == (sbyte)obj;
|
||||||
}
|
}
|
||||||
else if (obj is string)
|
else if (obj is string)
|
||||||
{
|
{
|
||||||
return string.Equals(Name, obj as string, StringComparison.OrdinalIgnoreCase);
|
return string.Equals(this.Name, obj as string, StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.Equals(obj);
|
return base.Equals(obj);
|
||||||
@ -250,44 +250,44 @@ namespace MobiusEditor.Model
|
|||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
return ID.GetHashCode();
|
return this.ID.GetHashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return (Name ?? String.Empty).ToUpperInvariant();
|
return (this.Name ?? String.Empty).ToUpperInvariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init(GameType gameType, TheaterType theater, HouseType house, DirectionType direction)
|
public void Init(GameType gameType, TheaterType theater, HouseType house, DirectionType direction)
|
||||||
{
|
{
|
||||||
var oldImage = Thumbnail;
|
Bitmap oldImage = this.Thumbnail;
|
||||||
var mockBuilding = new Building()
|
Building mockBuilding = new Building()
|
||||||
{
|
{
|
||||||
Type = this,
|
Type = this,
|
||||||
House = house,
|
House = house,
|
||||||
Strength = 256,
|
Strength = 256,
|
||||||
Direction = direction
|
Direction = direction
|
||||||
};
|
};
|
||||||
var render = MapRenderer.RenderBuilding(gameType, theater, Point.Empty, Globals.PreviewTileSize, Globals.PreviewTileScale, mockBuilding);
|
(Rectangle, Action<Graphics>, bool) render = MapRenderer.RenderBuilding(gameType, theater, Point.Empty, Globals.PreviewTileSize, Globals.PreviewTileScale, mockBuilding);
|
||||||
if (!render.Item1.IsEmpty)
|
if (!render.Item1.IsEmpty)
|
||||||
{
|
{
|
||||||
var th = new Bitmap(render.Item1.Width, render.Item1.Height);
|
Bitmap th = new Bitmap(render.Item1.Width, render.Item1.Height);
|
||||||
th.SetResolution(96, 96);
|
th.SetResolution(96, 96);
|
||||||
using (var g = Graphics.FromImage(th))
|
using (Graphics g = Graphics.FromImage(th))
|
||||||
{
|
{
|
||||||
MapRenderer.SetRenderSettings(g, Globals.PreviewSmoothScale);
|
MapRenderer.SetRenderSettings(g, Globals.PreviewSmoothScale);
|
||||||
render.Item2(g);
|
render.Item2(g);
|
||||||
if (IsFake)
|
if (this.IsFake)
|
||||||
{
|
{
|
||||||
MapRenderer.RenderFakeBuildingLabel(g, mockBuilding, Point.Empty, Globals.PreviewTileSize, Globals.PreviewTileScale, false);
|
MapRenderer.RenderFakeBuildingLabel(g, mockBuilding, Point.Empty, Globals.PreviewTileSize, Globals.PreviewTileScale, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Thumbnail = th;
|
this.Thumbnail = th;
|
||||||
OpaqueMask = GeneralUtils.FindOpaqueCells(th, Size, 10, 25, 0x80);
|
this.OpaqueMask = GeneralUtils.FindOpaqueCells(th, this.Size, 10, 25, 0x80);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Thumbnail = null;
|
this.Thumbnail = null;
|
||||||
}
|
}
|
||||||
if (oldImage != null)
|
if (oldImage != null)
|
||||||
{
|
{
|
||||||
@ -295,5 +295,16 @@ namespace MobiusEditor.Model
|
|||||||
catch { /* ignore */ }
|
catch { /* ignore */ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
Bitmap oldImage = this.Thumbnail;
|
||||||
|
this.Thumbnail = null;
|
||||||
|
if (oldImage != null)
|
||||||
|
{
|
||||||
|
try { oldImage.Dispose(); }
|
||||||
|
catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,5 +122,15 @@ namespace MobiusEditor.Model
|
|||||||
catch { /* ignore */ }
|
catch { /* ignore */ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
Bitmap oldImage = this.Thumbnail;
|
||||||
|
this.Thumbnail = null;
|
||||||
|
if (oldImage != null)
|
||||||
|
{
|
||||||
|
try { oldImage.Dispose(); }
|
||||||
|
catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1987,5 +1987,46 @@ namespace MobiusEditor.Model
|
|||||||
}
|
}
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ResetCachedGraphics()
|
||||||
|
{
|
||||||
|
// Dispose of cached images. This is non-destructive; the type objects themselves
|
||||||
|
// don't actually get disposed. Their thumbnail simply gets disposed and cleared.
|
||||||
|
foreach (ITechnoType technoType in this.AllTeamTechnoTypes)
|
||||||
|
{
|
||||||
|
// units, boats, aircraft, infantry
|
||||||
|
technoType.Reset();
|
||||||
|
}
|
||||||
|
// probably not needed since it's in the team techno types.
|
||||||
|
foreach (UnitType unitType in this.AllUnitTypes)
|
||||||
|
{
|
||||||
|
unitType.Reset();
|
||||||
|
}
|
||||||
|
// probably not needed since it's in the team techno types.
|
||||||
|
foreach (InfantryType infantryType in this.AllInfantryTypes)
|
||||||
|
{
|
||||||
|
infantryType.Reset();
|
||||||
|
}
|
||||||
|
foreach (BuildingType buildingType in this.BuildingTypes)
|
||||||
|
{
|
||||||
|
buildingType.Reset();
|
||||||
|
}
|
||||||
|
foreach (TemplateType template in this.TemplateTypes)
|
||||||
|
{
|
||||||
|
template.Reset();
|
||||||
|
}
|
||||||
|
foreach (TerrainType terrainType in this.TerrainTypes)
|
||||||
|
{
|
||||||
|
terrainType.Reset();
|
||||||
|
}
|
||||||
|
foreach (OverlayType overlayType in this.OverlayTypes)
|
||||||
|
{
|
||||||
|
overlayType.Reset();
|
||||||
|
}
|
||||||
|
foreach (SmudgeType smudgeType in this.SmudgeTypes)
|
||||||
|
{
|
||||||
|
smudgeType.Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,5 +191,15 @@ namespace MobiusEditor.Model
|
|||||||
catch { /* ignore */ }
|
catch { /* ignore */ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
Bitmap oldImage = this.Thumbnail;
|
||||||
|
this.Thumbnail = null;
|
||||||
|
if (oldImage != null)
|
||||||
|
{
|
||||||
|
try { oldImage.Dispose(); }
|
||||||
|
catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -196,5 +196,15 @@ namespace MobiusEditor.Model
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
Bitmap oldImage = this.Thumbnail;
|
||||||
|
this.Thumbnail = null;
|
||||||
|
if (oldImage != null)
|
||||||
|
{
|
||||||
|
try { oldImage.Dispose(); }
|
||||||
|
catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -484,5 +484,15 @@ namespace MobiusEditor.Model
|
|||||||
// Should never happen.
|
// Should never happen.
|
||||||
return new Point(0, 0);
|
return new Point(0, 0);
|
||||||
}
|
}
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
Bitmap oldImage = this.Thumbnail;
|
||||||
|
this.Thumbnail = null;
|
||||||
|
if (oldImage != null)
|
||||||
|
{
|
||||||
|
try { oldImage.Dispose(); }
|
||||||
|
catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,5 +219,15 @@ namespace MobiusEditor.Model
|
|||||||
catch { /* ignore */ }
|
catch { /* ignore */ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
Bitmap oldImage = this.Thumbnail;
|
||||||
|
this.Thumbnail = null;
|
||||||
|
if (oldImage != null)
|
||||||
|
{
|
||||||
|
try { oldImage.Dispose(); }
|
||||||
|
catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,5 +184,15 @@ namespace MobiusEditor.Model
|
|||||||
catch { /* ignore */ }
|
catch { /* ignore */ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
Bitmap oldImage = this.Thumbnail;
|
||||||
|
this.Thumbnail = null;
|
||||||
|
if (oldImage != null)
|
||||||
|
{
|
||||||
|
try { oldImage.Dispose(); }
|
||||||
|
catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3803,7 +3803,10 @@ namespace MobiusEditor.RedAlert
|
|||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
MapImage?.Dispose();
|
try { MapImage?.Dispose(); }
|
||||||
|
catch { /* ignore */ }
|
||||||
|
// Dispose of cached images in type objects. This is non-destructive; the type objects themselves don't actually get disposed.
|
||||||
|
Map.ResetCachedGraphics();
|
||||||
}
|
}
|
||||||
disposedValue = true;
|
disposedValue = true;
|
||||||
}
|
}
|
||||||
|
@ -1573,7 +1573,7 @@ namespace MobiusEditor.Render
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ITeamColor tc = Globals.TheTeamColorManager[building.House.BuildingTeamColor];
|
ITeamColor tc = Globals.TheTeamColorManager[building.House.BuildingTeamColor];
|
||||||
Color circleColor = tc?.BaseColor ?? Globals.TheTeamColorManager.RemapBaseColor;
|
Color circleColor = Globals.TheTeamColorManager.GetBaseColor(tc.Name);
|
||||||
bool[,] cells = building.Type.BaseOccupyMask;
|
bool[,] cells = building.Type.BaseOccupyMask;
|
||||||
int maskY = cells.GetLength(0);
|
int maskY = cells.GetLength(0);
|
||||||
int maskX = cells.GetLength(1);
|
int maskX = cells.GetLength(1);
|
||||||
@ -1601,7 +1601,7 @@ namespace MobiusEditor.Render
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ITeamColor tc = Globals.TheTeamColorManager[unit.House.BuildingTeamColor];
|
ITeamColor tc = Globals.TheTeamColorManager[unit.House.BuildingTeamColor];
|
||||||
Color circleColor = tc?.BaseColor ?? Globals.TheTeamColorManager.RemapBaseColor;
|
Color circleColor = Globals.TheTeamColorManager.GetBaseColor(tc.Name);
|
||||||
Color alphacorr = Color.FromArgb(unit.Tint.A * 128 / 256, circleColor);
|
Color alphacorr = Color.FromArgb(unit.Tint.A * 128 / 256, circleColor);
|
||||||
if (isJammer)
|
if (isJammer)
|
||||||
{
|
{
|
||||||
|
@ -394,9 +394,9 @@ namespace MobiusEditor.TiberianDawn
|
|||||||
flagColors[mpId] = Globals.TheTeamColorManager[house.UnitTeamColor];
|
flagColors[mpId] = Globals.TheTeamColorManager[house.UnitTeamColor];
|
||||||
}
|
}
|
||||||
// Metallic light blue
|
// Metallic light blue
|
||||||
flagColors[6] = Globals.TheTeamColorManager["BAD_UNIT"];
|
flagColors[6] = Globals.TheTeamColorManager["MULTI7"];
|
||||||
// RA Purple
|
// RA Purple
|
||||||
flagColors[7] = Globals.TheTeamColorManager["PURPLE"];
|
flagColors[7] = Globals.TheTeamColorManager["MULTI8"];
|
||||||
Size mapSize = !megaMap ? Constants.MaxSize : Constants.MaxSizeMega;
|
Size mapSize = !megaMap ? Constants.MaxSize : Constants.MaxSizeMega;
|
||||||
Map = new Map(basicSection, null, mapSize, typeof(House), houseTypes,
|
Map = new Map(basicSection, null, mapSize, typeof(House), houseTypes,
|
||||||
flagColors, TheaterTypes.GetTypes(), TemplateTypes.GetTypes(),
|
flagColors, TheaterTypes.GetTypes(), TemplateTypes.GetTypes(),
|
||||||
@ -3284,7 +3284,10 @@ namespace MobiusEditor.TiberianDawn
|
|||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
MapImage?.Dispose();
|
try { MapImage?.Dispose(); }
|
||||||
|
catch { /* ignore */ }
|
||||||
|
// Dispose of cached images in type objects. This is non-destructive; the type objects themselves don't actually get disposed.
|
||||||
|
Map.ResetCachedGraphics();
|
||||||
}
|
}
|
||||||
disposedValue = true;
|
disposedValue = true;
|
||||||
}
|
}
|
||||||
|
@ -85,14 +85,13 @@ namespace MobiusEditor.Utility
|
|||||||
public TeamColor(TeamColorManager teamColorManager, TeamColor col, string newName, Vector3 hsvShiftOverride)
|
public TeamColor(TeamColorManager teamColorManager, TeamColor col, string newName, Vector3 hsvShiftOverride)
|
||||||
{
|
{
|
||||||
this.teamColorManager = teamColorManager;
|
this.teamColorManager = teamColorManager;
|
||||||
this.Load(col);
|
this.Load(col, newName);
|
||||||
this.Name = newName;
|
|
||||||
this.hsvShift = hsvShiftOverride;
|
this.hsvShift = hsvShiftOverride;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Load(TeamColor col)
|
public void Load(TeamColor col, string newName)
|
||||||
{
|
{
|
||||||
this.Name = col.Name;
|
this.Name = newName ?? col.Name;
|
||||||
this.Variant = col.Variant;
|
this.Variant = col.Variant;
|
||||||
this.lowerBounds = col.LowerBounds;
|
this.lowerBounds = col.LowerBounds;
|
||||||
this.upperBounds = col.UpperBounds;
|
this.upperBounds = col.UpperBounds;
|
||||||
|
@ -28,8 +28,16 @@ namespace MobiusEditor.Utility
|
|||||||
private readonly IArchiveManager megafileManager;
|
private readonly IArchiveManager megafileManager;
|
||||||
public Color RemapBaseColor => Color.FromArgb(0x00, 0xFF, 0x00);
|
public Color RemapBaseColor => Color.FromArgb(0x00, 0xFF, 0x00);
|
||||||
|
|
||||||
public ITeamColor this[string key] => !string.IsNullOrEmpty(key) ? (ITeamColor)teamColors[key]: null;
|
public ITeamColor this[string key] => !string.IsNullOrEmpty(key) && teamColors.ContainsKey(key) ? (ITeamColor)teamColors[key]: null;
|
||||||
|
|
||||||
|
public Color GetBaseColor(string key)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(key) && teamColors.ContainsKey(key))
|
||||||
|
{
|
||||||
|
return teamColors[key].BaseColor;
|
||||||
|
}
|
||||||
|
return RemapBaseColor;
|
||||||
|
}
|
||||||
public TeamColor GetItem(string key) => !string.IsNullOrEmpty(key) ? teamColors[key] : null;
|
public TeamColor GetItem(string key) => !string.IsNullOrEmpty(key) ? teamColors[key] : null;
|
||||||
|
|
||||||
public void RemoveTeamColor(string col)
|
public void RemoveTeamColor(string col)
|
||||||
@ -56,12 +64,12 @@ namespace MobiusEditor.Utility
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TeamColorManager(IArchiveManager megafileManager, params string[] expandModPaths)
|
public TeamColorManager(IArchiveManager megafileManager)
|
||||||
{
|
{
|
||||||
this.megafileManager = megafileManager;
|
this.megafileManager = megafileManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Reset(GameType gameType)
|
public void Reset(GameType gameType, string theater)
|
||||||
{
|
{
|
||||||
teamColors.Clear();
|
teamColors.Clear();
|
||||||
}
|
}
|
||||||
|
56
CnCTDRAMapEditor/Utility/TeamRemap.cs
Normal file
56
CnCTDRAMapEditor/Utility/TeamRemap.cs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
using MobiusEditor.Interface;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MobiusEditor.Utility
|
||||||
|
{
|
||||||
|
class TeamRemap : ITeamColor
|
||||||
|
{
|
||||||
|
public string Name { get; private set; }
|
||||||
|
public byte UnitRadarColor { get; private set; }
|
||||||
|
public byte BuildingRadarColor { get; private set; }
|
||||||
|
|
||||||
|
private byte[] remapTable;
|
||||||
|
|
||||||
|
public TeamRemap(string name, byte unitRadarColor, byte buildingRadarColor, byte remapstart, byte[] remapValues)
|
||||||
|
{
|
||||||
|
this.Name = name;
|
||||||
|
this.UnitRadarColor = unitRadarColor;
|
||||||
|
this.BuildingRadarColor = buildingRadarColor;
|
||||||
|
this.remapTable = Enumerable.Range(0, 0x100).Cast<byte>().ToArray();
|
||||||
|
int max = Math.Max(0x100, remapstart + remapValues.Length);
|
||||||
|
for (int i = 0; i < max; ++i)
|
||||||
|
{
|
||||||
|
remapTable[remapstart + i] = remapValues[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TeamRemap(string name, byte unitRadarColor, byte buildingRadarColor, byte[] remapOrigins, byte[] remapValues)
|
||||||
|
{
|
||||||
|
this.Name = name;
|
||||||
|
this.UnitRadarColor = unitRadarColor;
|
||||||
|
this.BuildingRadarColor = buildingRadarColor;
|
||||||
|
this.remapTable = Enumerable.Range(0, 0x100).Cast<byte>().ToArray();
|
||||||
|
int max = Math.Max(remapOrigins.Length, remapValues.Length);
|
||||||
|
for (int i = 0; i < max; ++i)
|
||||||
|
{
|
||||||
|
remapTable[remapOrigins[i]] = remapValues[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void ApplyToImage(Bitmap image)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ApplyToImage(Bitmap image, out Rectangle opaqueBounds)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
137
CnCTDRAMapEditor/Utility/TeamRemapManager.cs
Normal file
137
CnCTDRAMapEditor/Utility/TeamRemapManager.cs
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
using MobiusEditor.Interface;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MobiusEditor.Utility
|
||||||
|
{
|
||||||
|
class TeamRemapManager : ITeamColorManager
|
||||||
|
{
|
||||||
|
// TD remap
|
||||||
|
public static readonly TeamRemap RemapTdGoodGuy = new TeamRemap("GOOD", 176, 180, 176, new byte[] { 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191 });
|
||||||
|
public static readonly TeamRemap RemapTdBadGuyRed = new TeamRemap("BAD_STRUCTURE", 127, 123, 176, new byte[] { 127, 126, 125, 124, 122, 46, 120, 47, 125, 124, 123, 122, 42, 121, 120, 120 });
|
||||||
|
public static readonly TeamRemap RemapTdBadGuyGray = new TeamRemap("BAD_UNIT", 127, 123, 176, new byte[] { 161, 200, 201, 202, 204, 205, 206, 12, 201, 202, 203, 204, 205, 115, 198, 114 });
|
||||||
|
// The color name identifiers in the remaster are all out of wack.
|
||||||
|
public static readonly TeamRemap RemapTdBlue = new TeamRemap("MULTI2", 2, 135, 176, new byte[] {2, 119, 118, 135, 136, 138, 112, 12, 118, 135, 136, 137, 138, 139, 114, 112});
|
||||||
|
public static readonly TeamRemap RemapTdOrange = new TeamRemap("MULTI5", 24, 26, 176, new byte[] { 24, 25, 26, 27, 29, 31, 46, 47, 26, 27, 28, 29, 30, 31, 43, 47 });
|
||||||
|
public static readonly TeamRemap RemapTdGreen = new TeamRemap("MULTI4", 167, 159, 176, new byte[] { 5, 165, 166, 167, 159, 142, 140, 199, 166, 167, 157, 3, 159, 143, 142, 141 });
|
||||||
|
public static readonly TeamRemap RemapTdLtBlue = new TeamRemap("MULTI6", 201, 203, 176, new byte[] { 161, 200, 201, 202, 204, 205, 206, 12, 201, 202, 203, 204, 205, 115, 198, 114 });
|
||||||
|
public static readonly TeamRemap RemapTdYellow = new TeamRemap("MULTI1", 5, 157, 176, new byte[] { 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191 });
|
||||||
|
public static readonly TeamRemap RemapTdRed = new TeamRemap("MULTI3", 127, 123, 176, new byte[] { 127, 126, 125, 124, 122, 46, 120, 47, 125, 124, 123, 122, 42, 121, 120, 120 });
|
||||||
|
// Added extra colours for flags
|
||||||
|
public static readonly TeamRemap RemapTdMul7 = new TeamRemap("MULTI7", 146, 209, 176, new byte[] { 146, 152, 209, 151, 173, 150, 173, 183, 146, 152, 209, 151, 173, 150, 173, 183 }); // Brown
|
||||||
|
public static readonly TeamRemap RemapTdMul8 = new TeamRemap("MULTI8", 214, 213, 176, new byte[] { 132, 133, 134, 213, 214, 121, 120, 12, 133, 134, 213, 214, 121, 174, 120, 199 }); // Burgundy
|
||||||
|
public static readonly TeamRemap RemapTdNone = new TeamRemap("NONE", 199, 199, 176, new byte[] { 14, 195, 196, 13, 169, 198, 199, 112, 14, 195, 196, 13, 169, 198, 199, 112 }); // Black
|
||||||
|
|
||||||
|
|
||||||
|
private static readonly Dictionary<string, TeamRemap> RemapsTd;
|
||||||
|
|
||||||
|
public const Byte MaxValueSixBit = 63;
|
||||||
|
private static readonly Byte[] ConvertToEightBit = new Byte[64];
|
||||||
|
|
||||||
|
static TeamRemapManager()
|
||||||
|
{
|
||||||
|
RemapsTd = (from field in typeof(ITeamColorManager).GetFields(BindingFlags.Static | BindingFlags.Public)
|
||||||
|
where field.IsInitOnly && typeof(TeamRemap).IsAssignableFrom(field.FieldType) && field.Name.StartsWith("RemapTd")
|
||||||
|
select field.GetValue(null) as TeamRemap).ToDictionary(trm => trm.Name);
|
||||||
|
|
||||||
|
// Build easy lookup tables for this, so no calculations are ever needed for this later.
|
||||||
|
for (Int32 i = 0; i < 64; ++i)
|
||||||
|
ConvertToEightBit[i] = (Byte)Math.Round(i * 255.0 / 63.0, MidpointRounding.ToEven);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dictionary<string, TeamRemap> remapsRa = new Dictionary<string, TeamRemap>();
|
||||||
|
private GameType currentlyLoadedGameType;
|
||||||
|
private Color[] currentlyLoadedPalette;
|
||||||
|
private readonly IArchiveManager mixfileManager;
|
||||||
|
|
||||||
|
|
||||||
|
public ITeamColor this[string key] => GetforCurrentGame(key);
|
||||||
|
public Color GetBaseColor(string key)
|
||||||
|
{
|
||||||
|
TeamRemap tc = GetforCurrentGame(key);
|
||||||
|
if (tc != null)
|
||||||
|
{
|
||||||
|
return currentlyLoadedPalette[tc.UnitRadarColor];
|
||||||
|
}
|
||||||
|
return RemapBaseColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TeamRemap GetforCurrentGame(string key)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(key))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Dictionary<string, TeamRemap> currentRemaps;
|
||||||
|
switch (currentlyLoadedGameType)
|
||||||
|
{
|
||||||
|
case GameType.TiberianDawn:
|
||||||
|
case GameType.SoleSurvivor:
|
||||||
|
currentRemaps = RemapsTd;
|
||||||
|
break;
|
||||||
|
case GameType.RedAlert:
|
||||||
|
currentRemaps = this.remapsRa;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return currentRemaps.ContainsKey(key) ? currentRemaps[key] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color remapBaseColor = Color.Black;
|
||||||
|
public Color RemapBaseColor => remapBaseColor;
|
||||||
|
|
||||||
|
public void Load(string path)
|
||||||
|
{
|
||||||
|
// Check if CPS, if so, fill in "this.remapsRa"
|
||||||
|
}
|
||||||
|
|
||||||
|
public TeamRemapManager(IArchiveManager fileManager)
|
||||||
|
{
|
||||||
|
this.mixfileManager = fileManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset(GameType gameType, string theater)
|
||||||
|
{
|
||||||
|
currentlyLoadedGameType = gameType;
|
||||||
|
currentlyLoadedPalette = new Color[0x100];
|
||||||
|
// file manager should already be reset to read from the correct game at this point.
|
||||||
|
using (Stream palette = mixfileManager.OpenFile(theater + ".pal"))
|
||||||
|
{
|
||||||
|
if (palette != null)
|
||||||
|
{
|
||||||
|
byte[] pal;
|
||||||
|
using (BinaryReader sr = new BinaryReader(palette))
|
||||||
|
{
|
||||||
|
pal = GeneralUtils.ReadAllBytes(sr);
|
||||||
|
}
|
||||||
|
int len = Math.Min(pal.Length / 3, 0x100);
|
||||||
|
int offs = 0;
|
||||||
|
for (int i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
byte r = ConvertToEightBit[pal[offs + 0] & 0x3F];
|
||||||
|
byte g = ConvertToEightBit[pal[offs + 1] & 0x3F];
|
||||||
|
byte b = ConvertToEightBit[pal[offs + 2] & 0x3F];
|
||||||
|
currentlyLoadedPalette[i] = Color.FromArgb(r, g, b);
|
||||||
|
offs += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (gameType == GameType.TiberianDawn || gameType == GameType.SoleSurvivor)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTheater()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -33,25 +33,16 @@ namespace MobiusEditor.Utility
|
|||||||
private static string MissingTexture = "DATA\\ART\\TEXTURES\\SRGB\\COMMON\\MISC\\MISSING.TGA";
|
private static string MissingTexture = "DATA\\ART\\TEXTURES\\SRGB\\COMMON\\MISC\\MISSING.TGA";
|
||||||
private bool processedMissingTexture = false;
|
private bool processedMissingTexture = false;
|
||||||
|
|
||||||
#if false
|
|
||||||
private class ImageData
|
|
||||||
{
|
|
||||||
public TGA TGA;
|
|
||||||
public JObject Metadata;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private readonly IArchiveManager megafileManager;
|
private readonly IArchiveManager megafileManager;
|
||||||
|
|
||||||
private Dictionary<string, Bitmap> cachedTextures = new Dictionary<string, Bitmap>();
|
private Dictionary<string, Bitmap> cachedTextures = new Dictionary<string, Bitmap>();
|
||||||
private Dictionary<(string, ITeamColor), (Bitmap, Rectangle)> teamColorTextures = new Dictionary<(string, ITeamColor), (Bitmap, Rectangle)>();
|
|
||||||
|
|
||||||
public TextureManager(IArchiveManager megafileManager)
|
public TextureManager(IArchiveManager megafileManager)
|
||||||
{
|
{
|
||||||
this.megafileManager = megafileManager;
|
this.megafileManager = megafileManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Reset()
|
public void Reset(GameType gameType, string theater)
|
||||||
{
|
{
|
||||||
Bitmap[] cachedImages = cachedTextures.Values.ToArray();
|
Bitmap[] cachedImages = cachedTextures.Values.ToArray();
|
||||||
cachedTextures.Clear();
|
cachedTextures.Clear();
|
||||||
@ -67,20 +58,6 @@ namespace MobiusEditor.Utility
|
|||||||
// Ignore.
|
// Ignore.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Bitmap, Rectangle)[] cachedTeamImages = teamColorTextures.Values.ToArray();
|
|
||||||
teamColorTextures.Clear();
|
|
||||||
for (int i = 0; i < cachedTeamImages.Length; ++i)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
(Bitmap bitmap, Rectangle opaqueBounds) = cachedTeamImages[i];
|
|
||||||
bitmap.Dispose();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// Ignore.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public (Bitmap, Rectangle) GetTexture(string filename, ITeamColor teamColor, bool generateFallback)
|
public (Bitmap, Rectangle) GetTexture(string filename, ITeamColor teamColor, bool generateFallback)
|
||||||
@ -101,13 +78,9 @@ namespace MobiusEditor.Utility
|
|||||||
return (retCopy, bounds);
|
return (retCopy, bounds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (teamColorTextures.TryGetValue((filename, teamColor), out (Bitmap bitmap, Rectangle opaqueBounds) result))
|
Bitmap resBitmap;
|
||||||
{
|
Rectangle resBounds = Rectangle.Empty;
|
||||||
Bitmap retCopy = new Bitmap(result.bitmap);
|
if (!cachedTextures.TryGetValue(filename, out _))
|
||||||
retCopy.SetResolution(96, 96);
|
|
||||||
return (retCopy, result.opaqueBounds);
|
|
||||||
}
|
|
||||||
if (!cachedTextures.TryGetValue(filename, out result.bitmap))
|
|
||||||
{
|
{
|
||||||
if (Path.GetExtension(filename).ToLower() == ".tga")
|
if (Path.GetExtension(filename).ToLower() == ".tga")
|
||||||
{
|
{
|
||||||
@ -181,71 +154,8 @@ namespace MobiusEditor.Utility
|
|||||||
cachedTextures[filename] = bitmap;
|
cachedTextures[filename] = bitmap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if false
|
|
||||||
// Attempt to load parent directory as archive
|
|
||||||
var archiveDir = Path.GetDirectoryName(filename);
|
|
||||||
var archivePath = archiveDir + ".ZIP";
|
|
||||||
using (var fileStream = megafileManager.Open(archivePath))
|
|
||||||
{
|
|
||||||
if (fileStream != null)
|
|
||||||
{
|
|
||||||
using (var archive = new ZipArchive(fileStream, ZipArchiveMode.Read))
|
|
||||||
{
|
|
||||||
var images = new Dictionary<string, ImageData>();
|
|
||||||
foreach (var entry in archive.Entries)
|
|
||||||
{
|
|
||||||
var name = Path.GetFileNameWithoutExtension(entry.Name);
|
|
||||||
if (!images.TryGetValue(name, out ImageData imageData))
|
|
||||||
{
|
|
||||||
imageData = images[name] = new ImageData { TGA = null, Metadata = null };
|
|
||||||
}
|
|
||||||
if ((imageData.TGA == null) && (Path.GetExtension(entry.Name).ToLower() == ".tga"))
|
|
||||||
{
|
|
||||||
using (var stream = entry.Open())
|
|
||||||
using (var memStream = new MemoryStream())
|
|
||||||
{
|
|
||||||
stream.CopyTo(memStream);
|
|
||||||
imageData.TGA = new TGA(memStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((imageData.Metadata == null) && (Path.GetExtension(entry.Name).ToLower() == ".meta"))
|
|
||||||
{
|
|
||||||
using (var stream = entry.Open())
|
|
||||||
using (var reader = new StreamReader(stream))
|
|
||||||
{
|
|
||||||
imageData.Metadata = JObject.Parse(reader.ReadToEnd());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((imageData.TGA != null) && (imageData.Metadata != null))
|
|
||||||
{
|
|
||||||
var bitmap = imageData.TGA.ToBitmap(true);
|
|
||||||
var size = new Size(imageData.Metadata["size"][0].ToObject<int>(), imageData.Metadata["size"][1].ToObject<int>());
|
|
||||||
var crop = Rectangle.FromLTRB(
|
|
||||||
imageData.Metadata["crop"][0].ToObject<int>(),
|
|
||||||
imageData.Metadata["crop"][1].ToObject<int>(),
|
|
||||||
imageData.Metadata["crop"][2].ToObject<int>(),
|
|
||||||
imageData.Metadata["crop"][3].ToObject<int>()
|
|
||||||
);
|
|
||||||
var uncroppedBitmap = new Bitmap(size.Width, size.Height, bitmap.PixelFormat);
|
|
||||||
uncroppedBitmap.SetResolution(96, 96);
|
|
||||||
using (var g = Graphics.FromImage(uncroppedBitmap))
|
|
||||||
{
|
|
||||||
g.DrawImage(bitmap, crop, new Rectangle(Point.Empty, bitmap.Size), GraphicsUnit.Pixel);
|
|
||||||
}
|
|
||||||
cachedTextures[Path.Combine(archiveDir, name) + ".tga"] = uncroppedBitmap;
|
|
||||||
images.Remove(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach (var item in images.Where(x => x.Value.TGA != null))
|
|
||||||
{
|
|
||||||
cachedTextures[Path.Combine(archiveDir, item.Key) + ".tga"] = item.Value.TGA.ToBitmap(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
if (!cachedTextures.TryGetValue(filename, out result.bitmap))
|
if (!cachedTextures.TryGetValue(filename, out resBitmap))
|
||||||
{
|
{
|
||||||
// Try loading as a DDS
|
// Try loading as a DDS
|
||||||
var ddsFilename = Path.ChangeExtension(filename, ".DDS");
|
var ddsFilename = Path.ChangeExtension(filename, ".DDS");
|
||||||
@ -260,26 +170,25 @@ namespace MobiusEditor.Utility
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!cachedTextures.TryGetValue(filename, out result.bitmap))
|
if (!cachedTextures.TryGetValue(filename, out resBitmap))
|
||||||
{
|
{
|
||||||
return result;
|
return (resBitmap, resBounds);
|
||||||
}
|
}
|
||||||
Bitmap resBm = new Bitmap(result.bitmap);
|
// Clone returned image.
|
||||||
|
Bitmap resBm = new Bitmap(resBitmap);
|
||||||
resBm.SetResolution(96, 96);
|
resBm.SetResolution(96, 96);
|
||||||
result.bitmap = resBm;
|
resBitmap = resBm;
|
||||||
if (teamColor != null)
|
if (teamColor != null)
|
||||||
{
|
{
|
||||||
Rectangle opaqueBounds;
|
Rectangle opaqueBounds;
|
||||||
teamColor.ApplyToImage(resBm, out opaqueBounds);
|
teamColor.ApplyToImage(resBm, out opaqueBounds);
|
||||||
result.opaqueBounds = opaqueBounds;
|
resBounds = opaqueBounds;
|
||||||
// EXPERIMENTAL: might be better not to cache this?
|
|
||||||
//teamColorTextures[(filename, teamColor)] = (new Bitmap(result.bitmap), result.opaqueBounds);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result.opaqueBounds = ImageUtils.CalculateOpaqueBounds(resBm);
|
resBounds = ImageUtils.CalculateOpaqueBounds(resBm);
|
||||||
}
|
}
|
||||||
return result;
|
return (resBitmap, resBounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadTgaFromZipFileStream(Stream fileStream, String name, ref TGA tga, ref JObject metadata)
|
private void LoadTgaFromZipFileStream(Stream fileStream, String name, ref TGA tga, ref JObject metadata)
|
||||||
|
@ -23,7 +23,7 @@ using System.Xml;
|
|||||||
|
|
||||||
namespace MobiusEditor.Utility
|
namespace MobiusEditor.Utility
|
||||||
{
|
{
|
||||||
public class Tile
|
public class Tile: IDisposable
|
||||||
{
|
{
|
||||||
public Bitmap Image { get; private set; }
|
public Bitmap Image { get; private set; }
|
||||||
|
|
||||||
@ -39,6 +39,24 @@ namespace MobiusEditor.Utility
|
|||||||
: this(image, new Rectangle(0, 0, image.Width, image.Height))
|
: this(image, new Rectangle(0, 0, image.Width, image.Height))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Bitmap image = this.Image;
|
||||||
|
this.Image = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (image != null)
|
||||||
|
{
|
||||||
|
image.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignore.
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Tileset
|
public class Tileset
|
||||||
@ -77,6 +95,17 @@ namespace MobiusEditor.Utility
|
|||||||
{
|
{
|
||||||
foreach (var tileItem in item.Value)
|
foreach (var tileItem in item.Value)
|
||||||
{
|
{
|
||||||
|
// no need to dispose the images; the Reset of TextureManager handles that.
|
||||||
|
foreach (KeyValuePair<string, Tile[]> tileinfo in tileItem.Value.TeamColorTiles)
|
||||||
|
{
|
||||||
|
if (tileinfo.Value != null) {
|
||||||
|
foreach (Tile tile in tileinfo.Value)
|
||||||
|
{
|
||||||
|
// clean up bitmap
|
||||||
|
tile.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
tileItem.Value.TeamColorTiles.Clear();
|
tileItem.Value.TeamColorTiles.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user