Utiliser le gestionnaire de contenu de SharpDX

Il y a peu de temps je vous parlais de SharpDX mais surtout de son toolkit dont l’API ressemble beaucoup à celle de XNA. Le gestionnaire de contenu du toolkit permet de charger des ressources de base (il faut spécifier l’extension de la ressource) ou optimisées dans un autre format (là le chargement se fait sans l’extension) via une étape de construction pendant la compilation du projet, comme c’est le cas avec un projet XNA qui va générer des fichiers xnb. Nous allons voir comment utiliser le gestionnaire de contenu dans un projet SharpDX, cela nous permettra d’utiliser des textures, des modèles 3D, des fonts et des effets !

Récupérer la dernière version

La première chose à faire va être de récupérer la dernière version de SharpDX, soit par Github (que vous devrez compiler) soit sur le site officiel en récupérant la version dev (il faut regarder sur la colonne de droite en bas), je vous recommande cette dernière solution et je me baserais dessus pour ce tutoriel. Lorsque vous avez terminé de télécharger l’archive il faut la décompresser car nous aurons besoin d’y récupérer quelques fichiers après la création du projet dans Visual Studio.

Création du projet dans Visual Studio

Vous pouvez utiliser la version que vous désirez de Visual Studio, ici j’utilise la 2012 Desktop express.

Création du projet
Création du projet

Lorsque le projet est prêt vous pouvez fermer Visual Studio car nous allons avoir besoin de faire quelques modifications sur le fichier de projet, mais avant ça il faut copier le dossier Bin/ et le fichier SharpDX.targets à la racine de votre projet, comme sur la capture suivante.

Copie des fichiers dans le projet
Copie des fichiers dans le projet

Nous passons maintenant à l’édition du fichier de projet SharpDXGame.csproj (je parle bien du fichier de projet et pas du fichier de solution). Ouvrez donc ce fichier avec votre éditeur de texte préféré (j’utilise Notepad++) et rendez vous à la fin du fichier, juste avant la balise Target Name= »BeforeBuild » et ajoutez y la balise suivante

<Import Project="..\SharpDX.targets" />

La fin de votre fichier de projet doit donc ressembler à ça

  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <Import Project="..\SharpDX.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>

Cette ligne de code indique au compilateur de Visual Studio qu’il faut importer le fichier SharpDX.targets avant de construire les sources. Vous pouvez consulter ce fichier si vous voulez (il faut être curieux dans la vie, surtout pour un programmeur, c’est important) et vous verrez qu’il contient des tâches permettant de construire les différentes ressources prises en charge par le gestionnaire de contenu. On pourrait se passer de cette étape et utiliser les outils de construction des ressources à la main, en console, mais vous imaginez devoir reconstruire toutes les ressources à la main à chaque fois qu’elles changent ? Surtout qu’il y a 4 programmes différents à exécuter (Modèle, SpriteFont, Image et Effet).

Vous pouvez rouvrir votre projet dans Visual Studio et ajouter les fichiers suivants en tant que référence :

  • SharpDX.dll
  • SharpDX.Direct3D11.dll
  • SharpDX.DXGI.dll
  • SharpDX.Toolkit.dll
  • SharpDX.Toolkit.Game.dll
  • SharpDX.Toolkit.Graphics.dll
  • SharpDX.Toolkit.Input.dll

Rappelez vous que ces fichiers sont stockés à la racine de votre projet dans le dossier Bin. J’utilise la version DirectX11-net40 mais vous pouvez utiliser tout autre version, suivant le type de projet que vous avez créé (Windows Phone, Windows ModernUI, etc…). Enfin la dernière étape consiste à créer un dossier Content dans votre projet à partir de Visual Studio, vous y mettrez toutes vos ressources à compiler, comme c’était le cas avec XNA.

Ajouter des ressources

Nous allons faire simple et ajouter une image de fond et un spriteFont afin d’écrire un petit message. Les SpriteFont peuvent être de plusieurs formats, je vous invite à consulter la documentation pour en savoir plus et je vous propose d’utiliser celui fournis avec les exemples du toolkit. Je vous le recopie ci-dessous, il est à enregistrer dans un fichier xml portant le nom que vous voulez.

