mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-01-13 12:56:35 -05:00
Added caching. Code cleanup.
This commit is contained in:
parent
98bb55a8ea
commit
2bf53e351c
@ -18,7 +18,7 @@ namespace OpenDiablo2.Common.Interfaces
|
||||
MPQFont GetMPQFont(string resourcePath);
|
||||
MPQDS1 GetMPQDS1(string resourcePath, LevelPreset level, LevelDetail levelDetail, LevelType levelType);
|
||||
MPQDT1 GetMPQDT1(string resourcePath);
|
||||
Palette GetPalette(string paletteName);
|
||||
Palette GetPalette(string paletteFile);
|
||||
MPQCOF GetPlayerAnimation(eHero hero, eWeaponClass weaponClass, eMobMode mobMode);
|
||||
MPQDCC GetPlayerDCC(MPQCOF.COFLayer cofLayer, eArmorType armorType, Palette palette);
|
||||
|
||||
|
39
OpenDiablo2.Common/Interfaces/ICache.cs
Normal file
39
OpenDiablo2.Common/Interfaces/ICache.cs
Normal file
@ -0,0 +1,39 @@
|
||||
/* OpenDiablo 2 - An open source re-implementation of Diablo 2 in C#
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Runtime.Caching;
|
||||
|
||||
namespace OpenDiablo2.Common.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides access to the cache system.
|
||||
/// </summary>
|
||||
public interface ICache
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets an item from the cache. If the item does not exist, the value factory will be executed to
|
||||
/// generate the value.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The return type of the value</typeparam>
|
||||
/// <param name="key">The name of the cache key, in the form of Type::X::Y::Z where
|
||||
/// Type is the base type, and x/y/z are unique identifiers for the item.</param>
|
||||
/// <param name="valueFactory">A function that returns the correct value if it does not already exist.</param>
|
||||
/// <param name="cacheItemPolicy">Pass in a new policy to control how this item is handled. Typically you can leave this null.</param>
|
||||
/// <returns>The item requested</returns>
|
||||
T AddOrGetExisting<T>(string key, Func<T> valueFactory, CacheItemPolicy cacheItemPolicy = null);
|
||||
}
|
||||
}
|
@ -1,17 +1,31 @@
|
||||
using System;
|
||||
/* OpenDiablo 2 - An open source re-implementation of Diablo 2 in C#
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OpenDiablo2.Common.Models
|
||||
{
|
||||
public sealed class MPQFont
|
||||
{
|
||||
public ImageSet FontImageSet;
|
||||
public Dictionary<byte, Size> CharacterMetric = new Dictionary<byte, Size>();
|
||||
public ImageSet FontImageSet { get; internal set; }
|
||||
public Dictionary<char, Size> CharacterMetric { get; internal set; } = new Dictionary<char, Size>();
|
||||
|
||||
public static MPQFont LoadFromStream(Stream fontStream, Stream tableStream)
|
||||
{
|
||||
@ -31,7 +45,7 @@ namespace OpenDiablo2.Common.Models
|
||||
br.ReadBytes(3);
|
||||
var size = new Size(br.ReadByte(), br.ReadByte());
|
||||
br.ReadBytes(3);
|
||||
var charCode = br.ReadByte();
|
||||
var charCode = (char)br.ReadByte();
|
||||
result.CharacterMetric[charCode] = size;
|
||||
br.ReadBytes(5);
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Runtime.Caching" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
@ -80,6 +81,7 @@
|
||||
<Compile Include="Enums\Mobs\eMobFlags.cs" />
|
||||
<Compile Include="Enums\Mobs\eStatModifierType.cs" />
|
||||
<Compile Include="Interfaces\Drawing\ICharacterRenderer.cs" />
|
||||
<Compile Include="Interfaces\ICache.cs" />
|
||||
<Compile Include="Interfaces\IItemManager.cs" />
|
||||
<Compile Include="Extensions\MobManagerExtensions.cs" />
|
||||
<Compile Include="Interfaces\IGameServer.cs" />
|
||||
|
@ -1,6 +1,21 @@
|
||||
using Autofac;
|
||||
/* OpenDiablo 2 - An open source re-implementation of Diablo 2 in C#
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Autofac;
|
||||
using OpenDiablo2.Common.Interfaces;
|
||||
using OpenDiablo2.Common.Interfaces.Drawing;
|
||||
using OpenDiablo2.Common.Interfaces.Mobs;
|
||||
using OpenDiablo2.Core.GameState_;
|
||||
using OpenDiablo2.Core.Map_Engine;
|
||||
@ -16,6 +31,7 @@ namespace OpenDiablo2.Core
|
||||
{
|
||||
log.Info("Configuring OpenDiablo2.Core service implementations.");
|
||||
|
||||
builder.RegisterType<Cache>().As<ICache>().SingleInstance();
|
||||
builder.RegisterType<Button>().As<IButton>().InstancePerDependency();
|
||||
builder.RegisterType<EngineDataManager>().As<IEngineDataManager>().SingleInstance();
|
||||
builder.RegisterType<ItemManager>().As<IItemManager>().SingleInstance();
|
||||
|
44
OpenDiablo2.Core/Cache.cs
Normal file
44
OpenDiablo2.Core/Cache.cs
Normal file
@ -0,0 +1,44 @@
|
||||
/* OpenDiablo 2 - An open source re-implementation of Diablo 2 in C#
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Runtime.Caching;
|
||||
using OpenDiablo2.Common.Interfaces;
|
||||
|
||||
namespace OpenDiablo2.Core
|
||||
{
|
||||
public sealed class Cache : ICache
|
||||
{
|
||||
private readonly static MemoryCache _cache = new MemoryCache("OpenDiablo2.Cache");
|
||||
|
||||
public Cache() { }
|
||||
|
||||
public T AddOrGetExisting<T>(string key, Func<T> valueFactory, CacheItemPolicy cacheItemPolicy = null)
|
||||
{
|
||||
var newValue = new Lazy<T>(valueFactory);
|
||||
var oldValue = _cache.AddOrGetExisting(key, newValue, cacheItemPolicy ?? new CacheItemPolicy()) as Lazy<T>;
|
||||
try
|
||||
{
|
||||
return (oldValue ?? newValue).Value;
|
||||
}
|
||||
catch
|
||||
{
|
||||
_cache.Remove(key);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -44,6 +44,7 @@
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Runtime.Caching" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
@ -56,6 +57,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AutofacModule.cs" />
|
||||
<Compile Include="Cache.cs" />
|
||||
<Compile Include="ItemManager.cs" />
|
||||
<Compile Include="EngineDataManager.cs" />
|
||||
<Compile Include="GameEngine.cs" />
|
||||
|
@ -1,8 +1,21 @@
|
||||
using System;
|
||||
/* OpenDiablo 2 - An open source re-implementation of Diablo 2 in C#
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using OpenDiablo2.Common;
|
||||
using OpenDiablo2.Common.Enums;
|
||||
using OpenDiablo2.Common.Interfaces;
|
||||
@ -12,19 +25,15 @@ namespace OpenDiablo2.Core
|
||||
{
|
||||
public sealed class ResourceManager : IResourceManager
|
||||
{
|
||||
private readonly ICache cache;
|
||||
private readonly IMPQProvider mpqProvider;
|
||||
private readonly IEngineDataManager engineDataManager;
|
||||
|
||||
private readonly Dictionary<string, ImageSet> ImageSets = new Dictionary<string, ImageSet>();
|
||||
private readonly Dictionary<string, MPQFont> MPQFonts = new Dictionary<string, MPQFont>();
|
||||
private readonly Dictionary<string, Palette> Palettes = new Dictionary<string, Palette>();
|
||||
private readonly Dictionary<string, MPQDT1> DTs = new Dictionary<string, MPQDT1>();
|
||||
private readonly Dictionary<string, MPQCOF> PlayerCOFs = new Dictionary<string, MPQCOF>();
|
||||
public Dictionary<string, List<AnimationData>> Animations { get; private set; }
|
||||
|
||||
public Dictionary<string, List<AnimationData>> Animations { get; private set; } = new Dictionary<string, List<AnimationData>>();
|
||||
|
||||
public ResourceManager(IMPQProvider mpqProvider, IEngineDataManager engineDataManager)
|
||||
public ResourceManager(ICache cache, IMPQProvider mpqProvider, IEngineDataManager engineDataManager)
|
||||
{
|
||||
this.cache = cache;
|
||||
this.mpqProvider = mpqProvider;
|
||||
this.engineDataManager = engineDataManager;
|
||||
|
||||
@ -32,70 +41,38 @@ namespace OpenDiablo2.Core
|
||||
}
|
||||
|
||||
public ImageSet GetImageSet(string resourcePath)
|
||||
{
|
||||
if (!ImageSets.ContainsKey(resourcePath))
|
||||
ImageSets[resourcePath] = ImageSet.LoadFromStream(mpqProvider.GetStream(resourcePath));
|
||||
|
||||
return ImageSets[resourcePath];
|
||||
}
|
||||
=> cache.AddOrGetExisting($"ImageSet::{resourcePath}", () => ImageSet.LoadFromStream(mpqProvider.GetStream(resourcePath)));
|
||||
|
||||
public MPQFont GetMPQFont(string resourcePath)
|
||||
{
|
||||
if (!MPQFonts.ContainsKey(resourcePath))
|
||||
MPQFonts[resourcePath] = MPQFont.LoadFromStream(mpqProvider.GetStream($"{resourcePath}.DC6"), mpqProvider.GetStream($"{resourcePath}.tbl"));
|
||||
|
||||
return MPQFonts[resourcePath];
|
||||
}
|
||||
=> cache.AddOrGetExisting($"Font::{resourcePath}", () => MPQFont.LoadFromStream(mpqProvider.GetStream($"{resourcePath}.DC6"), mpqProvider.GetStream($"{resourcePath}.tbl")));
|
||||
|
||||
public MPQDS1 GetMPQDS1(string resourcePath, LevelPreset level, LevelDetail levelDetail, LevelType levelType)
|
||||
{
|
||||
var mapName = resourcePath.Replace("data\\global\\tiles\\", "").Replace("\\", "/");
|
||||
return new MPQDS1(mpqProvider.GetStream(resourcePath), level, levelDetail, levelType, engineDataManager, this)
|
||||
{
|
||||
MapFile = resourcePath
|
||||
};
|
||||
}
|
||||
=> cache.AddOrGetExisting($"DS1::{resourcePath}::{level}::{levelDetail}::{levelType}", ()
|
||||
=> new MPQDS1(mpqProvider.GetStream(resourcePath), level, levelDetail, levelType, engineDataManager, this) { MapFile = resourcePath });
|
||||
|
||||
public Palette GetPalette(string paletteFile)
|
||||
{
|
||||
if (!Palettes.ContainsKey(paletteFile))
|
||||
=> cache.AddOrGetExisting($"Palette::{paletteFile}", () =>
|
||||
{
|
||||
var paletteNameParts = paletteFile.Split('\\');
|
||||
var paletteName = paletteNameParts[paletteNameParts.Count() - 2];
|
||||
Palettes[paletteFile] = Palette.LoadFromStream(mpqProvider.GetStream(paletteFile), paletteName);
|
||||
}
|
||||
|
||||
return Palettes[paletteFile];
|
||||
|
||||
|
||||
}
|
||||
return Palette.LoadFromStream(mpqProvider.GetStream(paletteFile), paletteName);
|
||||
});
|
||||
|
||||
public MPQDT1 GetMPQDT1(string resourcePath)
|
||||
{
|
||||
if (!DTs.ContainsKey(resourcePath))
|
||||
DTs[resourcePath] = new MPQDT1(mpqProvider.GetStream(resourcePath));
|
||||
|
||||
return DTs[resourcePath];
|
||||
}
|
||||
=> cache.AddOrGetExisting($"DT1::{resourcePath}", () => new MPQDT1(mpqProvider.GetStream(resourcePath)));
|
||||
|
||||
public MPQCOF GetPlayerAnimation(eHero hero, eWeaponClass weaponClass, eMobMode mobMode)
|
||||
{
|
||||
var key = $"{hero.ToToken()}{mobMode.ToToken()}{weaponClass.ToToken()}";
|
||||
if (PlayerCOFs.ContainsKey(key))
|
||||
return PlayerCOFs[key];
|
||||
|
||||
var path = $"{ResourcePaths.PlayerAnimationBase}\\{hero.ToToken()}\\COF\\{hero.ToToken()}{mobMode.ToToken()}{weaponClass.ToToken()}.cof";
|
||||
var result = MPQCOF.Load(mpqProvider.GetStream(path), Animations, hero, weaponClass, mobMode);
|
||||
PlayerCOFs[key] = result;
|
||||
|
||||
return result;
|
||||
}
|
||||
=> cache.AddOrGetExisting($"COF::{hero}::{weaponClass}::{mobMode}", () =>
|
||||
{
|
||||
var path = $"{ResourcePaths.PlayerAnimationBase}\\{hero.ToToken()}\\COF\\{hero.ToToken()}{mobMode.ToToken()}{weaponClass.ToToken()}.cof";
|
||||
return MPQCOF.Load(mpqProvider.GetStream(path), Animations, hero, weaponClass, mobMode);
|
||||
});
|
||||
|
||||
public MPQDCC GetPlayerDCC(MPQCOF.COFLayer cofLayer, eArmorType armorType, Palette palette)
|
||||
{
|
||||
// TODO: We need to cache this...
|
||||
byte[] binaryData;
|
||||
|
||||
|
||||
using (var stream = mpqProvider.GetStream(cofLayer.GetDCCPath(armorType)))
|
||||
{
|
||||
if (stream == null)
|
||||
@ -107,5 +84,24 @@ namespace OpenDiablo2.Core
|
||||
var result = new MPQDCC(binaryData, palette);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
=> cache.AddOrGetExisting($"DCC::{cofLayer}::{armorType}::{palette.Name}", () =>
|
||||
{
|
||||
byte[] binaryData;
|
||||
|
||||
using (var stream = mpqProvider.GetStream(cofLayer.GetDCCPath(armorType)))
|
||||
{
|
||||
if (stream == null)
|
||||
return null;
|
||||
|
||||
binaryData = new byte[stream.Length];
|
||||
stream.Read(binaryData, 0, (int)stream.Length);
|
||||
}
|
||||
var result = new MPQDCC(binaryData, palette);
|
||||
return result;
|
||||
});
|
||||
/*
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,6 @@ namespace OpenDiablo2.SDL2_
|
||||
private readonly IPaletteProvider paletteProvider;
|
||||
|
||||
private MPQCOF animationData;
|
||||
private MPQDCC[] layerData;
|
||||
|
||||
static readonly byte[] directionConversion = new byte[] { 3, 15, 4, 8, 0, 9, 5, 10, 1, 11, 6, 12, 2, 13, 7, 14 };
|
||||
|
||||
@ -138,19 +137,10 @@ namespace OpenDiablo2.SDL2_
|
||||
throw new ApplicationException("Could not locate animation for the character!");
|
||||
|
||||
var palette = paletteProvider.PaletteTable["Units"];
|
||||
var data = animationData.Layers
|
||||
.Select(layer => resourceManager.GetPlayerDCC(layer, ArmorType, palette))
|
||||
.ToArray();
|
||||
|
||||
log.Warn($"{data.Where(x => x == null).Count()} animation layers were not found!");
|
||||
|
||||
layerData = data.Where(x => x != null)
|
||||
.ToArray();
|
||||
|
||||
CacheFrames();
|
||||
CacheFrames(animationData.Layers.Select(layer => resourceManager.GetPlayerDCC(layer, ArmorType, palette)));
|
||||
}
|
||||
|
||||
private unsafe void CacheFrames()
|
||||
private unsafe void CacheFrames(IEnumerable<MPQDCC> layerData)
|
||||
{
|
||||
var cache = new DirectionCacheItem
|
||||
{
|
||||
@ -170,14 +160,26 @@ namespace OpenDiablo2.SDL2_
|
||||
var maxX = Int32.MinValue;
|
||||
var maxY = Int32.MinValue;
|
||||
|
||||
var layersIgnored = 0;
|
||||
var layersToRender = new List<MPQDCC>();
|
||||
foreach (var layer in layerData)
|
||||
{
|
||||
if (layer == null)
|
||||
{
|
||||
layersIgnored++;
|
||||
continue;
|
||||
}
|
||||
|
||||
layersToRender.Add(layer);
|
||||
minX = Math.Min(minX, layer.Directions[directionConversion[LocationDetails.MovementDirection]].Box.Left);
|
||||
minY = Math.Min(minY, layer.Directions[directionConversion[LocationDetails.MovementDirection]].Box.Top);
|
||||
maxX = Math.Max(maxX, layer.Directions[directionConversion[LocationDetails.MovementDirection]].Box.Right);
|
||||
maxY = Math.Max(maxY, layer.Directions[directionConversion[LocationDetails.MovementDirection]].Box.Bottom);
|
||||
}
|
||||
|
||||
if (layersIgnored > 0)
|
||||
log.Warn($"{layersIgnored} animation layer(s) were not found!");
|
||||
|
||||
var frameW = (maxX - minX) * 2; // Hack
|
||||
var frameH = (maxY - minY) * 2;
|
||||
|
||||
@ -191,8 +193,11 @@ namespace OpenDiablo2.SDL2_
|
||||
SDL.SDL_LockTexture(texture, IntPtr.Zero, out IntPtr pixels, out int pitch);
|
||||
UInt32* data = (UInt32*)pixels;
|
||||
|
||||
foreach (var layer in layerData)
|
||||
foreach (var layer in layersToRender)
|
||||
{
|
||||
if (layer == null)
|
||||
continue;
|
||||
|
||||
var direction = layer.Directions[directionConversion[LocationDetails.MovementDirection]];
|
||||
var frame = direction.Frames[frameIndex];
|
||||
|
||||
@ -212,8 +217,6 @@ namespace OpenDiablo2.SDL2_
|
||||
continue;
|
||||
|
||||
var color = palette.Colors[paletteIndex];
|
||||
var relativeX = (frame.XOffset - minX);
|
||||
var relativeY = (frame.YOffset - minY);
|
||||
|
||||
var offsetX = x + cell.XOffset + (frame.Box.X - minX);
|
||||
var offsetY = y + cell.YOffset + (frame.Box.Y - minY);
|
||||
@ -228,6 +231,7 @@ namespace OpenDiablo2.SDL2_
|
||||
|
||||
SDL.SDL_UnlockTexture(texture);
|
||||
SDL.SDL_SetTextureBlendMode(texture, SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND);
|
||||
|
||||
// TODO: Temporary code!
|
||||
cache.SpriteTexture[frameIndex] = texture;
|
||||
cache.SpriteRect[frameIndex] = new SDL.SDL_Rect { x = minX, y = minY, w = frameW, h = frameH };
|
||||
|
@ -48,7 +48,7 @@ namespace OpenDiablo2.SDL2_
|
||||
{
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
foreach(byte ch in text)
|
||||
foreach(var ch in text)
|
||||
{
|
||||
w += font.CharacterMetric[ch].Width;
|
||||
h = Math.Max(h, font.CharacterMetric[ch].Height);
|
||||
|
@ -76,7 +76,7 @@ namespace OpenDiablo2.SDL2_
|
||||
int h = 0;
|
||||
foreach (var ch in text)
|
||||
{
|
||||
var metric = font.font.CharacterMetric[(byte)ch];
|
||||
var metric = font.font.CharacterMetric[ch];
|
||||
w += metric.Width;
|
||||
h = Math.Max(Math.Max(h, metric.Height), font.sprite.FrameSize.Height);
|
||||
}
|
||||
@ -93,12 +93,12 @@ namespace OpenDiablo2.SDL2_
|
||||
var height = font.sprite.FrameSize.Height;
|
||||
for (int idx = 0; idx < text.Length; idx++)
|
||||
{
|
||||
width += font.font.CharacterMetric[(byte)text[idx]].Width;
|
||||
width += font.font.CharacterMetric[text[idx]].Width;
|
||||
|
||||
if (width >= MaxWidth)
|
||||
{
|
||||
idx = lastWordIndex;
|
||||
height += font.font.CharacterMetric[(byte)'|'].Height + 6;
|
||||
height += font.font.CharacterMetric['|'].Height + 6;
|
||||
width = 0;
|
||||
continue;
|
||||
}
|
||||
@ -146,7 +146,7 @@ namespace OpenDiablo2.SDL2_
|
||||
foreach (var ch in text)
|
||||
{
|
||||
WriteCharacter(cx, cy, (byte)ch);
|
||||
cx += font.font.CharacterMetric[(byte)ch].Width;
|
||||
cx += font.font.CharacterMetric[ch].Width;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -158,7 +158,7 @@ namespace OpenDiablo2.SDL2_
|
||||
var lastStartX = 0;
|
||||
for (int idx = 0; idx < text.Length; idx++)
|
||||
{
|
||||
width += font.font.CharacterMetric[(byte)text[idx]].Width;
|
||||
width += font.font.CharacterMetric[text[idx]].Width;
|
||||
|
||||
if (width >= MaxWidth)
|
||||
{
|
||||
@ -180,7 +180,7 @@ namespace OpenDiablo2.SDL2_
|
||||
var y = 0;
|
||||
foreach(var line in linesToRender)
|
||||
{
|
||||
var lineWidth = (line.Sum(c => font.font.CharacterMetric[(byte)c].Width));
|
||||
var lineWidth = (line.Sum(c => font.font.CharacterMetric[c].Width));
|
||||
var x = 0;
|
||||
|
||||
if (Alignment == eTextAlign.Centered)
|
||||
@ -191,10 +191,10 @@ namespace OpenDiablo2.SDL2_
|
||||
foreach (var ch in line)
|
||||
{
|
||||
WriteCharacter(x, y, (byte)ch);
|
||||
x += font.font.CharacterMetric[(byte)ch].Width;
|
||||
x += font.font.CharacterMetric[ch].Width;
|
||||
}
|
||||
|
||||
y += font.font.CharacterMetric[(byte)'|'].Height + 6;
|
||||
y += font.font.CharacterMetric['|'].Height + 6;
|
||||
}
|
||||
}
|
||||
SDL.SDL_SetRenderTarget(renderer, IntPtr.Zero);
|
||||
|
@ -5,7 +5,7 @@
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{2B0CF1AC-06DD-4322-AE8B-FF8A8C70A3CD}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>OpenDiablo2</RootNamespace>
|
||||
<AssemblyName>OpenDiablo2</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
|
@ -7,7 +7,7 @@
|
||||
</root>
|
||||
<appender name="console" type="log4net.Appender.ConsoleAppender">
|
||||
<layout type="log4net.Layout.PatternLayout">
|
||||
<conversionPattern value="%date %level %logger - %message%newline" />
|
||||
<conversionPattern value="%level %type{1}.%method - %message%newline" />
|
||||
</layout>
|
||||
</appender>
|
||||
<appender name="file" type="log4net.Appender.RollingFileAppender">
|
||||
|
Loading…
Reference in New Issue
Block a user