SLMCImporter.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. #region License
  2. // Copyright 2019 Kastellanos Nikolaos
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. #endregion
  16. using System;
  17. using System.Collections;
  18. using System.Collections.Generic;
  19. using System.IO;
  20. using System.Xml;
  21. using Microsoft.Xna.Framework;
  22. using Microsoft.Xna.Framework.Content.Pipeline;
  23. using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
  24. using Microsoft.Xna.Framework.Graphics;
  25. namespace nkast.Aether.Content.Pipeline
  26. {
  27. [ContentImporter(".slmc", DisplayName = "SLMC Importer - Aether", DefaultProcessor = "SLMCProcessor")]
  28. public class SLMCImporter : ContentImporter<TextureContent>
  29. {
  30. public override TextureContent Import(string filename, ContentImporterContext context)
  31. {
  32. Texture2DContent output;
  33. if (Path.GetExtension(filename) != ".slmc")
  34. throw new InvalidContentException("File type not supported.");
  35. IList<Texture2DContent> images = ImportSLMC(filename, context);
  36. if (images.Count < 1)
  37. throw new InvalidContentException("Element 'channels' must have at least one 'image'.");
  38. if (images.Count > 4)
  39. throw new InvalidContentException("No more than 4 images are supported.");
  40. int width = images[0].Mipmaps[0].Width;
  41. int height = images[0].Mipmaps[0].Height;
  42. // validate size
  43. foreach (Texture2DContent image in images)
  44. {
  45. if (image.Mipmaps[0].Width != width|| image.Mipmaps[0].Height != height)
  46. throw new InvalidContentException("Images must be of the same size.");
  47. }
  48. int pixelCount = width * height;
  49. int byteCount = pixelCount * 4;
  50. byte[] data = new byte[byteCount];
  51. for (int i = 0; i < images.Count; i++)
  52. {
  53. Texture2DContent image = images[i];
  54. BitmapContent face = image.Faces[0][0];
  55. byte[] pixelData = face.GetPixelData();
  56. for (int d = 0; d < pixelCount; d++)
  57. {
  58. data[d * 4 + i] = pixelData[d * 4];
  59. }
  60. }
  61. PixelBitmapContent<Color> bitmap = new PixelBitmapContent<Color>(width, height);
  62. bitmap.SetPixelData(data);
  63. output = new Texture2DContent();
  64. output.Faces[0].Add(bitmap);
  65. return output;
  66. }
  67. private IList<Texture2DContent> ImportSLMC(string filename, ContentImporterContext context)
  68. {
  69. XmlDocument xmlDoc = new XmlDocument();
  70. xmlDoc.Load(filename);
  71. XmlElement channels = xmlDoc.DocumentElement;
  72. if (channels.Name != "channels")
  73. throw new InvalidContentException(String.Format("Root element must be 'channels'."));
  74. TextureImporter txImporter = new TextureImporter();
  75. List<Texture2DContent> images = new List<Texture2DContent>();
  76. foreach (XmlNode imageNode in channels.ChildNodes)
  77. {
  78. if (imageNode.Name != "image")
  79. throw new InvalidContentException(String.Format("Element '{0}' not supported in 'channels'.", imageNode.Name));
  80. string imageSource = GetAttribute(imageNode, "source");
  81. string fullImageSource = Path.Combine(Path.GetDirectoryName(filename), imageSource);
  82. context.AddDependency(fullImageSource);
  83. Texture2DContent textureContent = (Texture2DContent)txImporter.Import(fullImageSource, context);
  84. textureContent.Name = Path.GetFileNameWithoutExtension(fullImageSource);
  85. images.Add(textureContent);
  86. }
  87. return images;
  88. }
  89. private static string GetAttribute(XmlNode xmlNode, string attributeName)
  90. {
  91. XmlAttribute attribute = xmlNode.Attributes[attributeName];
  92. if (attribute == null) return null;
  93. return attribute.Value;
  94. }
  95. internal static int GetBitmapSize(SurfaceFormat format, int width, int height)
  96. {
  97. int pixels = width * height;
  98. switch (format)
  99. {
  100. case SurfaceFormat.Dxt1:
  101. return Math.Max(8, (pixels / 2));
  102. default:
  103. throw new NotImplementedException();
  104. }
  105. }
  106. }
  107. }