using System; using System.Collections.Generic; using System.ComponentModel; //using System.Drawing; using System.Data; using System.Text; using System.Xml; using System.Windows.Forms; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework; using Nuclex; using DarkWynter.Engine.Controllers; namespace OperationDrawDown { public partial class Engine : Nuclex.GameControl { public static Engine _self; // Set up a Game Mode to switch controller types with. public enum GameMode { Menu, Game }; public static GameMode gameMode; public enum EditMode { Copy, Move, Draw, Erase}; public static EditMode editMode; public delegate void EngineUpdate(); public static event EngineUpdate engineUpdate; public static SpriteBatch spriteBatch; public static ContentManager content; public static Cell selectedTileBrush; private SceneGraph sceneGraph; public Player player; SelectionRectangle rectangleA; SelectionRectangle rectangleB; bool isMouseSelecting = false; bool isSelectionMoving = false; bool isMouseDrawing = false; ControllerManager controllerManager; List args = new List(); public Engine() { InitializeComponent(); // Self-publishing Singleton Pattern. // Engine publishes it's control functions via static handles visible from any UserControl. // These Static Control functions access local Engine variables as if via pointer. // In code, just substitute "Engine._self" for "this" to promote a local variable to static access. // eg - "this.sceneGraph.Update(.01);" is promoted to "Engine._self.sceneGraph.Update(.01);" Engine._self = this; } protected override void Initialize() { sceneGraph = new SceneGraph(); player = new Player(); content = new ContentManager(Services); content.RootDirectory = "Content"; spriteBatch = new SpriteBatch(this.graphics.GraphicsDevice); editMode = EditMode.Draw; rectangleA = new SelectionRectangle(); rectangleA.Color_Set(0.0f, 1.0f, 0.0f, 0.5f); rectangleB = new SelectionRectangle(); rectangleB.Color_Set(1.0f, 0.0f, 0.0f, 0.5f); LoadScene("_xml/Level1.xml"); gameMode = GameMode.Game; // Create a List of Child Controllers List controllerTypes = new List(); controllerTypes.Add(typeof(PlayerController)); // Pass in Width and Height used by mouse. controllerManager = new ControllerManager( graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height, controllerTypes ); // Pass "this" as EventArgs to Conroller delegates functions args.Add(this); base.Initialize(); } private void LoadScene(string xmlHotZoneFilePath) { XmlDocument reader = new XmlDocument(); reader.Load(xmlHotZoneFilePath); foreach (XmlNode hotZoneNode in reader.ChildNodes) { if (hotZoneNode.Name == "HotZone") { // Get World Scale Cell.scale = int.Parse(hotZoneNode.Attributes["glyphPixelScale"].Value); // Unpack Content/Assets foreach (XmlNode node in hotZoneNode.ChildNodes) { if (node.Name == "SceneGraph") { // Create SceneGraph sceneGraph.Load(node); } else if (node.Name == "Players") { // Create List of Actors player.Load(node); } } } } } protected override void Update(Microsoft.Xna.Framework.GameTime gameTime) { // Trigger Update Event... // UserControls should subscribe if they need to update their displays. if (Engine.engineUpdate != null) Engine.engineUpdate(); // Checks if any controllers Added or Removed controllerManager.Update(); // Update Appropriate Controller if (gameMode == GameMode.Menu) { //// Update all MenuControllers //List controllers = controllerManager.GetControllers(typeof(MenuController)); //for (int i = 0; i < controllers.Count; i++) //{ // controllers[i].Update(ref args); //} } if (gameMode == GameMode.Game) { // Update all GameControllers List controllers = controllerManager.GetControllers(typeof(PlayerController)); for (int i = 0; i < controllers.Count; i++) { controllers[i].Update(ref args); } } base.Update(gameTime); } protected override void Draw(Microsoft.Xna.Framework.GameTime gameTime) { graphics.GraphicsDevice.Clear(Microsoft.Xna.Framework.Graphics.Color.Black); Viewport viewport = graphics.GraphicsDevice.Viewport; if (Engine.gameMode == GameMode.Menu) { // Title Menu } else if (Engine.gameMode == GameMode.Game) { Engine.spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None); sceneGraph.Draw(); player.Draw(); rectangleA.Draw(); rectangleB.Draw(); Engine.spriteBatch.End(); } base.Draw(gameTime); } private void MouseDown_Click(object sender, MouseEventArgs args) { // Left Mouse Button // Handle Drawing and Rectangle Selection Events; if (args.Button == MouseButtons.Left) { if (Engine.editMode == EditMode.Draw || Engine.editMode == EditMode.Erase) { Engine.PaintBrushSelectedCell(args.X, args.Y); // Signal MouseMove that user is drawing. this.isMouseDrawing = true; } else { // Inside/Outside Bounding Region if (this.rectangleA.Contains(args.X, args.Y)) { // Init Rectangle B at Rectangle A's location this.rectangleB.SetStartPoint(this.rectangleA.StartX, this.rectangleA.StartY); this.rectangleB.SetEndPoint(this.rectangleA.EndX, this.rectangleA.EndY); // Signal MouseUp that user is moving/copying blocks. this.isSelectionMoving = true; } else { // Set Rectangle Start Point. this.rectangleA.SetStartPoint(args.X, args.Y); this.rectangleA.SetEndPoint(args.X, args.Y); // Hide Rectangle B this.rectangleB.SetStartPoint(0, 0); this.rectangleB.SetEndPoint(0, 0); // Signal MouseUp that user is selecting blocks. this.isMouseSelecting = true; } } } // Context Menu Launch - Right Mouse Button if (args.Button == MouseButtons.Right) { // Pre-process Context-Menu data here. // Context-Menu delegate associated in engine.designer file. } } private void MouseMotion(object sender, MouseEventArgs args) { if (Engine.editMode == EditMode.Draw || Engine.editMode == EditMode.Erase) { if(this.isMouseDrawing) { Engine.PaintBrushSelectedCell(args.X, args.Y); } } else { if (this.isMouseSelecting) { // Set Selector Rectangle EndPoint this.rectangleA.SetEndPoint(args.X, args.Y); } if (this.isSelectionMoving) { // Move Selection Rectangle this.rectangleB.MoveTo(args.X, args.Y); } } } private void MouseUp_Click(object sender, MouseEventArgs args) { if (this.isMouseDrawing) { // Turn signal off, set in MouseDown this.isMouseDrawing = false; } // Handle Tile-Selection Event if (this.isMouseSelecting) { // Snap selection to block boundaries rectangleA.DescretizeSelection(Cell.scale); // Turn signal off, set in MouseDown this.isMouseSelecting = false; } // Handle Tile-Drop Event Copy/Move if (this.isSelectionMoving) { if (Engine.editMode == EditMode.Copy) { Engine.CopySelectedCells(); } else if (Engine.editMode == EditMode.Move) { // Move the Cells Engine.MoveSelectedCells(); } // Turn signal off, set in MouseDown this.isSelectionMoving = false; } } #region Controls (Static Driver Interface Handles) public static void CopySelectedCells() { Engine._self.sceneGraph.CopyCells_ByScreenCoord( Engine._self.rectangleA, Engine._self.rectangleB.StartX - Engine._self.rectangleA.StartX, Engine._self.rectangleB.StartY - Engine._self.rectangleA.StartY ); } public static void MoveSelectedCells() { Engine._self.sceneGraph.MoveCells_ByScreenCoord( Engine._self.rectangleA, Engine._self.rectangleB.StartX - Engine._self.rectangleA.StartX, Engine._self.rectangleB.StartY - Engine._self.rectangleA.StartY ); } public static void PaintBrushSelectedCell(int screenX, int screenY) { if (Engine.editMode == EditMode.Draw) { if (Engine.selectedTileBrush != null) { Engine._self.sceneGraph.SetCell_ByScreenCoord( screenX, screenY, Engine.selectedTileBrush.Clone(screenX, screenY) ); } } else if (Engine.editMode == EditMode.Erase) { Engine._self.sceneGraph.SetCell_ByScreenCoord( screenX, screenY, new Cell(screenX, screenY) ); } } #endregion } }