muddesigner/RoomDesigner/frmMain.cs
Scionwest_cp 988b592e1d Room Designer:
* Fixed designer crashing if no plugin .dll's where found.
2009-11-24 18:41:32 -08:00

329 lines
14 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MUDEngine.Objects.Environment;
using MUDEngine.Objects;
using MUDEngine;
using MUDEngine.FileSystem;
using MUDEngine.Attributes;
namespace RoomDesigner
{
public partial class frmMain : Form
{
//Current _CurrentRoom
Room _CurrentRoom;
//Doorway currently loaded.
Door _CurrentDoor;
ManagedScripting.ScriptingEngine _ScriptEngine;
List<System.Reflection.Assembly> _Plugins;
public frmMain()
{
InitializeComponent();
//Initialize the Room & Doorway
_CurrentRoom = new Room();
_CurrentDoor = new Door(AvailableTravelDirections.None);
//Show the user(s) the rooms properties
propertyRoom.SelectedObject = _CurrentRoom;
//This instances a copy of AvailableTravelDirections which is a list of
//currently available directions users can travel within rooms.
//Instead of updating the editor each time a new travel direction is implemented,
//we simply build an array that contains each travel direction currently available
//within the engine by getting each element from the AvailableTravelDirections enum
AvailableTravelDirections direction = new AvailableTravelDirections();
//Build an array of travel directions currently implemented
Array Values = System.Enum.GetValues(direction.GetType());
//Loop through each travel direction within the array and add it
//to the lstDirections listbox.
foreach (int Value in Values)
{
string Display = Enum.GetName(direction.GetType(), Value);
//The array contains a 'None' direction. As the editor will allow for
//installing and uninstalling doorways, we don't need to show a 'None' direction
//in the listbox.
if (!Display.Equals("None"))
this.lstDirections.Items.Add(Display);
}
//Load all of our plugin .dll files. This is the only directory not generated by
//the engine, developers will need to manually create the folder if they want to
//create plugins
LoadPlugins();
//Before we loop through the plugins list to build our combo box return values
//we need to add the MUDEngine.dll to the list, so that it's objects can be
//used as return values with the engines scripts.
//We can use Assembly.Load("MUDEngine.dll") but that would load a 2nd copy
//of the engine in memory, as RoomDesigner.exe already has it loaded in memory.
//To prevent duplicate copies in memory, we will search every assembly currently
//loaded by the application instead until we find our engine.
//Build an array of assemblies currently loaded in memory by RoomDesigner.exe
System.Reflection.Assembly[] tempList = System.AppDomain.CurrentDomain.GetAssemblies();
//Loop through each assembly in the array and find the mud engine
foreach (System.Reflection.Assembly a in tempList)
{
//Check the assemblies manifest name to see if it matches our mud engine name
if (a.ManifestModule.Name.ToLower() == "mudengine.dll")
{
//Found the engine, add it to the plugins list so that we can
//add it's BaseObject inherited classes to the Script tab's
//Return Type combo box.
_Plugins.Add(a);
break;
}
}
//Loop through each plugin, and add it's objects to the return type
//combo box, so scripts can inherit from them.
foreach (System.Reflection.Assembly assembly in _Plugins)
{
//Loop through each time within this specific plugin assembly
foreach (Type type in assembly.GetTypes())
{
//Check if the current Type inherits from BaseObject
if (type.BaseType.Name == "BaseObject")
{
//Now that we know it inherits from BaseObject
//we need to make sure that it is a useable class
//or it's for internal use only. This can be set by
//the developer using the UnusableAttribute attribute
//on the class
bool isUseable = true;
foreach (object attribute in type.GetCustomAttributes(false))
{
//Check if the Type contains the UnsableAttribute attribute
if (attribute is UnusableAttribute)
{
//It does, exit the loop and declare it unuseable
isUseable = false;
break;
}
}
//If the class does not contain the UnusableAttribute attribute
//we can use it as a return value for our scripts.
if (isUseable)
{
comReturnTypes.Items.Add(type.Name);
}
}
}//foreach Type loop
}//foreach Assembly loop
//Instance the scripting engine and set it up.
_ScriptEngine = new ManagedScripting.ScriptingEngine();
_ScriptEngine.Compiler = ManagedScripting.ScriptingEngine.CompilerSelections.SourceCompiler;
_ScriptEngine.CompileStyle = ManagedScripting.Compilers.BaseCompiler.ScriptCompileStyle.CompileToMemory;
_ScriptEngine.KeepTempFiles = false;
}
private void LoadPlugins()
{
string pluginPath = System.IO.Path.Combine(Application.StartupPath, "Plugins");
_Plugins = new List<System.Reflection.Assembly>();
//Check if the plugin path exists.
if (!System.IO.Directory.Exists(pluginPath))
return;
//Now loop through every .dll file in the plugins directory and load it into memory
//A copy is stored within a collection for use later if needed.
foreach (string assembly in System.IO.Directory.GetFiles(pluginPath, "*.dll"))
{
_Plugins.Add(System.Reflection.Assembly.LoadFile(assembly));
}
//TODO: Look for ways to allow Types to inherit from a Windows Control, and add each
//control to a new tab or menu item, allowing for editor plugins as well.
}
/// <summary>
/// Closes the editor.
/// TODO: Serialize the Room out to file.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnCloseEditor_Click(object sender, EventArgs e)
{
Application.Exit();
}
/// <summary>
/// Change the currently selected direction, allowing users to uninstall or install
/// a doorway, and display the selected doorways properties for editing.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void lstDirections_SelectedIndexChanged(object sender, EventArgs e)
{
//Used to indicate that the direction the user selected exists,
//and was found for editing
bool IsFound = false;
//Loop through each doorway installed within the _CurrentRoom and see if the user has
//selected a direction that belongs to a _CurrentDoor already created. If a _CurrentDoor with
//the selected direction is found, we display it's properties for editing instead
//of creating a new _CurrentDoor and overwriting the previously created doorway.
foreach (Door newDoor in _CurrentRoom.InstalledDoors)
{
//Check if the current _CurrentDoor in the loop matches the currently selected
//travel direction the user has selected in the listbox.
if (newDoor.TravelDirection.ToString() == lstDirections.SelectedItem.ToString())
{
//The travel directions match, let's set the current _CurrentDoor in the loop as our
//new selected doorway so that the user can edit it.
_CurrentDoor = newDoor;
//Indicates that we found a matching doorway and have set it up for
//editing within the propertygrid
IsFound = true;
//Exit the loop
break;
}
}
//There isn't a _CurrentDoor installed into the _CurrentRoom yet with a travel direction
//matching that of the users currently selected travel direction within the listbox.
//so we instance a new _CurrentDoor
if (!IsFound)
{
AvailableTravelDirections direction = GetDirection(lstDirections.SelectedItem.ToString());
_CurrentDoor = new Door(direction);
}
//Display the properties for users to edit. This could be a pre-existing doorway
//found within our loop, or a new doorway.
propertyDoor.SelectedObject = _CurrentDoor;
}
/// <summary>
/// Modified values within the doorway get stored within the currentDoor Field.
/// </summary>
/// <param name="s"></param>
/// <param name="e"></param>
private void propertyDoor_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
{
//Check if we are installing the door into the room or
//uninstalling it from the current room.
switch (_CurrentDoor.DoorState)
{
case Door.AvailableDoorStates.Installed:
InstallDoor();
break;
case Door.AvailableDoorStates.Uninstalled:
UninstallDoor();
break;
}
}
/// <summary>
/// Converts a string into an AvailableTravelDirections enum equivilant if it
/// exists within the enum list.
/// </summary>
/// <param name="Direction"></param>
/// <returns></returns>
private AvailableTravelDirections GetDirection(string Direction)
{
foreach (AvailableTravelDirections value in Enum.GetValues(typeof(AvailableTravelDirections)))
{
string name = value.ToString();
if (name == Direction)
return value;
}
return AvailableTravelDirections.None;
}
/// <summary>
/// Installs the _CurrentDoor into the _CurrentRoom's collection of doorways
/// </summary>
private void InstallDoor()
{
//Indicates if we found a door already installed within the room
//matching the selected travel direction.
bool IsInstalled = false;
//Incase there are no existing doors, the foreach loop gets skipped.
if (_CurrentRoom.InstalledDoors.Count == 0)
{
//Add the new door to the room
_CurrentRoom.InstalledDoors.Add(_CurrentDoor);
return;
}
//Loop through all of the installed doors within this room and
//check to see if we have a doorway with the same travel direction
//that the user has selected within the list box. If so then we
//need to prompt the user to ensure it's ok to overwrite the previous
//door with a new door.
//TODO: Look at this closer, do i need this messagebox?
foreach (Door newDoor in _CurrentRoom.InstalledDoors)
{
if (newDoor.TravelDirection == _CurrentDoor.TravelDirection)
{
/*DialogResult result = MessageBox.Show("Door already exists! Overwrite it?", "Room Designer", MessageBoxButtons.YesNo);
if (result == DialogResult.No)
return;
*/
_CurrentRoom.InstalledDoors.Remove(newDoor);
_CurrentRoom.InstalledDoors.Add(_CurrentDoor);
IsInstalled = true;
break;
}
}
if (!IsInstalled)
_CurrentRoom.InstalledDoors.Add(_CurrentDoor);
}
/// <summary>
/// Uninstalls the doorway from the room.
/// </summary>
private void UninstallDoor()
{
foreach (Door door in _CurrentRoom.InstalledDoors)
{
if (door.TravelDirection == _CurrentDoor.TravelDirection)
{
_CurrentRoom.InstalledDoors.Remove(door);
break;
}
}
}
/// <summary>
/// Resets the room.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnNewRoom_Click(object sender, EventArgs e)
{
DialogResult result = MessageBox.Show("Are you sure you want to create a new room?", "Room Designer", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.No)
return;
_CurrentRoom = new Room();
_CurrentDoor = new Door(AvailableTravelDirections.None);
propertyDoor.SelectedObject = null;
propertyRoom.SelectedObject = _CurrentRoom;
}
}
}