/* * LuaConsoleScreen.cs * Authors: Adam Nabinger * based on code by August Zinsser * Copyright (c) 2007-2008 Cornell University This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ using System; using System.Collections.Generic; using System.Text; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using LuaInterface; using Microsoft.Xna.Framework; using Util; public class LuaConsoleScreen : GameScreen { private struct HistoryItem { internal enum Code { Command, Output, Error }; internal string Text; internal Code CodeType; internal HistoryItem(string text, Code codeType) { Text = text; CodeType = codeType; } } private const int mLeft = 5; private const int mBottom = 40; private const int mSpacing = 40; private const float mScreenPercentage = .333f; private const int mHistoryCount = 25; private static readonly string mCursor = "> "; private static List mHistory = new List(); private static int mHistoryIndex = 0; private SpriteBatch mSpriteBatch; private SpriteFont font; private InputHandler inputHandler; private Lua LuaVM; private string commandString = string.Empty; private Texture2D lineTex; public LuaConsoleScreen(Lua VM) { LuaVM = VM; } protected override void Dispose(bool disposing) { if (disposing) { mSpriteBatch.Dispose(); } base.Dispose(disposing); } public override void Initialize() { inputHandler = GetInputHandler(); inputHandler.Initialize(); inputHandler.ReportAllEvents = true; inputHandler.ReportCase = true; base.Initialize(); } protected override void LoadContent() { mSpriteBatch = new SpriteBatch(GraphicsDevice); font = Content.Load(@"Fonts\menufont"); lineTex = Content.Load(@"blank"); base.LoadContent(); } public override void Reinitialize() { throw new Exception("The method or operation is not implemented."); } public override void Update(Microsoft.Xna.Framework.GameTime gameTime) { while (inputHandler.HasEvent()) { InputEvent e = inputHandler.GetNextEvent(); KeyInputEvent key = e as KeyInputEvent; if (key != null && e.Trigger == Trigger.Activated) { switch (key.Key) { case Keys.Back: commandString = commandString.Substring(0, Math.Max(commandString.Length - 1, 0)); break; case Keys.Up: int newIndexUp = mHistoryIndex; do { if (newIndexUp < mHistory.Count - 1) { ++newIndexUp; } else { return; } } while (mHistory[newIndexUp].CodeType != HistoryItem.Code.Command); mHistoryIndex = newIndexUp; commandString = mHistory[mHistoryIndex].Text; break; case Keys.Down: int newIndexDown = mHistoryIndex; do { if (newIndexDown > 0) { --newIndexDown; } else { return; } } while (mHistory[newIndexDown].CodeType != HistoryItem.Code.Command); mHistoryIndex = newIndexDown; commandString = mHistory[mHistoryIndex].Text; break; case Keys.Enter: if (commandString != string.Empty) { mHistory.Insert(0, new HistoryItem(commandString, HistoryItem.Code.Command)); // Send the command the Lua Virtual Machine try { LuaVM.DoString(commandString); } catch (Exception ex) { mHistory.Insert(0, new HistoryItem(ex.Message, HistoryItem.Code.Error)); } // Update console commands commandString = string.Empty; mHistoryIndex = -1; } break; case Keys.Escape: case Keys.OemTilde: Done(); break; default: commandString += key.ToCodeString(); break; } } } // Update history lines while (mHistory.Count > mHistoryCount) { mHistory.RemoveAt(mHistory.Count - 1); } base.Update(gameTime); } // TODO: Cleanup public override void Draw(Microsoft.Xna.Framework.GameTime gameTime) { mSpriteBatch.Begin(SpriteBlendMode.Additive, SpriteSortMode.Immediate, SaveStateMode.None); int lineY = (int)(GraphicsDevice.Viewport.Height * mScreenPercentage); mSpriteBatch.Draw( lineTex, new Rectangle(0, 0, GraphicsDevice.Viewport.Width, (int)(GraphicsDevice.Viewport.Height * mScreenPercentage)), null, new Color(75, 75, 155, 180), 0f, Vector2.Zero, SpriteEffects.None, 0f); mSpriteBatch.Draw( lineTex, new Rectangle(0, (int)(lineY - 2), GraphicsDevice.Viewport.Width, 4), null, new Color(200, 200, 200, 200), 0f, Vector2.Zero, SpriteEffects.None, 0f); // Draw the command line Vector2 cursorSize = font.MeasureString(mCursor); mSpriteBatch.DrawString(font, mCursor, new Vector2(mLeft, lineY - mBottom), new Color(255, 150, 0, 255)); mSpriteBatch.DrawString(font, commandString, new Vector2(mLeft + (int)cursorSize.X, lineY - mBottom), new Color(255, 255, 175, 255)); // Draw the history lines Color color; for (int i = 0; i < mHistory.Count; i++) { int y = lineY - (mSpacing) * (i + 2); if (mHistoryIndex == i) mSpriteBatch.DrawString(font, mCursor, new Vector2(mLeft, y), new Color(200, 150, 0, 200)); if (mHistory[i].CodeType == HistoryItem.Code.Command) color = new Color(200, 200, 150, 255); else if (mHistory[i].CodeType == HistoryItem.Code.Output) color = new Color(155, 255, 255, 255); else color = new Color(255, 0, 0, 255); mSpriteBatch.DrawString(font, mHistory[i].Text, new Vector2(mLeft + (int)cursorSize.X, y), color); } mSpriteBatch.End(); base.Draw(gameTime); } }