TX2D 3.0.0.0 GUIVideo resource
by Jason Cahill · 07/19/2009 (11:24 am) · 4 comments
Installation:
Convert your project to XNA 3.1 by right-clicking on your Torque projects (Game, TorqueCore, and Torque2D) and convert to XNA 3.1. XNA 3.1 is required for video support.Here are the two new source files you need to add to your project:
TorqueCore\GUI\GUIVideo.cs
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Media;
using GarageGames.Torque.Core;
using GarageGames.Torque.GFX;
using GarageGames.Torque.MathUtil;
using GarageGames.Torque.Materials;
using GarageGames.Torque.Util;
namespace GarageGames.Torque.GUI
{
/// <summary>
/// The style properties for the GUIVideo control.
/// </summary>
public class GUIVideoStyle : GUIStyle
{
//======================================================
#region Public properties, operators, constants, and enums
/// <summary>
/// Whether the GUIVideo control should resize itself to the same
/// dimensions of the specified bitmap.
/// </summary>
public bool SizeToBitmap
{
get { return _sizeToBitmap; }
set { _sizeToBitmap = value; }
}
#endregion
//======================================================
#region Private, protected, internal fields
bool _sizeToBitmap = true;
#endregion
}
/// <summary>
/// Draws an image to the GUICanvas.
/// </summary>
public class GUIVideo : GUIControl
{
//======================================================
#region Public properties, operators, constants, and enums
/// <summary>
/// The image file to render to the screen.
/// </summary>
public string Bitmap
{
get { return _bitmapName; }
set
{
_bitmapName = value;
if (_bitmapName != String.Empty)
{
if (_material != null)
_material.Dispose();
_material = new Materials.VideoMaterial();
_material.TextureFilename = _bitmapName;
_material.IsTranslucent = true;
_material.IsColorBlended = true;
_material.IsLooped = _isLooped;
// rdbnote: the render material should really handle this for me
Texture2D texture = (Texture2D)(_material.Texture.Instance);
_material.Stop();
_bitmapSize = new Vector2(texture.Width, texture.Height);
if (_style != null && _style.SizeToBitmap)
Size = _bitmapSize;
}
else
{
if (_material != null)
_material.Dispose();
_material = null;
}
}
}
/// <summary>
/// The opacity of the bitmap. 1.0f is fully visible. 0.0f is fully transparent.
/// </summary>
public float Opacity
{
get { return _opacity; }
set { _opacity = value; }
}
public bool IsLooped
{
get { return _isLooped; }
set { _isLooped = value; if (_material != null) _material.IsLooped = value; }
}
#endregion
//======================================================
#region Public methods
public void Play()
{
_material.Play();
}
public void Stop()
{
_material.Stop();
}
public void Pause()
{
_material.Pause();
}
public void Resume()
{
_material.Resume();
}
public override void OnRender(Vector2 offset, RectangleF updateRect)
{
Profiler.Instance.StartBlock("GUIVideo.OnRender");
// clear bitmap modulation
DrawUtil.ClearBitmapModulation();
RectangleF ctrlRect = new RectangleF(offset, _bounds.Extent);
// fill in, if appropriate
if (_style.IsOpaque)
DrawUtil.RectFill(ctrlRect, _style.FillColor[CustomColor.ColorBase]);
// set the opacity of the material
_material.Opacity = _opacity;
if (_material != null)
{
// draw the bitmap
DrawUtil.BitmapStretch(_material, ctrlRect, BitmapFlip.None);
}
// draw a border, if appropriate
if (_style.HasBorder)
DrawUtil.Rect(ctrlRect, _style.BorderColor[CustomColor.ColorBase]);
Profiler.Instance.EndBlock("GUIVideo.OnRender");
// render the child controls
_RenderChildControls(offset, updateRect);
}
public override void CopyTo(TorqueObject obj)
{
base.CopyTo(obj);
GUIVideo obj2 = (GUIVideo)obj;
obj2.Bitmap = Bitmap;
}
#endregion
//======================================================
#region Private, protected, internal methods
protected override bool _OnNewStyle(GUIStyle style)
{
_style = (style as GUIVideoStyle);
Assert.Fatal(_style != null, "GUIVideo._OnNewStyle - Control was assigned an invalid style!");
if (_style == null || !base._OnNewStyle(style))
return false;
if (_style.SizeToBitmap && _material != null)
Size = new Vector2(_bitmapSize.X, _bitmapSize.Y);
return true;
}
#endregion
//======================================================
#region Private, protected, internal fields
string _bitmapName = String.Empty;
Materials.VideoMaterial _material = null;
float _opacity = 1.0f;
bool _isLooped = true;
Vector2 _bitmapSize;
GUIVideoStyle _style = null;
#endregion
}
}TorqueCore\Materials\VideoMaterial.cs
using System;
using System.Collections.Generic;
using System.Text;
using GarageGames.Torque.Core;
using GarageGames.Torque.SceneGraph;
using GarageGames.Torque.RenderManager;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Media;
namespace GarageGames.Torque.Materials
{
/// <summary>
/// Extremely basic material that simply renders a texture or solid color.
///
/// Parameters
///
/// worldViewProjection: the world space to screen space matrix
/// baseTexture: the texture
/// opacity: visibility level from 0 (invisible) to 1 (opaque)
///
/// Techniques
///
/// CopyTechnique: IsCopyPass true
/// TexturedTechnique: Texture set and IsColorBlended false
/// ColorTextureBlendTechnique: Texture set and IsColorBlended true
/// ColoredTechnique: Texture not set
/// </summary>
public class VideoMaterial : RenderMaterial, ITextureMaterial
{
//======================================================
#region Constructors
public VideoMaterial()
{
EffectFilename = "SimpleEffect";
}
#endregion
//======================================================
#region Public properties, operators, constants, and enums
/// <summary>
/// The filename of the texture to use.
/// </summary>
public string TextureFilename
{
get { return _textureFilename; }
set { _textureFilename = value; }
}
/// <summary>
/// The opacity to render at.
/// </summary>
public float Opacity
{
get { return _opacity; }
set { _opacity = value; }
}
public bool IsLooped
{
get { return _isLooped; }
set { _isLooped = value; }
}
/// <summary>
/// Whether or not to blend the color with the texture. The color is read from
/// the vertex data.
/// </summary>
public bool IsColorBlended
{
get { return _isColorBlended; }
set { _isColorBlended = value; }
}
/// <summary>
/// Whether or not this is a copy pass. A copy pass will not use any filtering
/// when sampling textures.
/// </summary>
public bool IsCopyPass
{
get { return _isCopyPass; }
set { _isCopyPass = value; }
}
/// <summary>
/// The texture object loaded from TextureFilename.
/// </summary>
public Resource<Texture> Texture
{
get
{
if (_isInvalid && !string.IsNullOrEmpty(_textureFilename))
{
_video = ResourceManager.Instance.GlobalContentManager.Load<Video>(_textureFilename);
_videoPlayer = new VideoPlayer();
_videoPlayer.Play(_video);
_texture = ResourceManager.Instance.CreateResource<Texture>(_videoPlayer.GetTexture());
_isInvalid = false;
}
_videoPlayer.IsLooped = _isLooped;
_videoPlayer.GetTexture();
return _texture;
}
}
#endregion
//======================================================
#region Public methods
/// <summary>
/// Sets the texture directly on the material, rather than looking it up from TextureFilename.
/// </summary>
/// <param name="texture"></param>
public void SetTexture(Texture texture)
{
_texture = ResourceManager.Instance.CreateResource<Texture>(texture);
_textureFilename = string.Empty;
}
public override void Dispose()
{
_texture.Invalidate();
base.Dispose();
}
public void Play()
{
_videoPlayer.Play(_video);
}
public void Stop()
{
_videoPlayer.Stop();
}
public void Pause()
{
_videoPlayer.Pause();
}
public void Resume()
{
_videoPlayer.Resume();
}
#endregion
//======================================================
#region Private, protected, internal methods
protected override string _SetupEffect(SceneRenderState srs, MaterialInstanceData materialData)
{
if ((_texture.IsNull || _texture.IsInvalid) && !string.IsNullOrEmpty(_textureFilename))
_texture = ResourceManager.Instance.LoadTexture(_textureFilename);
if (_isCopyPass)
return "CopyTechnique";
if (!_texture.IsNull)
{
if (_isColorBlended)
return "ColorTextureBlendTechnique";
return "TexturedTechnique";
}
return "ColoredTechnique";
}
protected override void _SetupGlobalParameters(SceneRenderState srs, MaterialInstanceData materialData)
{
base._SetupGlobalParameters(srs, materialData);
if (!_texture.IsNull)
EffectManager.SetParameter(_baseTextureParameter, Texture.Instance);
}
protected override void _SetupObjectParameters(RenderInstance renderInstance, SceneRenderState srs)
{
base._SetupObjectParameters(renderInstance, srs);
EffectManager.SetParameter(_worldViewProjectionParameter, renderInstance.ObjectTransform * srs.View * srs.Projection);
if (IsTranslucent)
EffectManager.SetParameter(_opacityParameter, renderInstance.Opacity * _opacity);
}
protected override void _LoadParameters()
{
base._LoadParameters();
_worldViewProjectionParameter = EffectManager.GetParameter(Effect, "worldViewProjection");
_baseTextureParameter = EffectManager.GetParameter(Effect, "baseTexture");
_opacityParameter = EffectManager.GetParameter(Effect, "opacity");
}
protected override void _ClearParameters()
{
_worldViewProjectionParameter = null;
_baseTextureParameter = null;
_opacityParameter = null;
base._ClearParameters();
}
#endregion
//======================================================
#region Private, protected, internal fields
float _opacity = 1.0f;
bool _isColorBlended = false;
bool _isCopyPass = false;
string _textureFilename = string.Empty;
Resource<Texture> _texture;
bool _isInvalid = true;
bool _isLooped = true;
Video _video = null;
VideoPlayer _videoPlayer = null;
EffectParameter _worldViewProjectionParameter;
EffectParameter _baseTextureParameter;
EffectParameter _opacityParameter;
#endregion
}
}In Visual Studio, ensure these files are included in your project.
Add the following lines of source code to TorqueCore\Core\XML\TorqueSceneData.cs (near line 297):
_defaultTypeMap.Add("GUIVideo", typeof(Torque.GUI.GUIVideo));
_defaultTypeMap.Add("GUIVideoStyle", typeof(Torque.GUI.GUIVideoStyle));Perform a build. You should not get any warnings or errors from this code.
Adding Video to your Game:
Per the instructions included with XNA 3.1, you must create WMV files with CBR for both the audio and video stream. You must have BOTH and audio and video stream for this to work. I used Microsoft Expression Encoder 2.0 to convert a clip from a DVD from MPEG-2 to WMV with CBR (as opposed to the default VBR).Once you have a video that meets these requirements, put it in your Gamedataimages folder, and include it in your project. Make sure it's in the Content (data) part of your Visual Studio project with:
* Build Action: Compile
* Content Importer: WMV Video File - XNA Framework
* Content Processor: Video - XNA Framework
* Copy to Output Directory: Do not copy
Adding a GUIVideo control:
In your .gui file, you need to create two things: a GUIVideoStyle (based on GUIBitmapStyle) and a GUIVideo control. Here's a sample of each:<GUIVideoStyle name="VideoStyle">
<SizeToBitmap>false</SizeToBitmap>
<PreserveAspectRatio>false</PreserveAspectRatio>
</GUIVideoStyle>
<GUIVideo name="Video">
<Style nameRef="VideoStyle"/>
<Bitmap>dataimagesBSG</Bitmap>
<IsLooped>false</IsLooped>
<Position>
<X>214</X>
<Y>10</Y>
</Position>
<Size>
<X>852</X>
<Y>480</Y>
</Size>
<HorizSizing>Width</HorizSizing>
<VertSizing>Height</VertSizing>
</GUIVideo>Making the video play:
In my Game.cs file, I added the following lines to BeginRun(){
SceneLoader.Load(@"data\ui\MenuScreen.gui");
GUICanvas.Instance.SetContentControl("MenuScreen");
int keyboardId = InputManager.Instance.FindDevice("keyboard");
GarageGames.Torque.Sim.InputMap.Global.BindAction(keyboardId, (int)Microsoft.Xna.Framework.Input.Keys.G, _playVideo);
GarageGames.Torque.Sim.InputMap.Global.BindAction(keyboardId, (int)Microsoft.Xna.Framework.Input.Keys.P, _pauseVideo);
GarageGames.Torque.Sim.InputMap.Global.BindAction(keyboardId, (int)Microsoft.Xna.Framework.Input.Keys.R, _resumeVideo);
GarageGames.Torque.Sim.InputMap.Global.BindAction(keyboardId, (int)Microsoft.Xna.Framework.Input.Keys.S, _stopVideo);
}Then, I defined the following four functions, also in my Game.cs:
private void _playVideo(float val)
{
if (val != 0)
{
GUIVideo gv = TorqueObjectDatabase.Instance.FindObject<GUIVideo>("Video");
gv.Play();
}
}
private void _pauseVideo(float val)
{
if (val != 0)
{
GUIVideo gv = TorqueObjectDatabase.Instance.FindObject<GUIVideo>("Video");
gv.Pause();
}
}
private void _resumeVideo(float val)
{
if (val != 0)
{
GUIVideo gv = TorqueObjectDatabase.Instance.FindObject<GUIVideo>("Video");
gv.Resume();
}
}
private void _stopVideo(float val)
{
if (val != 0)
{
GUIVideo gv = TorqueObjectDatabase.Instance.FindObject<GUIVideo>("Video");
gv.Stop();
}
}Legalese
I grant perpetual, royalty-free use of this code to anyone for any purpose, indie or commercial. I make no warranty or guarantees on this code and it is provided AS IS and WITH ALL FLAWS. I grant GarageGames full use of this source code for inclusion in a future release of Torque X.About the author
#3
One question for you.
I created a GuiMainMenu class that inherits from GUIVideo
In order to unload the video from memory I'm assuming I can just call this.Stop();
Then Set my GuiMainMenu to null?
The reason I ask is I found that the video kept playing (I could hear it) even after setting the file to null. So I assume a reference is kept in the code somewhere.
Just wanted to verify that calling stop will free up the memory. Thanks!
07/23/2009 (6:57 pm)
Hi Jason. Thanks for uploading this resource. It saved me tons of time and is implemented 100 times better then I would have done so myself.One question for you.
I created a GuiMainMenu class that inherits from GUIVideo
In order to unload the video from memory I'm assuming I can just call this.Stop();
Then Set my GuiMainMenu to null?
The reason I ask is I found that the video kept playing (I could hear it) even after setting the file to null. So I assume a reference is kept in the code somewhere.
Just wanted to verify that calling stop will free up the memory. Thanks!
#4
On the Xbox though I'm having 2 issues.
1)It dosn't play the video (I think 3.1 isn't on xbox yet am I correct?)
2) I can't exit my game on the xbox it just locks up. Having my GUIMainMenu inherit from GUIBitmap and call a bitmap rather then a video fixes this.
Any ideas?
07/23/2009 (8:09 pm)
Actually one other thing. This is working great on the pc.On the Xbox though I'm having 2 issues.
1)It dosn't play the video (I think 3.1 isn't on xbox yet am I correct?)
2) I can't exit my game on the xbox it just locks up. Having my GUIMainMenu inherit from GUIBitmap and call a bitmap rather then a video fixes this.
Any ideas?

Torque Owner Brian
Brian