#region CPL License
/*
Nuclex Framework
Copyright (C) 2002-2009 Nuclex Development Labs
This library is free software; you can redistribute it and/or
modify it under the terms of the IBM Common Public License as
published by the IBM Corporation; either version 1.0 of the
License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
IBM Common Public License for more details.
You should have received a copy of the IBM Common Public
License along with this library
*/
#endregion
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Nuclex.Graphics {
/// Drawable object that monitors the GraphicsDeviceService
public abstract class Drawable : IDisposable {
/// Initializes a new drawable object.
///
/// Graphics device this drawable object will be bound to
///
public Drawable(IGraphicsDeviceService graphicsDeviceService) {
// Remember the graphics device service for later
this.graphicsDeviceService = graphicsDeviceService;
this.deviceCreatedDelegate = new EventHandler(deviceCreated);
this.deviceResettingDelegate = new EventHandler(deviceResetting);
this.deviceResetDelegate = new EventHandler(deviceReset);
this.deviceDisposingDelegate = new EventHandler(deviceDisposing);
// Register to the graphics device events
subscribeToGraphicsDeviceService();
}
/// Immediately releases all resources owned by this instance
///
/// This method is not suitable for being called during a GC run, it is intended
/// for manual usage when you actually want to get rid of the Drawable object.
///
public virtual void Dispose() {
// Unsubscribe from the graphics device service's events
if(this.graphicsDeviceService != null) {
unsubscribeFromGraphicsDeviceService();
this.graphicsDeviceService = null;
}
}
/// Called when the Drawable should draw itself.
/// Provides a snapshot of the game's timing values
public virtual void Draw(GameTime gameTime) { }
/// GraphicsDevice this component is bound to.
public GraphicsDevice GraphicsDevice {
get { return this.graphicsDeviceService.GraphicsDevice; }
}
/// Retrieves the graphics device service from a service provider.
/// Service provider to look in
/// The graphics device service, if it was available
///
/// This method is included in the Drawable class to allow deriving classes
/// to expect an IServerProvider as their constructor argument and still
/// initialize Drawable, their base class, with a graphics device service.
///
///
/// public class MyDrawable : Drawable {
///
/// public MyDrawable(IServiceProvider serviceProvider) :
/// base(GetGraphicsDeviceService(serviceProvider)) { }
///
/// }
///
///
///
protected static IGraphicsDeviceService GetGraphicsDeviceService(
IServiceProvider serviceProvider
) {
IGraphicsDeviceService graphicsDeviceService = serviceProvider.GetService(
typeof(IGraphicsDeviceService)
) as IGraphicsDeviceService;
if(graphicsDeviceService == null)
throw new InvalidOperationException("Graphics device service not found");
return graphicsDeviceService;
}
/// Graphics device service the drawable was constucted on
protected IGraphicsDeviceService GraphicsDeviceService {
get { return this.graphicsDeviceService; }
}
///
/// Called when the object needs to set up graphics resources. Override to
/// set up any object specific graphics resources.
///
///
/// True if all graphics resources need to be set up; false if only
/// manual resources need to be set up.
///
[
Obsolete(
"The LoadGraphicsContent method is obsolete and will be removed in the future. " +
"Use the LoadContent method instead."
)
]
protected virtual void LoadGraphicsContent(bool createAllContent) { }
///
/// Called when graphics resources need to be loaded. Override this method to load
/// any game-specific graphics resources.
///
protected virtual void LoadContent() { }
///
/// Called when graphics resources should be released. Override to
/// handle component specific graphics resources.
///
///
/// True if all graphics resources should be released; false if only
/// manual resources should be released.
///
[
Obsolete(
"The UnloadGraphicsContent method is obsolete and will be removed in the future. " +
"Use the UnloadContent method instead."
)
]
protected virtual void UnloadGraphicsContent(bool destroyAllContent) { }
///
/// Called when graphics resources need to be unloaded. Override this method to unload
/// any game-specific graphics resources.
///
protected virtual void UnloadContent() { }
///
/// Subscribes this component to the events of the graphics device service.
///
private void subscribeToGraphicsDeviceService() {
// Register to the events of the graphics device service so we know when
// the graphics device is set up, shut down or reset.
this.graphicsDeviceService.DeviceCreated += this.deviceCreatedDelegate;
this.graphicsDeviceService.DeviceResetting += this.deviceResettingDelegate;
this.graphicsDeviceService.DeviceReset += this.deviceResetDelegate;
this.graphicsDeviceService.DeviceDisposing += this.deviceDisposingDelegate;
// If a graphics device has already been created, we need to simulate the
// DeviceCreated event that we did miss because we weren't born yet :)
if(this.graphicsDeviceService.GraphicsDevice != null) {
#pragma warning disable 618 // Call to obsolete method
LoadGraphicsContent(true);
#pragma warning restore 618 // Call to obsolete method
LoadContent();
}
}
///
/// Unsubscribes this component from the events of the graphics device service.
///
private void unsubscribeFromGraphicsDeviceService() {
// Unsubscribe from the events again
this.graphicsDeviceService.DeviceCreated -= new EventHandler(deviceCreated);
this.graphicsDeviceService.DeviceResetting -= new EventHandler(deviceResetting);
this.graphicsDeviceService.DeviceReset -= new EventHandler(deviceReset);
this.graphicsDeviceService.DeviceDisposing -= new EventHandler(deviceDisposing);
// If the graphics device is still active, we give the component a chance
// to clean up its data
if(this.graphicsDeviceService.GraphicsDevice != null) {
#pragma warning disable 618 // Call to obsolete method
UnloadGraphicsContent(true);
#pragma warning restore 618 // Call to obsolete method
UnloadContent();
}
}
/// Called when the graphics device is created
/// Graphics device service that created a new device
/// Not used
private void deviceCreated(object sender, EventArgs arguments) {
#pragma warning disable 618 // Call to obsolete method
LoadGraphicsContent(true);
#pragma warning restore 618 // Call to obsolete method
LoadContent();
}
/// Called before the graphics device is being reset
/// Graphics device service that is resetting its device
/// Not used
private void deviceResetting(object sender, EventArgs arguments) {
#pragma warning disable 618 // Call to obsolete method
UnloadGraphicsContent(false);
#pragma warning restore 618 // Call to obsolete method
}
/// Called after the graphics device has been reset
/// Graphics device service that has just reset its device
/// Not used
private void deviceReset(object sender, EventArgs arguments) {
#pragma warning disable 618 // Call to obsolete method
LoadGraphicsContent(false);
#pragma warning restore 618 // Call to obsolete method
}
/// Called before the graphics device is being disposed
/// Graphics device service that's disposing the device
/// Not used
private void deviceDisposing(object sender, EventArgs arguments) {
#pragma warning disable 618 // Call to obsolete method
UnloadGraphicsContent(true);
#pragma warning restore 618 // Call to obsolete method
UnloadContent();
}
/// Graphics device service this component is bound to.
private IGraphicsDeviceService graphicsDeviceService;
/// Delegate for the deviceCreated() method
private EventHandler deviceCreatedDelegate;
/// Delegate for the deviceResetting() method
private EventHandler deviceResettingDelegate;
/// Delegate for the deviceReset() method
private EventHandler deviceResetDelegate;
/// Delegate for the deviceDisposing() method
private EventHandler deviceDisposingDelegate;
}
} // namespace Nuclex.Graphics