[dohtml]<style type="text/css">
<!--
body.hl { background-color:#ffffff; }
pre.hl { color:#000000; background-color:#FFFFFF; font-size:smaller; font-family:Courier New;}
.num { color:#000000; }
.esc { color:#000000; }
.str { color:#000000; }
.dstr { color:#000000; }
.slc { color:#008000; font-style:italic; }
.com { color:#008000; font-style:italic; }
.dir { color:#0000ff; }
.sym { color:#000000; }
.line { color:#008000; }
.kwa { color:#0000ff; font-weight:bold; }
.kwb { color:#0000ff; }
.kwc { color:#0000ff; font-weight:bold; }
.kwd { color:#000000; }
.clasMark { color:#339999 }
.stringMark { color: #660066 }
.Estilo1 {
font-family: verdana;
font-size: 85%;
}
.Estilo14 {font-size: smaller; font-family: verdana; text-align:justify}
.Estilo16 {font-size: large; font-family: verdana; font-weight: bold; }
.Estilo17 {font-size: medium}
.Estilo19 {font-size: smaller; font-family: verdana; color: #0000FF; }
.Estilo21 {font-size: smaller; font-family: verdana; color: rgb(51,153,153); }
//-->
</style>
<p class="Estilo16">
El XNA Content Pipeline</p>
<p class="Estilo16 Estilo17">
Que es el Content Pipeline?</p>
<p class="Estilo14">
El content pipeline es una API que permite a los desarrolladores y diseñadores incorporar
contenidos multimedia en los proyectos creados con XNA framework, estos contenidos
multimedia son por ejemplo:</p>
<ul>
<li class="Estilo14">imágenes</li>
<li class="Estilo14">sonidos</li>
<li class="Estilo14">contenido 3d</li>
<li class="Estilo14">efectos</li>
</ul>
<span class="Estilo14">Por defecto el content pipeline soporta una amplia gama de formatos
de archivo diferentes los cuales son usualmente usados en la industria de los videojuegos,
el content pipeline (en adelante CPL) facilita el acceso a estos archivos y brinda
un interfaz de acceso unificada que permite acceder a dichos recursos desde cualquier
objeto utilizado dentro del juego sin necesidad de hacer uso de múltiples referencias
cruzadas lo cual desde luego va en favor de la independencia de cada componente
lo cual en un juego generalmente es una tarea muy difícil de hacer. Sin embargo
las capacidades del CPL podrían verse limitadas por la cantidad de archivos que
soporta puesto que es muy común que en la industria de los videojuegos se usen formatos
de archivo independientes de acuerdo a las necesidades particulares de cada proyecto,
es aquí donde reside una de las mas importantes características del CPL... es <strong>
extensible</strong>.
<br />
<br />
El CPL incorpora un marco de trabajo que permite fácilmente incorporar soporte a
diferentes tipos de archivo e incluso extender la funcionalidad de un tipo de archivo
ya soportado.</span>
<p class="Estilo16 Estilo17 ">
Como Funciona el Content PipeLine?</p>
<p>
<span class="Estilo14">Lo primero ha tener en cuenta son los elementos con los cuales
trabaja:</span></p><p>
<span class="Estilo19">Namespace: Microsoft.Xna.Framework.Content.Pipeline </span>
<span class="Estilo21">
<br />
ContentImporter
<br />
ContentProcessor</span>
<br />
<span class="Estilo19">Namespace: Microsoft.Xna.Framework.Content </span>
<br />
<span class="Estilo21">ContentTypeReader</span><br />
<span class="Estilo19">Namespace: Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compile </span>
<br />
<span class="Estilo21">ContentTypeWriter</span>
</p>
<p class="Estilo14">
El camino comienza con el ContentImporter este es el encargado de realizar lectura
física del archivo a importar y colocar la información en un objeto capaz de almacenarla.
Seguidamente la información colocada en el objeto es pasada a través de un ContentProcessor
el cual se encarga de realizar transformaciones en la información cargada en el
paso anterior. El <span class="Estilo21">ContentTypeWriter</span> se encarga de
escribir ese objeto en un archivo con el formato del CPL. Todos los pasos anteriores
suceden en tiempo de compilación, el ultimo paso sucede en tiempo de ejecución cuando
el juego ya esta ejecutándose, es allí donde el <span class="Estilo21">ContentTypeReader</span>
lee los archivos creados por el CPL para cargar en memoria el recurso almacenado.
Debido a que se debe adicionar una referencia a estas clases en el CPL es necesario
que los tres primeros objetos existan compilados en una librería dinámica, mientras
que el ultimo puede hacer parte el juego directamente.</p>
<p>
<a style="color: rgb(0, 0, 0);" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"
href="http://bp0.blogger.com/_SpDJXReOOTs/Rf2RfHjZDuI/AAAAAAAAAAM/8fYWjN1MDIc/s1600-h/CPL.PNG">
<img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;"
src="http://bp0.blogger.com/_SpDJXReOOTs/Rf2RfHjZDuI/AAAAAAAAAAM/8fYWjN1MDIc/s400/CPL.PNG"
alt="" id="BLOGGER_PHOTO_ID_5043347121514286818" border="0" /></a>
</p>
<span class="Estilo16 Estilo17">Como hacer que el Content Pipeline soporte un archivo
diferente? </span>
<p>
<span class="Estilo14">Normalmente con tan solo el </span><span class="Estilo21">ContentImporter</span><span
class="Estilo14"> y el </span><span class="Estilo21">ContentProcessor</span><span
class="Estilo14"> es suficiente para cargar un tipo de archivo ya que basicamente
lo que se hace es utilizar estos objetos para convertir los datos del archivo en
uno de los tipos de dato ya soportados por el CPL, sin embargo si se requiere información
adicional que no es contenida en el tipo soportado es entonces necesario que el
desarrollador establezca la forma en que el CPL escribe esos datos en un archivo
del CPL y la forma en que el CPL debe cargarlos una vez se solicite desde el juego,
para ello son las clases </span><span class="Estilo21">ContentTypeWriter</span><span
class="Estilo14"> y </span><span class="Estilo21">ContentTypeReader</span><span class="Estilo14">.
La buena noticia es que para adicionar soporte a un nuevo tipo de archivo estas
clases proveen los mecanismos necesarios para implementarlo de manera relativamente
fácil, la mala noticia es que todas son clases abstractas así que la mayoría del
trabajo lo debe hacer uno mismo.
</span>
</p>
<p class="Estilo14">
A continuación un ejemplo de Implementación de un nuevo tipo de archivo para el
CPL.
<br />
<br />
Supongamos existe un tipo de arhivo bmp2 dicho archivo posee la información habitual
de un archivo bmp más tres datos muy importantes que requerimos (todos los campos
son un ejemplo):</p>
<ul class="Estilo14">
<li>Color de Máscara</li>
<li>Número de Colores</li>
<li>Prioridad</li>
</ul>
<span class="Estilo14">La tarea nro 1 crear un </span><span class="Estilo21">ContentImporter</span><span
class="Estilo14"> . Hay que recordar que </span><span class="Estilo21">ContentImporter</span><span
class="Estilo14"> es una clase abstracta asi que se debe crear una clase que herede
de </span><span class="Estilo21">ContentImporter</span><span class="Estilo14"> , adicionalmente
esta clase es genérica por lo cual debemos pasar el parámetro del tipo de dato que
se soportara para importar.</span>
<pre><span class="kwa">public class</span> <span class="clasMark">BMP2Importer</span> <span
class="sym">:</span> <span class="clasMark">ContentImporter</span>
<span class="sym">{ }</span></pre>
<span class="Estilo14">pero un momento... de donde salio </span><span class="Estilo21">
BMP2Content</span><span class="Estilo14">? bueno dado que se esta incorporando un nuevo
tipo de archivo es necesario que crear un objeto contenedor de los datos que se
cargan desde ese archivo, teniendo en cuenta que el formato bmp2 lo usaremos para
crear texturas 2D lo mejor que se puede hacer es crear una clase que herede de un
contenedor existente, para este caso </span><span class="Estilo21">Texture2DContent</span><span
class="Estilo14"> :</span>
<pre><span class="kwa">using</span> Microsoft<span class="sym">.</span>Xna<span class="sym">.</span>Framework<span
class="sym">;</span>
<span class="kwa">using</span> Microsoft<span class="sym">.</span>Xna<span class="sym">.</span>Framework<span
class="sym">.</span>Graphics<span class="sym">;</span>
<span class="kwa">using</span> Microsoft<span class="sym">.</span>Xna<span class="sym">.</span>Framework<span
class="sym">.</span>Content<span class="sym">.</span>Pipeline<span class="sym">;</span>
<span class="kwa">using</span> Microsoft<span class="sym">.</span>Xna<span class="sym">.</span>Framework<span
class="sym">.</span>Content<span class="sym">.</span>Pipeline<span class="sym">.</span>Graphics<span
class="sym">;</span>
<span class="kwa">public class</span> <span class="clasMark">BMP2Content</span> <span
class="sym">:</span> <span class="clasMark">Texture2DContent</span>
<span class="sym">{</span>
<span class="kwa">public</span> <span class="kwd">BMP2Content</span><span class="sym">():</span> <span
class="kwa">base</span><span class="sym">()</span>
<span class="sym">{}</span>
<span class="kwa">private</span> <span class="clasMark">Color</span> maskColor<span
class="sym">;</span>
<span class="kwa">public</span> <span class="clasMark">Color</span> MaskColor
<span class="sym">{</span>
<span class="kwa">get</span>
<span class="sym">{</span>
<span class="kwa">return</span> maskColor<span class="sym">;</span>
<span class="sym">}</span>
<span class="kwa">set</span>
<span class="sym">{</span>
maskColor <span class="sym">=</span> <span class="kwa">value</span><span class="sym">;</span>
<span class="sym">}</span>
<span class="sym">}</span>
<span class="kwa">private</span> <span class="kwb">int</span> numColores<span class="sym">;</span>
<span class="kwa">public</span> <span class="kwb">int</span> NumColores
<span class="sym">{</span>
<span class="kwa">get</span>
<span class="sym">{</span>
<span class="kwa">return</span> numColores<span class="sym">;</span>
<span class="sym">}</span>
<span class="kwa">set</span>
<span class="sym">{</span>
numColores <span class="sym">=</span> <span class="kwa">value</span><span class="sym">;</span>
<span class="sym">}</span>
<span class="sym">}</span>
<span class="kwa">private</span> <span class="kwb">byte</span> prioridad<span class="sym">;</span>
<span class="kwa">public</span> <span class="kwb">byte</span> Prioridad
<span class="sym">{</span>
<span class="kwa">get</span>
<span class="sym">{</span>
<span class="kwa">return</span> prioridad<span class="sym">;</span>
<span class="sym">}</span>
<span class="kwa">set</span>
<span class="sym">{</span>
prioridad <span class="sym">=</span> <span class="kwa">value</span><span class="sym">;</span>
<span class="sym">}</span>
<span class="sym">}</span>
<span class="sym">}</span></pre>
<p class="Estilo14">
Este contenedor permite manipular los datos desde su cargue hasta su transformacion
y escritura en un archivo del content pipeline, sin embargo se requiere de una estructura
adicional para manipularlo, porque? bueno el contenedor puede ser realmente cualquier
estructura pero se requiere que sea liviana puesto que la cantidad de recursos que
tengamos puede incrementar dramaticamente el tiempo que se invcierta en la compilacion
del proyecto ya que cada uno de los recursos pasara por un importer, un processor
y un writer, ya cuando se va a utilizar esa informacion en un objeto util para el
juego si debemos disponer de toda la infromacion necesaria.
<br />
<br />
Para este ejemplo, debido a que el archivo de tipo bmp2 va a ser usado como textura
se pueden usar dos opciones, una es crear una clase de textura nueva (poco recomendable)
y la otra es crear una clase que herede de un tipo de textura ya existente, para
el caso lo que mas nos conviene es crear una clase que herede de <span class="Estilo21">
Texture2D</span>.</p>
<pre><span class="kwa">public class</span> <span class="clasMark">BMP2Texture2D</span> <span
class="sym">:</span> <span class="clasMark">Texture2D</span>
<span class="sym">{</span>
<span class="kwa">public</span> <span class="clasMark">BMP2Texture2D</span><span
class="sym">(</span><span class="clasMark">GraphicsDevice</span> device<span class="sym">,</span> <span
class="kwb">int</span> height<span class="sym">,</span> <span class="kwb">int</span> with<span
class="sym">,</span>
<span class="kwb">int</span> numberLevels<span class="sym">,</span> <span class="clasMark">ResourceUsage</span> usage<span
class="sym">,</span> <span class="clasMark">SurfaceFormat</span> format<span class="sym">)</span>
<span class="sym">:</span> <span class="kwa">base</span><span class="sym">(</span>device<span
class="sym">,</span> with<span class="sym">,</span> height<span class="sym">,</span> numberLevels<span
class="sym">,</span> usage<span class="sym">,</span> format<span class="sym">)</span>
<span class="sym">{}</span>
<span class="kwa">public</span> <span class="kwd">BMP2Texture2D</span><span class="sym">(</span><span
class="clasMark">GraphicsDevice</span> device<span class="sym">,</span> <span class="kwb">int</span> height<span
class="sym">,</span> <span class="kwb">int</span> with<span class="sym">,</span> <span
class="kwb">int</span> numberLevels<span class="sym">,</span>
<span class="clasMark">ResourceUsage</span> usage<span class="sym">,</span> <span
class="clasMark">SurfaceFormat</span> format<span class="sym">,</span>
<span class="clasMark">ResourceManagementMode</span> resourceManagementMode<span
class="sym">)</span>
<span class="sym">:</span> <span class="kwa">base</span><span class="sym">(</span>device<span
class="sym">,</span> with<span class="sym">,</span> height<span class="sym">,</span> numberLevels<span
class="sym">,</span> usage<span class="sym">,</span> format<span class="sym">,</span> resourceManagementMode<span
class="sym">)</span>
<span class="sym">{</span>
<span class="sym">}</span>
<span class="kwa">private</span> <span class="clasMark">Color</span> maskColor<span
class="sym">;</span>
<span class="kwa">public</span> <span class="clasMark">Color</span> MaskColor
<span class="sym">{</span>
<span class="kwa">get</span>
<span class="sym">{</span>
<span class="kwa">return</span> maskColor<span class="sym">;</span>
<span class="sym">}</span>
<span class="kwa">set</span>
<span class="sym">{</span>
maskColor <span class="sym">=</span> <span class="kwa">value</span><span class="sym">;</span>
<span class="sym">}</span>
<span class="sym">}</span>
<span class="kwa">private</span> <span class="kwb">int</span> numColores<span class="sym">;</span>
<span class="kwa">public</span> <span class="kwb">int</span> NumColores
<span class="sym">{</span>
<span class="kwa">get</span>
<span class="sym">{</span>
<span class="kwa">return</span> numColores<span class="sym">;</span>
<span class="sym">}</span>
<span class="kwa">set</span>
<span class="sym">{</span>
numColores <span class="sym">=</span> <span class="kwa">value</span><span class="sym">;</span>
<span class="sym">}</span>
<span class="sym">}</span>
<span class="kwa">private</span> <span class="kwb">byte</span> prioridad<span class="sym">;</span>
<span class="kwa">public</span> <span class="kwb">byte</span> Prioridad
<span class="sym">{</span>
<span class="kwa">get</span>
<span class="sym">{</span>
<span class="kwa">return</span> prioridad<span class="sym">;</span>
<span class="sym">}</span>
<span class="kwa">set</span>
<span class="sym">{</span>
prioridad <span class="sym">=</span> <span class="kwa">value</span><span class="sym">;</span>
<span class="sym">}</span>
<span class="sym">}</span>
<span class="sym">}</span>
</pre>
<p class="Estilo14">
Esta clase ya trae todo lo que necesita una textura 2d más las cosas propias del
formato bmp2 de el ejemplo.
<br />
Ahora si se puede crear el <span class="Estilo21">ContentImporter</span> indicando
el tipo de contenido a almacenar.
</p>
<pre>
<span class="sym">[</span><span class="kwd">ContentImporter</span><span class="sym">(</span><span
class="stringMark">".bmp2"</span><span class="sym">,</span> DisplayName <span
class="sym">=</span> <span class="stringMark">"Imagen BMP2"</span><span
class="sym">,</span> DefaultProcessor <span class="sym">=</span> <span class="stringMark">"Procesador
para imagenes BMP2"</span><span class="sym">)]</span>
<span class="kwa">public class</span> <span class="clasMark">BMP2Importer</span> <span
class="sym">:</span> <span class="clasMark">ContentImporter</span><span class="sym"><</span><span
class="clasMark">BMP2Content</span><span class="sym">></span>
<span class="sym">{</span>
<span class="kwa">public override</span> <span class="clasMark">BMP2Content</span> <span
class="kwd">Import</span><span class="sym">(</span><span class="kwb">string</span> filename<span
class="sym">,</span> <span class="clasMark">ContentImporterContext</span> context<span
class="sym">)</span>
<span class="sym">{</span>
<span class="clasMark">BPM2</span> miBmp <span class="sym">=</span> <span class="kwa">new</span> <span
class="clasMark">BMP2</span><span class="sym">(</span>filename<span class="sym">);</span>
<span class="slc">//Este objeto es de ayuda para recuperar la informacion de color y
llevarla facilmente al</span>
<span class="slc">//MipmapChain del objeto textureContent</span>
<span class="clasMark">PixelBitmapContent</span><span class="sym"><</span><span
class="clasMark">Rgb24</span><span class="sym">></span> pixelHelper<span class="sym">;</span>
<span class="slc">//Array de textura a retornar</span>
<span class="clasMark">BMP2Content</span> textureContent<span class="sym">;</span>
<span class="slc">//Array de bytes para capturar la informacion del archivo JKI</span>
<span class="kwb">byte</span><span class="sym">[]</span> byteArray<span class="sym">;</span>
<span class="slc">//Inicializa un nuevo contenedor de datos de pixeles</span>
pixelHelper <span class="sym">=</span> <span class="kwa">new</span> <span class="clasMark">PixelBitmapContent</span><span
class="sym"><</span><span class="clasMark">Rgb24</span><span class="sym">>(</span>miBmp<span
class="sym">.</span>Width<span class="sym">,</span>miBmp<span class="sym">.</span>Height<span
class="sym">);</span>
<span class="slc">//Cargar la informacion de bytes para el archivo</span>
byteArray <span class="sym">=</span> miBmp<span class="sym">.</span><span class="kwd">GetBytes</span><span
class="sym">();</span>
<span class="slc">//Envia los datos de bytes al pixel helper</span>
pixelHelper<span class="sym">.</span><span class="kwd">SetPixelData</span><span class="sym">(</span>byteArray<span
class="sym">);</span>
<span class="slc">//Inicializa un nuevo contenedor para la textura</span>
textureContent <span class="sym">=</span> <span class="kwa">new</span> <span class="clasMark">BMP2Content</span><span
class="sym">();</span>
<span class="slc">//Carga la informacion de la imagen en la textura</span>
textureContent<span class="sym">.</span>Mipmaps <span class="sym">=</span> <span
class="kwa">new</span> <span class="clasMark">MipmapChain</span><span class="sym">(</span>pixelHelper<span
class="sym">);</span>
<span class="slc">//Guarda el color de mascara de la imagen</span>
textureContent<span class="sym">.</span>MaskColor <span class="sym">=</span> <span
class="kwa">new</span> <span class="clasMark">Color</span><span class="sym">(</span>miBmp<span
class="sym">.</span>ColorMascara<span class="sym">.</span>R<span class="sym">,</span>miBmp<span
class="sym">.</span>ColorMascara<span class="sym">.</span>G<span class="sym">,</span>
miBmp<span class="sym">.</span>ColorMascara<span class="sym">.</span>B<span class="sym">);</span>
<span class="slc">//Establecer el numero de colores</span>
textureContent<span class="sym">.</span>NumColores <span class="sym">=</span> miBmp<span
class="sym">.</span>Palette<span class="sym">.</span>Count<span class="sym">;</span>
textureContent<span class="sym">.</span>Prioridad <span class="sym">=</span> <span
class="num">0</span><span class="sym">;</span>
<span class="kwa">return</span> textureContent<span class="sym">;</span>
<span class="sym">}</span>
<span class="sym">}</span>
</pre>
<p class="Estilo14">
La primera linea es un atributo de la clase, la cual le permitira al Content Pipeline
identificar que esta es un <span class="Estilo21">ContentImporter</span> y le proporcionara
informacion adicional acerca de que informacion debe mostrar desde el IDE de Visual
Studio respecto a los archivos que este ContentImporter es capaz de utilizar asi
como un nombre descriptivo de la funcionalidad. Seguidamente lo que se hace cargar
desde archvo un objeto BMP2 el cual desde luego es un objeto que ya es capaz de
cargar un archivo bmp2, el objeto pixelHelper es utilizado como una 'Helper Class'
ya que si bien no se necesita de manera directa, si es un excelente atajo para poder
crear un <span class="Estilo21">MipmapChain</span> el cual es requerido para cargar
en un objeto <span class="Estilo21">Texture2DContent</span> con la informacion de
la imagen que se requiere, finalmente en la parte inferior del método se asignan
la informacion adicional que se requiere.
<br />
<br />
Una vez se ha importado la informacion desde el archivo esta debe pasar por el processor,
el procesor se debe hacer para que funcione igual que funciona un procesor para
una imagen BMP normal asi que se puede reutilizar un processor que ya este creado
en XNA y eso es todo ya que sobre el resto de la informacion no se requiere hacer
ninguna modificacion. El processor en este caso es bastante sencillo:
</p>
<pre>
<span class="sym">[</span><span class="kwd">ContentProcessor</span><span class="sym">(</span>DisplayName <span
class="sym">=</span> <span class="stringMark">"Procesador para imagenes BMP2"</span><span
class="sym">)]</span>
<span class="kwa">class</span> <span class="clasMark">BMP2Processor</span> <span
class="sym">:</span> <span class="clasMark">ContentProcessor</span><span class="sym"><</span><span
class="clasMark">BMP2Content</span><span class="sym">,</span> <span class="clasMark">BMP2Content</span><span
class="sym">></span>
<span class="sym">{</span>
<span class="kwa">public override</span> <span class="clasMark">BMP2Content</span> <span
class="kwd">Process</span><span class="sym">(</span><span class="clasMark">BMP2Content</span> input<span
class="sym">,</span> <span class="clasMark">ContentProcessorContext</span> context<span
class="sym">)</span>
<span class="sym">{</span>
input<span class="sym">[</span>i<span class="sym">] = (</span><span class="clasMark">BMP2Content</span><span
class="sym">)</span>context<span class="sym">.</span>Convert<span class="sym"><</span><span
class="clasMark">TextureContent</span><span class="sym">,</span><span class="clasMark">TextureContent</span><span
class="sym">>(</span>
<span class="sym">(</span><span class="clasMark">TextureContent</span><span class="sym">)</span>input<span
class="sym">[</span>i<span class="sym">],</span>
<span class="stringMark">"SpriteTextureProcessor"</span><span class="sym">);</span>
<span class="kwa">return</span> input<span class="sym">;</span>
<span class="sym">}</span>
<span class="sym">}</span>
</pre>
<p class="Estilo14">
El atributo inicial tiene la misma funcionalidad que en el importer y es proveer
una pequeña descripcion del ContentProcessor para que aparezca en el IDE de Visual
Studio. Se llama al metodo context.Convert indicandole que debe usar el builting
processor <span class="Estilo21">SpriteTextureProcessor</span>, esto hara que la
informacion inherente a una textura 2d sea procesada de la manera habitual . Finalmente
se procede a crear el <span class="Estilo21">ContentTypeWriter</span>.</p>
<pre>
<span class="sym">[</span>ContentTypeWriter<span class="sym">]</span>
<span class="kwa">public class</span> <span class="clasMark">BMP2ContentWriter</span> <span
class="sym">:</span> <span class="clasMark">ContentTypeWriter</span><span class="sym"><</span><span
class="clasMark">BMP2Content</span><span class="sym">></span>
<span class="sym">{</span>
<span class="kwa">protected override</span> <span class="kwb">void</span> <span class="kwd">Write</span><span
class="sym">(</span><span class="clasMark">ContentWriter</span> output<span class="sym">,</span> <span
class="clasMark">BMP2Content</span> <span class="kwa">value</span><span class="sym">)</span>
<span class="sym">{</span>
<span class="slc">//Buffer para la informacion de la imagen</span>
<span class="kwb">byte</span><span class="sym">[]</span> pixelData<span class="sym">;</span>
<span class="slc">//Escribe alto y ancho</span>
output<span class="sym">.</span><span class="kwd">Write</span><span class="sym">(</span><span
class="kwa">value</span><span class="sym">.</span>Mipmaps<span class="sym">[</span><span
class="num">0</span><span class="sym">].</span>Height<span class="sym">);</span>
output<span class="sym">.</span><span class="kwd">Write</span><span class="sym">(</span><span
class="kwa">value</span><span class="sym">.</span>Mipmaps<span class="sym">[</span><span
class="num">0</span><span class="sym">].</span>Width<span class="sym">);</span>
<span class="slc">//Obtiene el contenido de la imagen</span>
pixelData <span class="sym">=</span> <span class="kwa">value</span><span class="sym">.</span>Mipmaps<span
class="sym">[</span><span class="num">0</span><span class="sym">].</span><span class="kwd">GetPixelData</span><span
class="sym">();</span>
<span class="slc">//Escribe el tamaño de datos de la imagen</span>
output<span class="sym">.</span><span class="kwd">Write</span><span class="sym">(</span>pixelData<span
class="sym">.</span>Length<span class="sym">);</span>
<span class="slc">//Escribe la informacion de la imagen</span>
output<span class="sym">.</span><span class="kwd">Write</span><span class="sym">(</span>pixelData<span
class="sym">);</span>
<span class="slc">//Escribe el color de mascara de la imagen</span>
output<span class="sym">.</span>WriteObject<span class="sym"><</span><span class="clasMark">Color</span><span
class="sym">>(</span><span class="kwa">value</span><span class="sym">.</span>MaskColor<span
class="sym">);</span>
<span class="sym">}</span>
<span class="kwa">public override</span> <span class="kwb">string</span> <span class="kwd">GetRuntimeReader</span><span
class="sym">(</span><span class="clasMark">TargetPlatform</span> targetPlatform<span
class="sym">)</span>
<span class="sym">{</span>
<span class="kwa">return</span> <span class="kwb">typeof</span><span class="sym">(</span><span
class="clasMark">BMP2ContentReader</span><span class="sym">).</span>AssemblyQualifiedName<span
class="sym">;</span>
<span class="sym">}</span>
<span class="sym">}</span>
</pre>
<p class="Estilo14">
El atributo inicial tiene la misma funcionalidad que en el importer. El método write
lo que hace es escribir en el archivo del CPL la informacion relacionada con el
archivo ya previamente cargado en el <span class="Estilo21">BMP2Content</span>,
el objeto output recibido como parametro posee metodos para escribir a nivel de
tipos nativos y soporta una amplia gama de tipos incluidos en el xna framework,
el método GetRuntimeReader Almacena informacion que le indica el CPL en tiempo dejecucion
que clase debe instanciar para poder convertir un archivo del CPL en el objeto que
se desea, es decir indica cual implementacion de <span class="Estilo21">ContentTypeReader</span>
debe utilizarce para tal fin. Esta es la implementacion de <span class="clasMark">ContentTypeReader</span>
para leer en tiempo de ejecucion lo que el ContentTypeWriter ha guardado en tiempo
de compilacion, el objeto input recibido como parametro posee metodos para leer
a nivel de tipos nativos y soporta una amplia gama de tipos incluidos en el xna
framework.</p>
<pre>
<span class="kwa">public class</span> <span class="Estilo13">BMP2ContentReader</span> <span
class="sym">:</span> <span class="Estilo13">ContentTypeReader</span><span class="sym"><</span>BMP2Texture2D<span
class="sym">></span>
<span class="sym">{</span>
<span class="kwa">protected override</span> <span class="Estilo13">BMP2Texture2D</span> <span
class="kwd">Read</span><span class="sym">(</span><span class="Estilo13">ContentReader</span> input<span
class="sym">,</span> <span class="Estilo13">BMP2Texture2D</span> existingInstance<span
class="sym">)</span>
<span class="sym">{</span>
<span class="slc">//Se obtiene el dispositivo grafico</span>
<span class="Estilo13">GraphicsDevice</span> graphics <span class="sym">= ((</span>IGraphicsDeviceService<span
class="sym">)</span>
input<span class="sym">.</span>ContentManager<span class="sym">.</span>ServiceProvider<span
class="sym">.</span><span class="kwd">GetService</span><span class="sym">(</span><span
class="kwb">typeof</span><span class="sym">(</span><span class="Estilo13">IGraphicsDeviceService</span><span
class="sym">))</span>
<span class="sym">).</span>GraphicsDevice<span class="sym">;</span>
<span class="slc">//Inicializa la instancia actual, lee el ancho y alto de la imagen</span>
existingInstance <span class="sym">=</span> <span class="kwa">new</span> <span class="Estilo13">BMP2Texture2D</span><span
class="sym">(</span>graphics<span class="sym">,</span>
input<span class="sym">.</span><span class="kwd">ReadInt32</span><span class="sym">(),</span> input<span
class="sym">.</span><span class="kwd">ReadInt32</span><span class="sym">(),</span>
<span class="num">1</span><span class="sym">,</span> <span class="Estilo13">ResourceUsage</span><span
class="sym">.</span>AutoGenerateMipMap<span class="sym">,</span> <span class="Estilo13">SurfaceFormat</span><span
class="sym">.</span>Color<span class="sym">);</span>
<span class="slc">//Establece el contenido de la imagen</span>
<span class="slc">//lee el tamaño de la informacion en bytes a leer</span>
<span class="slc">//y lee la informacion en bytes</span>
existingInstance<span class="sym">[</span>i<span class="sym">].</span>SetData<span
class="sym"><</span><span class="kwb">byte</span><span class="sym">>(</span>input<span
class="sym">.</span><span class="kwd">ReadBytes</span><span class="sym">(</span>input<span
class="sym">.</span><span class="kwd">ReadInt32</span><span class="sym">()));</span>
<span class="slc">//Establece el color de mascara</span>
existingInstance<span class="sym">[</span>i<span class="sym">].</span>maskColor <span
class="sym">=</span> input<span class="sym">.</span>ReadObject<span class="sym"><</span><span
class="Estilo13">Color</span><span class="sym">>();</span>
<span class="kwa">return</span> existingInstance<span class="sym">;</span>
<span class="sym">}</span>
<span class="sym">}</span>
</pre>
<p class="Estilo14">
Eso es todo, para hacerlo funcionar, se requiere compilar estas clases en una dll
la cual se debe adicionar al content pipeline, para hacer eso se debe ir a las propiedades
del proyecto y luego a la ultima pestaña la cual desde luego se llama Content Pipeline,
desde alli presionar el boton Add y seleccionar la dll creada. Para que desde el
juego se peuda cargar la informacion se debe incluir referencia por lo menos al
ensamblado donde se compilo el <span class="Estilo21">ContentTypeReader</span>.
En adelante tan solo se accede al recurso a travez de un content manager como se
hace de manera habitual:</p>
<pre>
<span class="clasMark">ContentManager</span> content<span class="sym">;</span>
<span class="sym">...</span>
<span class="sym">...</span>
<span class="sym">...</span>
<span class="clasMark">BMP2Texture</span> myTexture <span class="sym">=</span> content<span
class="sym">.</span>Load<span class="sym"><</span><span class="clasMark">BMP2Texture</span><span
class="sym">>(</span><span class="stringMark">@"myImage.bmp2"</span><span
class="sym">);</span></pre>
<p class="Estilo14">
Espero les sea de utilidad. Saludos.</p>
[/dohtml]