[GS 2.0]
Game Studio 2.0 beta has ended and Game Studio 2.0 has been officially released. There are breaking changes in the ContentPipeline.targets file, so I've updated the VBContentManager class to generate a Content.contentproj file that works within the new parameters. The usage of the class remains the same.
- Works with Game Studio 2.0
- Now outputs content to the appropriate Visual Studio bin location (i.e., bin\Debug or bin\Release, whichever you've set Visual Studio to)
Public Class VBContentManager
Inherits ContentManager
Public Fonts As Hashtable(Of SpriteFont)
Public Textures As Hashtable(Of Texture2D)
Public SubTextures As Hashtable(Of Hashtable(Of Rectangle))
Public Sounds As Hashtable(Of SoundBank)
Public Effects As Hashtable(Of Effect)
Private strContentprojFile, strProjectFolder, strExecutingFolder, strContentFolder As String
Private objContent As List(Of ContentFile)
Private intDupeSound, intDupeTexture, intDupeFont, intDupeEffect As Integer
Public Enum Platform
Windows
XBox360
End Enum
Public Enum ContentTypes
Textures = 0
Fonts = 1
Sounds = 2
Effects = 3
End Enum
Private Enum ImporterName
TextureImporter = 0
FontDescriptionImporter = 1
XactImporter = 2
EffectImporter = 3
End Enum
Private Enum ProcessorName
TextureProcessor = 0
FontDescriptionProcessor = 1
XactProcessor = 2
EffectProcessor = 3
End Enum
Public Structure ContentFile
Public ContentType As ContentTypes
Public File As System.IO.FileInfo
Public Name As String
Public Sub New(ByVal ContentType As ContentTypes, ByVal ContentFile As System.IO.FileInfo, ByVal Name As String)
Me.ContentType = ContentType
Me.File = ContentFile
Me.Name = Name
End Sub
End Structure
''' <summary>
''' Creates a new ContentManager which has been extended with functionality to support a Visual Basic (or other non-C#) project
''' </summary>
''' <param name="ServiceProvider">Your game has a .Services property; send that in here.</param>
''' <param name="ContentFolder">Your content folder (a relative path, from your game's Project node as it appears in the Solution Explorer)</param>
''' <remarks></remarks>
Public Sub New(ByVal ServiceProvider As IServiceProvider, ByVal ContentFolder As String)
MyBase.New(ServiceProvider)
With System.Reflection.Assembly.GetEntryAssembly.Location
Me.strExecutingFolder = .Substring(0, .LastIndexOf("\"))
End With
With Me.strExecutingFolder
With .Substring(0, .LastIndexOf("\") - 1)
Me.strProjectFolder = .Substring(0, .LastIndexOf("\"))
End With
End With
Me.strContentFolder = Me.strProjectFolder & "\" & ContentFolder
Me.Fonts = New Hashtable(Of SpriteFont)
Me.Textures = New Hashtable(Of Texture2D)
Me.SubTextures = New Hashtable(Of Hashtable(Of Rectangle))
Me.Sounds = New Hashtable(Of SoundBank)
Me.Effects = New Hashtable(Of Effect)
End Sub
''' <summary>
''' Attempts to load all assets which have been compiled by the Content Pipeline. Assets are placed into the respective Hash table (Fonts, Textures, et al)
''' </summary>
''' <remarks></remarks>
Public Sub LoadAllContent()
Dim objCompiledContent As New List(Of IO.FileInfo)
Dim strUnknownFiles As String = ""
For Each file As IO.FileInfo In New IO.DirectoryInfo(Me.strExecutingFolder).GetFiles("*.xnb", IO.SearchOption.AllDirectories)
Try
'Font?
With file.FullName.ToLower
Me.Fonts.Add(file.Name.Replace(file.Extension, ""), Me.Load(Of SpriteFont)(.Replace(Me.strExecutingFolder & "\", "").Replace(file.Extension, "")))
End With
Catch notAFont As Exception
Try
'Texture2D?
With file.FullName
Me.Textures.Add(file.Name.Replace(file.Extension, ""), Me.Load(Of Texture2D)(.Replace(Me.strExecutingFolder & "\", "").Replace(file.Extension, "")))
End With
'Is this a sheet w/ a rectangle map? If so, load the rectangle map
If IO.File.Exists(file.FullName.Replace(file.Extension, ".map")) Then
Me.LoadMap(file.Name.Replace(file.Extension, ""), file.FullName.Replace(file.Extension, ".map"))
End If
Catch notATexture2D As Exception
Try
'Sound?
With file.FullName.ToLower
Me.Sounds.Add(file.Name.Replace(file.Extension, ""), Me.Load(Of SoundBank)(.Replace(Me.strExecutingFolder & "\", "").Replace(file.Extension, "")))
End With
Catch notASoundBank As Exception
Try
'Effect?
With file.FullName.ToLower
Me.Effects.Add(file.Name.Replace(file.Extension, ""), Me.Load(Of Effect)(.Replace(Me.strExecutingFolder & "\", "").Replace(file.Extension, "")))
End With
Catch unknown As Exception
strUnknownFiles &= vbCrLf & file.FullName
End Try
End Try
End Try
End Try
Next
If strUnknownFiles <> "" Then
MsgBox("The VBContentManager was unable to determine the correct loader for:" & vbCrLf & _
strUnknownFiles & vbCrLf & vbCrLf & _
"Unless loaded by something else, the above content won't be available at runtime." & vbCrLf & vbCrLf & _
"This application may become unstable as a result.")
End If
End Sub
Private Sub LoadMap(ByVal strTextureNameName As String, ByVal strMapFile As String)
Dim objReader As IO.StreamReader
Dim strMapData As String
Dim strLine() As String
Dim strItem() As String
objReader = New IO.StreamReader(strMapFile)
Me.SubTextures.Add(strTextureNameName, New Hashtable(Of Rectangle))
strMapData = objReader.ReadToEnd
objReader.Close()
objReader.Dispose()
strLine = strMapData.Split(vbCrLf.ToCharArray, System.StringSplitOptions.RemoveEmptyEntries)
For Each strMapItem As String In strLine
strItem = strMapItem.Split(",".ToCharArray, System.StringSplitOptions.RemoveEmptyEntries)
Me.SubTextures(strTextureNameName).Add(strItem(0), New Rectangle(CInt(strItem(1)), CInt(strItem(2)), CInt(strItem(3)), CInt(strItem(4))))
Next
End Sub
''' <summary>
''' Compiles the VB Content Pipeline
''' </summary>
''' <param name="stealth">Hide/Show the MSBuild window during the compile process</param>
''' <param name="platform">If there's a way the Xbox360 will work with VB, you could pass in the Xbox parameter as a target platform to MSBuild. But it's Windows by default.</param>
''' <remarks></remarks>
Public Sub CompileContent(ByVal stealth As Boolean, Optional ByVal platform As Platform = VBContentManager.Platform.Windows)
Dim objProcess As Process
Dim objPSI As New Diagnostics.ProcessStartInfo
Me.objContent = New List(Of ContentFile)
Me.HarvestContent()
If Me.objContent.Count > 0 Then
Me.BuildContentProj(platform)
Try 'to write the content project file to disk
Using TempStreamWriter As System.IO.StreamWriter = New System.IO.StreamWriter(Me.strProjectFolder & "\Content.contentproj", False)
With TempStreamWriter
.Write(Me.strContentprojFile)
.Close()
End With
End Using
Try
With objPSI
.FileName = Environment.GetEnvironmentVariable("Windir") & "\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe"
.Arguments = """" & Me.strProjectFolder & "\Content.contentproj""" & _
" /verbosity:normal" & _
" /l:FileLogger,Microsoft.Build.Engine;logfile=""" & Me.strProjectFolder & "\Content.log"""
If stealth Then
.Arguments &= " /noconsolelogger"
.WindowStyle = ProcessWindowStyle.Hidden
End If
End With
'give the .contentproj file to MSBuild
objProcess = System.Diagnostics.Process.Start(objPSI)
While Not objProcess.HasExited
Threading.Thread.Sleep(100)
End While
Catch ex As Exception
MsgBox("When building the pipeline, trying to run MSBuild.exe resulted in: " & ex.Message)
End Try
Catch ex As Exception
MsgBox("When building the pipeline, trying to create the Content.contentproj file """ & Me.strProjectFolder & "\Content.contentproj"" resulted in: " & ex.Message)
End Try
End If
End Sub
Private Sub HarvestContent()
Dim objRoot As System.IO.DirectoryInfo = New System.IO.DirectoryInfo(Me.strContentFolder)
For Each sound As System.IO.FileInfo In objRoot.GetFiles("*.xab", IO.SearchOption.AllDirectories)
If Me.objContent.Contains(New ContentFile(ContentTypes.Sounds, sound, sound.Name.Replace(sound.Extension, ""))) Then
Me.intDupeSound += 1
Me.objContent.Add(New ContentFile(ContentTypes.Sounds, sound, sound.Name.Replace(sound.Extension, "") & Me.intDupeSound.ToString))
Else
Me.objContent.Add(New ContentFile(ContentTypes.Sounds, sound, sound.Name.Replace(sound.Extension, "")))
End If
Next
For Each texture As System.IO.FileInfo In objRoot.GetFiles("*.png", IO.SearchOption.AllDirectories)
If Me.objContent.Contains(New ContentFile(ContentTypes.Textures, texture, texture.Name.Replace(texture.Extension, ""))) Then
Me.intDupeTexture += 1
Me.objContent.Add(New ContentFile(ContentTypes.Textures, texture, texture.Name.Replace(texture.Extension, "") & Me.intDupeTexture.ToString))
Else
Me.objContent.Add(New ContentFile(ContentTypes.Textures, texture, texture.Name.Replace(texture.Extension, "")))
End If
Next
For Each texture As System.IO.FileInfo In objRoot.GetFiles("*.jpg", IO.SearchOption.AllDirectories)
If Me.objContent.Contains(New ContentFile(ContentTypes.Textures, texture, texture.Name.Replace(texture.Extension, ""))) Then
Me.intDupeTexture += 1
Me.objContent.Add(New ContentFile(ContentTypes.Textures, texture, texture.Name.Replace(texture.Extension, "") & Me.intDupeTexture.ToString))
Else
Me.objContent.Add(New ContentFile(ContentTypes.Textures, texture, texture.Name.Replace(texture.Extension, "")))
End If
Next
For Each texture As System.IO.FileInfo In objRoot.GetFiles("*.gif", IO.SearchOption.AllDirectories)
If Me.objContent.Contains(New ContentFile(ContentTypes.Textures, texture, texture.Name.Replace(texture.Extension, ""))) Then
Me.intDupeTexture += 1
Me.objContent.Add(New ContentFile(ContentTypes.Textures, texture, texture.Name.Replace(texture.Extension, "") & Me.intDupeTexture.ToString))
Else
Me.objContent.Add(New ContentFile(ContentTypes.Textures, texture, texture.Name.Replace(texture.Extension, "")))
End If
Next
For Each font As System.IO.FileInfo In objRoot.GetFiles("*.spritefont", IO.SearchOption.AllDirectories)
If Me.objContent.Contains(New ContentFile(ContentTypes.Fonts, font, font.Name.Replace(font.Extension, ""))) Then
Me.intDupeFont += 1
Me.objContent.Add(New ContentFile(ContentTypes.Fonts, font, font.Name.Replace(font.Extension, "") & Me.intDupeFont.ToString))
Else
Me.objContent.Add(New ContentFile(ContentTypes.Fonts, font, font.Name.Replace(font.Extension, "")))
End If
Next
For Each effect As System.IO.FileInfo In objRoot.GetFiles("*.fx", IO.SearchOption.AllDirectories)
If Me.objContent.Contains(New ContentFile(ContentTypes.Effects, effect, effect.Name.Replace(effect.Extension, ""))) Then
Me.intDupeEffect += 1
Me.objContent.Add(New ContentFile(ContentTypes.Effects, effect, effect.Name.Replace(effect.Extension, "") & Me.intDupeEffect.ToString))
Else
Me.objContent.Add(New ContentFile(ContentTypes.Effects, effect, effect.Name.Replace(effect.Extension, "")))
End If
Next
End Sub
Private Sub BuildContentProj(ByVal platform As Platform)
Dim strPlatform As String
Select Case platform
Case VBContentManager.Platform.XBox360
strPlatform = "Xbox 360"
Case Else
strPlatform = "Windows"
End Select
Me.strContentprojFile = _
"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">" & vbCrLf & _
vbTab & "<Import Project=""$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\v2.0\Microsoft.Xna.GameStudio.ContentPipeline.targets"" />" & vbCrLf & _
vbTab & "<PropertyGroup>" & vbCrLf & _
vbTab & vbTab & "<OutputType>Library</OutputType>" & vbCrLf & _
vbTab & vbTab & "<XnaFrameworkVersion>v2.0</XnaFrameworkVersion>" & vbCrLf & _
vbTab & vbTab & "<ProjectDir>" & Me.strProjectFolder & "\</ProjectDir>" & vbCrLf & _
vbTab & vbTab & "<ParentOutputDir>" & Me.strExecutingFolder & "</ParentOutputDir>" & vbCrLf & _
vbTab & vbTab & "<ContentRootDirectory>\</ContentRootDirectory>" & vbCrLf & _
vbTab & vbTab & "<XNAContentPipelineTargetPlatform>" & strPlatform & "</XNAContentPipelineTargetPlatform>" & vbCrLf & _
vbTab & vbTab & "<OutputPath>" & Me.strExecutingFolder & "\</OutputPath>" & vbCrLf & _
vbTab & vbTab & "<OutputDirectory>" & Me.strExecutingFolder & "\</OutputDirectory>" & vbCrLf & _
vbTab & "</PropertyGroup>" & vbCrLf & _
vbTab & "<ItemGroup>" & vbCrLf & _
vbTab & vbTab & "<Reference Include=""Microsoft.Xna.Framework.Content.Pipeline.EffectImporter, Version=2.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d, processorArchitecture=MSIL"" />" & vbCrLf & _
vbTab & vbTab & "<Reference Include=""Microsoft.Xna.Framework.Content.Pipeline.FBXImporter, Version=2.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d, processorArchitecture=MSIL"" />" & vbCrLf & _
vbTab & vbTab & "<Reference Include=""Microsoft.Xna.Framework.Content.Pipeline.TextureImporter, Version=2.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d, processorArchitecture=MSIL"" />" & vbCrLf & _
vbTab & vbTab & "<Reference Include=""Microsoft.Xna.Framework.Content.Pipeline.XImporter, Version=2.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d, processorArchitecture=MSIL"" />" & vbCrLf & _
vbTab & "</ItemGroup>"
For Each content As ContentFile In Me.objContent
Me.strContentprojFile &= vbCrLf & _
vbTab & "<ItemGroup>" & vbCrLf & _
vbTab & vbTab & "<Compile Include=""" & content.File.FullName & """>" & vbCrLf & _
vbTab & vbTab & vbTab & "<Name>" & content.Name & "</Name>" & vbCrLf & _
vbTab & vbTab & vbTab & "<Importer>" & CType(content.ContentType, ImporterName).ToString & "</Importer>" & vbCrLf & _
vbTab & vbTab & vbTab & "<Processor>" & CType(content.ContentType, ProcessorName).ToString & "</Processor>" & vbCrLf & _
vbTab & vbTab & "</Compile>" & vbCrLf & _
vbTab & "</ItemGroup>"
If content.ContentType = ContentTypes.Textures Then
'If this texture is a sheet w/ a map, copy it's map out in the executable area
'along side the existing or eventual compiled texture
If IO.File.Exists(content.File.FullName.Replace(content.File.Extension, ".map")) Then
Try
IO.File.Copy(content.File.FullName.Replace(content.File.Extension, ".map"), _
Me.strExecutingFolder & content.File.FullName.Replace(Me.strProjectFolder, "").Replace(content.File.Extension, ".map"), True)
Catch ex As Exception
'I'm going to be optimistic and assume that if I can't copy
'it's because the file is already there, and life is just fine
End Try
End If
End If
Next
Me.strContentprojFile &= vbCrLf & vbTab & "<!-- To modify your build process, add your task inside one of the targets below and uncomment it. " & vbCrLf & _
vbTab & " Other similar extension points exist, see Microsoft.Common.targets." & vbCrLf & _
vbTab & "<Target Name=""BeforeBuild"">" & vbCrLf & _
vbTab & "</Target>" & vbCrLf & _
vbTab & "<Target Name=""AfterBuild"">" & vbCrLf & _
vbTab & "</Target>" & vbCrLf & _
vbTab & "-->" & vbCrLf & _
"</Project>"
End Sub
End Class
0 comments:
Post a Comment