* 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\TeamColor.cs" />
|
||||
<Compile Include="Utility\TeamColorManager.cs" />
|
||||
<Compile Include="Utility\TeamRemap.cs" />
|
||||
<Compile Include="Utility\TeamRemapManager.cs" />
|
||||
<Compile Include="Utility\TextureManager.cs" />
|
||||
<Compile Include="Utility\TGASharpLib.cs" />
|
||||
<Compile Include="Utility\Tileset.cs" />
|
||||
|
@ -12,6 +12,8 @@
|
||||
// distributed with this program. You should have received a copy of the
|
||||
// GNU General Public License along with permitted additional restrictions
|
||||
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
|
||||
using MobiusEditor.Model;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace MobiusEditor.Interface
|
||||
@ -20,5 +22,6 @@ namespace MobiusEditor.Interface
|
||||
{
|
||||
string DisplayName { get; }
|
||||
Bitmap Thumbnail { get; }
|
||||
void Reset();
|
||||
}
|
||||
}
|
||||
|
@ -14,8 +14,6 @@ namespace MobiusEditor.Interface
|
||||
{
|
||||
/// <summary>Name of the color, used as identifier.</summary>
|
||||
string Name { get; }
|
||||
/// <summary>A general color representing this team color.</summary>
|
||||
Color BaseColor { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Apply this color to a given image.
|
||||
|
@ -15,7 +15,12 @@ namespace MobiusEditor.Interface
|
||||
Color RemapBaseColor { 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 Reset(GameType gameType);
|
||||
void Reset(GameType gameType, string theater);
|
||||
}
|
||||
}
|
@ -1059,7 +1059,7 @@ namespace MobiusEditor
|
||||
{
|
||||
var fileInfo = new FileInfo(fileName);
|
||||
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('.');
|
||||
// No point in supporting jpeg here; the mapping needs distinct colours without fades.
|
||||
@ -1092,7 +1092,7 @@ namespace MobiusEditor
|
||||
ModPaths.TryGetValue(gameType, out modPaths);
|
||||
}
|
||||
loadMultiThreader.ExecuteThreaded(
|
||||
() => LoadFile(name, fileType, gameType, isTdMegaMap, modPaths),
|
||||
() => LoadFile(name, fileType, gameType, theater, isTdMegaMap, modPaths),
|
||||
PostLoad, true,
|
||||
(e,l) => LoadUnloadUi(e, l, loadMultiThreader),
|
||||
"Loading map");
|
||||
@ -1138,10 +1138,11 @@ namespace MobiusEditor
|
||||
"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;
|
||||
gameType = GameType.None;
|
||||
theater = null;
|
||||
isTdMegaMap = false;
|
||||
try
|
||||
{
|
||||
@ -1212,6 +1213,7 @@ namespace MobiusEditor
|
||||
{
|
||||
return false;
|
||||
}
|
||||
theater = (iniContents["Map"].TryGetValue("Theater") ?? "temperate").ToLower();
|
||||
switch (fileType)
|
||||
{
|
||||
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.
|
||||
Globals.TheArchiveManager.ExpandModPaths = modPaths;
|
||||
Globals.TheArchiveManager.Reset(gameType);
|
||||
Globals.TheGameTextManager.Reset(gameType);
|
||||
Globals.TheTextureManager.Reset();
|
||||
Globals.TheTextureManager.Reset(gameType, theater);
|
||||
Globals.TheTilesetManager.Reset();
|
||||
Globals.TheTeamColorManager.Reset(gameType);
|
||||
Globals.TheTeamColorManager.Reset(gameType, theater);
|
||||
IGamePlugin plugin = null;
|
||||
if (gameType == GameType.TiberianDawn)
|
||||
{
|
||||
@ -1334,6 +1336,7 @@ namespace MobiusEditor
|
||||
else if (gameType == GameType.RedAlert)
|
||||
{
|
||||
Globals.TheTeamColorManager.Load(@"DATA\XML\CNCRATEAMCOLORS.XML");
|
||||
Globals.TheTeamColorManager.Load("palette.cps");
|
||||
plugin = new RedAlert.GamePluginRA(!noImage);
|
||||
}
|
||||
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));
|
||||
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)
|
||||
{
|
||||
if (teamColorManager is TeamColorManager tcm)
|
||||
{
|
||||
// Add extra purple for flag..
|
||||
TeamColor teamColorPurple = new TeamColor(tcm);
|
||||
teamColorPurple.Load("PURPLE", "BASE_TEAM",
|
||||
// Add extra colors for flags.
|
||||
TeamColor teamColorSeven = new TeamColor(tcm);
|
||||
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,
|
||||
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));
|
||||
tcm.AddTeamColor(teamColorPurple);
|
||||
}
|
||||
else // if (teamColorManager is TeamRemapManager tcc)
|
||||
{
|
||||
// TODO classic team color
|
||||
//TeamRemap teamColorPurple = new TeamRemap(tcc);
|
||||
//teamColorPurple.Load(/*TODO*/);
|
||||
//tcc.AddTeamColor(teamColorPurple);
|
||||
tcm.AddTeamColor(teamColorEight);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The separate-threaded part for making a new map.
|
||||
/// </summary>
|
||||
@ -1424,7 +1418,7 @@ namespace MobiusEditor
|
||||
}
|
||||
try
|
||||
{
|
||||
IGamePlugin plugin = LoadNewPlugin(gameType, isTdMegaMap, modPaths);
|
||||
IGamePlugin plugin = LoadNewPlugin(gameType, theater, isTdMegaMap, modPaths);
|
||||
// This initialises the theater
|
||||
plugin.New(theater);
|
||||
if (SteamworksUGC.IsInit)
|
||||
@ -1488,11 +1482,11 @@ namespace MobiusEditor
|
||||
/// <param name="isTdMegaMap"></param>
|
||||
/// <param name="modPaths"></param>
|
||||
/// <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
|
||||
{
|
||||
IGamePlugin plugin = LoadNewPlugin(gameType, isTdMegaMap, modPaths);
|
||||
IGamePlugin plugin = LoadNewPlugin(gameType, theater, isTdMegaMap, modPaths);
|
||||
string[] errors = plugin.Load(loadFilename, fileType).ToArray();
|
||||
return new MapLoadInfo(loadFilename, fileType, plugin, errors);
|
||||
}
|
||||
@ -1650,7 +1644,7 @@ namespace MobiusEditor
|
||||
}
|
||||
// Unload graphics
|
||||
Globals.TheTilesetManager.Reset();
|
||||
Globals.TheTextureManager.Reset();
|
||||
Globals.TheTextureManager.Reset(GameType.None, null);
|
||||
// Clean up loaded file status
|
||||
filename = null;
|
||||
loadedFileType = FileType.None;
|
||||
|
@ -64,7 +64,7 @@ namespace MobiusEditor.Model
|
||||
|
||||
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[,] OccupyMask { get; private set; }
|
||||
@ -76,19 +76,19 @@ namespace MobiusEditor.Model
|
||||
|
||||
public bool HasBib
|
||||
{
|
||||
get { return (Flag & BuildingTypeFlag.Bib) == BuildingTypeFlag.Bib; }
|
||||
get { return (this.Flag & BuildingTypeFlag.Bib) == BuildingTypeFlag.Bib; }
|
||||
set
|
||||
{
|
||||
// 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
|
||||
{
|
||||
Flag &= ~BuildingTypeFlag.Bib;
|
||||
this.Flag &= ~BuildingTypeFlag.Bib;
|
||||
}
|
||||
RecalculateBibs();
|
||||
this.RecalculateBibs();
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,14 +101,14 @@ namespace MobiusEditor.Model
|
||||
public bool IsAircraft => false;
|
||||
public bool IsFixedWing => false;
|
||||
|
||||
public bool IsFake => (Flag & BuildingTypeFlag.Fake) == BuildingTypeFlag.Fake;
|
||||
public bool HasTurret => (Flag & BuildingTypeFlag.Turret) == BuildingTypeFlag.Turret;
|
||||
public bool IsSingleFrame => (Flag & BuildingTypeFlag.SingleFrame) == BuildingTypeFlag.SingleFrame;
|
||||
public bool CanRemap => (Flag & BuildingTypeFlag.NoRemap) != BuildingTypeFlag.NoRemap;
|
||||
public bool IsFake => (this.Flag & BuildingTypeFlag.Fake) == BuildingTypeFlag.Fake;
|
||||
public bool HasTurret => (this.Flag & BuildingTypeFlag.Turret) == BuildingTypeFlag.Turret;
|
||||
public bool IsSingleFrame => (this.Flag & BuildingTypeFlag.SingleFrame) == BuildingTypeFlag.SingleFrame;
|
||||
public bool CanRemap => (this.Flag & BuildingTypeFlag.NoRemap) != BuildingTypeFlag.NoRemap;
|
||||
/// <summary>
|
||||
/// Indicates buildings that have pieces sticking out at the top that should not overlap the objects on these cells.
|
||||
/// </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)
|
||||
{
|
||||
@ -118,7 +118,7 @@ namespace MobiusEditor.Model
|
||||
this.Name = name;
|
||||
this.GraphicsSource = graphicsSource ?? name;
|
||||
this.DisplayName = !String.IsNullOrEmpty(textId) && !String.IsNullOrEmpty(Globals.TheGameTextManager[textId])
|
||||
? Globals.TheGameTextManager[textId] + " (" + Name.ToUpperInvariant() + ")"
|
||||
? Globals.TheGameTextManager[textId] + " (" + this.Name.ToUpperInvariant() + ")"
|
||||
: name.ToUpperInvariant();
|
||||
this.PowerProduction = powerProd;
|
||||
this.PowerUsage = powerUse;
|
||||
@ -184,30 +184,30 @@ namespace MobiusEditor.Model
|
||||
|
||||
private void RecalculateBibs()
|
||||
{
|
||||
int maskY = BaseOccupyMask.GetLength(0);
|
||||
int maskX = BaseOccupyMask.GetLength(1);
|
||||
if (HasBib)
|
||||
int maskY = this.BaseOccupyMask.GetLength(0);
|
||||
int maskX = this.BaseOccupyMask.GetLength(1);
|
||||
if (this.HasBib)
|
||||
{
|
||||
OccupyMask = new bool[maskY + 1, maskX];
|
||||
for (var y = 0; y < maskY; ++y)
|
||||
this.OccupyMask = new bool[maskY + 1, maskX];
|
||||
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)
|
||||
{
|
||||
for (var x = 0; x < maskX; ++x)
|
||||
for (int x = 0; x < maskX; ++x)
|
||||
{
|
||||
OccupyMask[maskY, x] = true;
|
||||
OccupyMask[maskY - 1, x] = true;
|
||||
this.OccupyMask[maskY, x] = true;
|
||||
this.OccupyMask[maskY - 1, x] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OccupyMask = BaseOccupyMask;
|
||||
this.OccupyMask = this.BaseOccupyMask;
|
||||
}
|
||||
}
|
||||
|
||||
@ -218,15 +218,15 @@ namespace MobiusEditor.Model
|
||||
int baseMaskX = this.BaseOccupyMask.GetLength(1);
|
||||
string occupyMask = GeneralUtils.GetStringFromMask(this.BaseOccupyMask);
|
||||
TheaterType[] theaters = null;
|
||||
if (Theaters != null)
|
||||
if (this.Theaters != null)
|
||||
{
|
||||
int thLen = Theaters.Length;
|
||||
int thLen = this.Theaters.Length;
|
||||
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.
|
||||
BuildingType newBld = new BuildingType(ID, Name, null, PowerProduction, PowerUsage, Storage, baseMaskX, baseMaskY, occupyMask, OwnerHouse, theaters, FactoryOverlay, FrameOFfset, GraphicsSource, Flag);
|
||||
newBld.DisplayName = DisplayName;
|
||||
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 = this.DisplayName;
|
||||
return newBld;
|
||||
}
|
||||
|
||||
@ -238,11 +238,11 @@ namespace MobiusEditor.Model
|
||||
}
|
||||
else if (obj is sbyte)
|
||||
{
|
||||
return ID == (sbyte)obj;
|
||||
return this.ID == (sbyte)obj;
|
||||
}
|
||||
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);
|
||||
@ -250,44 +250,44 @@ namespace MobiusEditor.Model
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return ID.GetHashCode();
|
||||
return this.ID.GetHashCode();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
var oldImage = Thumbnail;
|
||||
var mockBuilding = new Building()
|
||||
Bitmap oldImage = this.Thumbnail;
|
||||
Building mockBuilding = new Building()
|
||||
{
|
||||
Type = this,
|
||||
House = house,
|
||||
Strength = 256,
|
||||
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)
|
||||
{
|
||||
var th = new Bitmap(render.Item1.Width, render.Item1.Height);
|
||||
Bitmap th = new Bitmap(render.Item1.Width, render.Item1.Height);
|
||||
th.SetResolution(96, 96);
|
||||
using (var g = Graphics.FromImage(th))
|
||||
using (Graphics g = Graphics.FromImage(th))
|
||||
{
|
||||
MapRenderer.SetRenderSettings(g, Globals.PreviewSmoothScale);
|
||||
render.Item2(g);
|
||||
if (IsFake)
|
||||
if (this.IsFake)
|
||||
{
|
||||
MapRenderer.RenderFakeBuildingLabel(g, mockBuilding, Point.Empty, Globals.PreviewTileSize, Globals.PreviewTileScale, false);
|
||||
}
|
||||
}
|
||||
Thumbnail = th;
|
||||
OpaqueMask = GeneralUtils.FindOpaqueCells(th, Size, 10, 25, 0x80);
|
||||
this.Thumbnail = th;
|
||||
this.OpaqueMask = GeneralUtils.FindOpaqueCells(th, this.Size, 10, 25, 0x80);
|
||||
}
|
||||
else
|
||||
{
|
||||
Thumbnail = null;
|
||||
this.Thumbnail = null;
|
||||
}
|
||||
if (oldImage != null)
|
||||
{
|
||||
@ -295,5 +295,16 @@ namespace MobiusEditor.Model
|
||||
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 */ }
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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 */ }
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
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.
|
||||
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 */ }
|
||||
}
|
||||
}
|
||||
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 */ }
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -1573,7 +1573,7 @@ namespace MobiusEditor.Render
|
||||
return;
|
||||
}
|
||||
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;
|
||||
int maskY = cells.GetLength(0);
|
||||
int maskX = cells.GetLength(1);
|
||||
@ -1601,7 +1601,7 @@ namespace MobiusEditor.Render
|
||||
return;
|
||||
}
|
||||
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);
|
||||
if (isJammer)
|
||||
{
|
||||
|
@ -394,9 +394,9 @@ namespace MobiusEditor.TiberianDawn
|
||||
flagColors[mpId] = Globals.TheTeamColorManager[house.UnitTeamColor];
|
||||
}
|
||||
// Metallic light blue
|
||||
flagColors[6] = Globals.TheTeamColorManager["BAD_UNIT"];
|
||||
flagColors[6] = Globals.TheTeamColorManager["MULTI7"];
|
||||
// RA Purple
|
||||
flagColors[7] = Globals.TheTeamColorManager["PURPLE"];
|
||||
flagColors[7] = Globals.TheTeamColorManager["MULTI8"];
|
||||
Size mapSize = !megaMap ? Constants.MaxSize : Constants.MaxSizeMega;
|
||||
Map = new Map(basicSection, null, mapSize, typeof(House), houseTypes,
|
||||
flagColors, TheaterTypes.GetTypes(), TemplateTypes.GetTypes(),
|
||||
@ -3284,7 +3284,10 @@ namespace MobiusEditor.TiberianDawn
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -85,14 +85,13 @@ namespace MobiusEditor.Utility
|
||||
public TeamColor(TeamColorManager teamColorManager, TeamColor col, string newName, Vector3 hsvShiftOverride)
|
||||
{
|
||||
this.teamColorManager = teamColorManager;
|
||||
this.Load(col);
|
||||
this.Name = newName;
|
||||
this.Load(col, newName);
|
||||
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.lowerBounds = col.LowerBounds;
|
||||
this.upperBounds = col.UpperBounds;
|
||||
|
@ -28,8 +28,16 @@ namespace MobiusEditor.Utility
|
||||
private readonly IArchiveManager megafileManager;
|
||||
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 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;
|
||||
}
|
||||
|
||||
public void Reset(GameType gameType)
|
||||
public void Reset(GameType gameType, string theater)
|
||||
{
|
||||
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 bool processedMissingTexture = false;
|
||||
|
||||
#if false
|
||||
private class ImageData
|
||||
{
|
||||
public TGA TGA;
|
||||
public JObject Metadata;
|
||||
}
|
||||
#endif
|
||||
|
||||
private readonly IArchiveManager megafileManager;
|
||||
|
||||
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)
|
||||
{
|
||||
this.megafileManager = megafileManager;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
public void Reset(GameType gameType, string theater)
|
||||
{
|
||||
Bitmap[] cachedImages = cachedTextures.Values.ToArray();
|
||||
cachedTextures.Clear();
|
||||
@ -67,20 +58,6 @@ namespace MobiusEditor.Utility
|
||||
// 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)
|
||||
@ -101,13 +78,9 @@ namespace MobiusEditor.Utility
|
||||
return (retCopy, bounds);
|
||||
}
|
||||
}
|
||||
if (teamColorTextures.TryGetValue((filename, teamColor), out (Bitmap bitmap, Rectangle opaqueBounds) result))
|
||||
{
|
||||
Bitmap retCopy = new Bitmap(result.bitmap);
|
||||
retCopy.SetResolution(96, 96);
|
||||
return (retCopy, result.opaqueBounds);
|
||||
}
|
||||
if (!cachedTextures.TryGetValue(filename, out result.bitmap))
|
||||
Bitmap resBitmap;
|
||||
Rectangle resBounds = Rectangle.Empty;
|
||||
if (!cachedTextures.TryGetValue(filename, out _))
|
||||
{
|
||||
if (Path.GetExtension(filename).ToLower() == ".tga")
|
||||
{
|
||||
@ -181,71 +154,8 @@ namespace MobiusEditor.Utility
|
||||
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
|
||||
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);
|
||||
result.bitmap = resBm;
|
||||
resBitmap = resBm;
|
||||
if (teamColor != null)
|
||||
{
|
||||
Rectangle opaqueBounds;
|
||||
teamColor.ApplyToImage(resBm, out opaqueBounds);
|
||||
result.opaqueBounds = opaqueBounds;
|
||||
// EXPERIMENTAL: might be better not to cache this?
|
||||
//teamColorTextures[(filename, teamColor)] = (new Bitmap(result.bitmap), result.opaqueBounds);
|
||||
resBounds = opaqueBounds;
|
||||
}
|
||||
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)
|
||||
|
@ -23,7 +23,7 @@ using System.Xml;
|
||||
|
||||
namespace MobiusEditor.Utility
|
||||
{
|
||||
public class Tile
|
||||
public class Tile: IDisposable
|
||||
{
|
||||
public Bitmap Image { get; private set; }
|
||||
|
||||
@ -39,6 +39,24 @@ namespace MobiusEditor.Utility
|
||||
: 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
|
||||
@ -77,6 +95,17 @@ namespace MobiusEditor.Utility
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user