Arial16.xml

<?xml version="1.0" encoding="utf-8"?>
<TkFont>
  <FontName>Arial</FontName>
  <Size>16</Size>
  <Spacing>0</Spacing>
  <LineSpacing>0</LineSpacing>
  <UseKerning>false</UseKerning>
  <Format>Auto</Format>
  <CharacterRegions>
    <CharacterRegion>
      <Start>32</Start>
      <End>127</End>
    </CharacterRegion>    
  </CharacterRegions>
  <DefaultCharacter>32</DefaultCharacter>
  <Style>Regular</Style>
  <NoPremultiply>false</NoPremultiply>
</TkFont>

Il faut le placer dans le dossier Content du projet, faites de même avec une image de fond au format PNG ou JPG. Je vous donne maintenant le code de base :

Program.cs

namespace SharpDXGame
{
    public class Program
    {
        public static void Main(string[] args)
        {
            using (var game = new MyGame())
                game.Run();
        }
    }
}

MyGame.cs

using SharpDX;
using SharpDX.Toolkit;
using SharpDX.Toolkit.Content;
using SharpDX.Toolkit.Graphics;
using SharpDX.Toolkit.Input;

namespace SharpDXGame
{
    public class MyGame : Game
    {
        protected GraphicsDeviceManager graphics;
        protected KeyboardManager keyboardManager;
        protected SpriteBatch spriteBatch;

        private SpriteFont spriteFont;
        private Texture2D image;

        public MyGame()
            : base()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            keyboardManager = new KeyboardManager(this);
            graphics.PreferredBackBufferWidth = 320;
            graphics.PreferredBackBufferHeight = 240;
        }

        protected override void Initialize()
        {
            Window.Title = "MySharpDXGame : Chargement de ressource";
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            spriteFont = Content.Load<SpriteFont>("Arial16");
            image = Content.Load<Texture2D>("background");
            base.LoadContent();
        }

        protected override void Update(GameTime gameTime)
        {
            if (keyboardManager.GetState().IsKeyDown(Keys.Escape))
                Exit();

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            spriteBatch.Begin();
            spriteBatch.Draw(image, Vector2.Zero, Color.White);
            spriteBatch.DrawString(spriteFont, "Utilisation d'un SpriteFont", new Vector2(40, 170), Color.Red);
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}

Si vous compilez maintenant votre projet tout se passera sans problème mais le programme ne se lancera pas correctement et vous aurez une belle exception, il faut effectivement spécifier pour chaque ressource son action de génération car ça n’est pas automatique (Un grand pouvoir implique de grande responsabilités et bien là c’est pareil, c’est à vous de faire le bon choix d’action). Pour cela c’est très simple il faut faire un clic droit sur la ressource et choisir propriétés, dans la fenêtre qui s’ouvre il faut choisir la bonne action suivant le type de ressource.

Pour l’image

Action de texture
Action de texture

Pour le SpriteFont

Action pour un spriteFont
Action pour un spriteFont

Maintenant vous pouvez compiler et lancer le projet et vous verrez votre image de fond avec du texte à l’écran. Si vous allez dans le dossier où a été généré l’exécutable vous verrez qu’un dossier Content a été automatiquement créé et que dedans s’y trouve deux fichiers au format tkb.

Conclusion

Vous savez maintenant comment mettre en œuvre un projet SharpDX et faire fonctionner le mécanisme de construction des ressources. J’espère que par la suite nous aurons des templates de projet tout prêts afin de ne pas être obligé de modifier le fichier de projet à la main. N’oubliez pas qu’il faut spécifier le type d’action pour chaque ressource, ça peut paraitre long mais sachez que vous pouvez sélectionner plusieurs ressources en même temps pour leur attribuer une action commune (à la tout de suite ça va déjà mieux 😉 ). Vous pouvez récupérer les sources du projet sur mon espace Github à cette adresse.