Monogame для Windows Phone 8: черные текстуры после деактивации
Я столкнулся со странной проблемой в моем приложении monogame (3.1) для Windows Phone 8. Когда приложение деактивировано, а затем активировано, все текстуры становятся черными. Это произошло также после блокировки экрана (UserIdleDetectionMode включен).
Я проверил GraphicsDevice.IsDisposed, GraphicsDevice.IsContentLost, GraphicsDevice.ResourcesLost, но все выглядит хорошо. Я реализовал перезагрузку всех своих текстур в событиях Activated и Unobscured, но полная перезагрузка текстуры занимает слишком много времени. В то же время в Marketplace я вижу одноигровые приложения, легко обрабатывающие функцию дезактивации-активации. Более того, это же приложение для windows phone 7, написанное на xna, восстанавливает очень быстро. Что я делаю не так с моногамой? Мое приложение основано на одноигровом шаблоне WP8.
Обновить:
Только что обнаружили, что все текстуры, загруженные через Content.Load (...), восстанавливаются очень быстро. Но все мои текстуры написаны от руки: я загружаю файл из TileContainer, распаковываю его, читаю его данные с помощью ImageTools, создаю Texture2D и устанавливаю его пиксели с загруженными данными. Файлы JPEG также отображаются в RenderTarget2D как BGR565, чтобы использовать пространство. Более того, я широко использую RenderTarget2D для рендеринга текстовых меток с тенями, композиций времени выполнения спрайтов и так далее. Похоже, что Monogame просто не хочет восстанавливать изображения, загруженные не Content.Load. Продолжать расследование...
2 ответа
Согласно моногамным разработчикам потерянные текстуры - нормальная ситуация. Я сделал полную перезагрузку текстуры в событии GraphicsDevice.DeviceReset. Чтобы это работало быстро, я реализовал загрузку из несжатых файлов xnb. Это довольно просто, если в этом формате есть только значения пикселей. Это единственное решение.
Вот как читать с несжатого xnb:
private static Texture2D TextureFromUncompressedXnbStream(GraphicsDevice graphicsDevice, Stream stream)
{
BinaryReader xnbReader = new BinaryReader(stream);
byte cx = xnbReader.ReadByte();
byte cn = xnbReader.ReadByte();
byte cb = xnbReader.ReadByte();
byte platform = xnbReader.ReadByte();
if (cx != 'X' || cn != 'N' || cb != 'B')
return null;
byte version = xnbReader.ReadByte();
byte flags = xnbReader.ReadByte();
bool compressed = (flags & 0x80) != 0;
if (version != 5 && version != 4)
return null;
int xnbLength = xnbReader.ReadInt32();
xnbReader.ReadBytes(0x9D);//skipping processor string
SurfaceFormat surfaceFormat = (SurfaceFormat)xnbReader.ReadInt32();
int width = (xnbReader.ReadInt32());
int height = (xnbReader.ReadInt32());
int levelCount = (xnbReader.ReadInt32());
int levelCountOutput = levelCount;
Texture2D texture = texture = new Texture2D(graphicsDevice, width, height, false, SurfaceFormat.Color);
for (int level = 0; level < levelCount; level++)
{
int levelDataSizeInBytes = (xnbReader.ReadInt32());
byte[] levelData = xnbReader.ReadBytes(levelDataSizeInBytes);
if (level >= levelCountOutput)
continue;
texture.SetData(level, null, levelData, 0, levelData.Length);
}
xnbReader.Dispose();
return texture;
}
Я только что получил ответ от Тома Спилмана на форумах Monogame, и очевидно, что содержимое Content.Load восстанавливается нормально, и другие данные должны быть повторно инициализированы программой. Что вы можете сделать, это подключиться к событию GraphicsDevice.DeviceResetting, чтобы получить уведомление, когда происходит этот сброс.