#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