namespace DarkWynter.Engine.Init
{
#region Using Statements
using System;
using System.Xml;
using System.Diagnostics;
using System.Threading;
using System.Collections.Generic;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
#endregion
using Audio;
using Globals;
using ObjectLib;
using Init;
using GameObjects;
///
/// The base class used in the XML layer of the architecture.
/// XML loads several configuration files, parses their main structure, and stores the nodes in public variables that are accessed by the rest of the program.
///
public static class XML
{
///
/// Content check boolean. If content is loaded, set to true.
///
public static bool contentInstalled = true;
///
/// Gets the current working directory for file access
///
///
public static String GetWorkingDirectory()
{
String curDir = Directory.GetCurrentDirectory();
// String workDir = curDir.Substring(0, curDir.IndexOf("bin\\x86\\Debug"));
return curDir;
}
#region GameObjectTypes
///
/// Contains all the Type definitions for GameObjects
///
public static List gameObjectTypes;
///
/// Create an GameObject using the "type" string included in the XmlNode.
/// User-Defined types can be added to the engine by inheriting from GameObjectTypes
/// and overloading it's CreateGameobjectType method. This method must create a new
/// GameObject and assign it to the incoming GameObject. Creation of the GameObject
/// by the overloaded User-Defined class should use a case statement to decide what
/// kind of GameObject to create based on the Xml-based "type" parameter.
///
/// A blank GameObject to replace with User-Defined GameObject.
/// Returns true if GameObject was successfully created.
public static bool CreateGameObjectType(ref GameObject gameObject)
{
// Loop through engine and game layer types
for (int i = 0; i < gameObjectTypes.Count; i++)
{
// Try and create the gameObject
bool found = gameObjectTypes[i].CreateGameObjectType(ref gameObject);
if (found) { return true; }
}
return false;
}
#endregion
#region User Preferences
///
/// Loads xml System settings from SystemSettings.xml.
///
public static void LoadUserPreferences()
{
try
{
// Load physics, music, and fog
XmlDocument reader = new XmlDocument();
reader.Load("_xml/UserSettings/UserSettings.xml");
XmlNodeList allNodes = reader.ChildNodes;
foreach (XmlNode settingsNode in allNodes)
{
if (settingsNode.Name == "SystemSettings")
{
XmlNodeList settingsNodes = settingsNode.ChildNodes;
foreach (XmlNode node in settingsNodes)
{
if (node.Name == "EnableShadowMap1")
{
string value = node.Attributes["value"].Value;
if (value == "Yes")
{
Statics_Engine.SystemSettings.enableShadowMap1 = true;
}
else
{
Statics_Engine.SystemSettings.enableShadowMap1 = false;
}
}
else if (node.Name == "EnableShadowMap2")
{
string value = node.Attributes["value"].Value;
if (value == "Yes")
{
Statics_Engine.SystemSettings.enableShadowMap2 = true;
}
else
{
Statics_Engine.SystemSettings.enableShadowMap2 = false;
}
}
else if (node.Name == "EnableTerrainBumpMapping")
{
string value = node.Attributes["value"].Value;
if (value == "Yes")
{
Statics_Engine.SystemSettings.enableTerrainBumpMapping = true;
}
else
{
Statics_Engine.SystemSettings.enableTerrainBumpMapping = false;
}
}
else if (node.Name == "EnableTerrainMultiTexturing")
{
string value = node.Attributes["value"].Value;
if (value == "Yes")
{
Statics_Engine.SystemSettings.enableTerrainMultiTexturing = true;
}
else
{
Statics_Engine.SystemSettings.enableTerrainMultiTexturing = false;
}
}
else if (node.Name == "NumberOfTerrainTextures")
{
int value = int.Parse(node.Attributes["value"].Value);
if (value == 4)
{
Statics_Engine.SystemSettings.numberOfTerrainTextures = 4;
}
else if (value == 3)
{
Statics_Engine.SystemSettings.numberOfTerrainTextures = 3;
}
else
{
Statics_Engine.SystemSettings.numberOfTerrainTextures = 2;
}
}
else if (node.Name == "SingleLightSource")
{
string value = node.Attributes["value"].Value;
if (value == "Yes")
{
Statics_Engine.SystemSettings.singleLightSource = true;
}
else
{
Statics_Engine.SystemSettings.singleLightSource = false;
}
}
else if (node.Name == "MusicEnabled")
{
string value = node.Attributes["value"].Value;
if (value == "Yes")
{
Statics_Engine.SystemSettings.music = true;
}
else
{
Statics_Engine.SystemSettings.music = false;
}
}
else if (node.Name == "SoundEffects")
{
string value = node.Attributes["value"].Value;
if (value == "Yes")
{
Statics_Engine.SystemSettings.soundFX = true;
}
else
{
Statics_Engine.SystemSettings.soundFX = false;
}
}
}
}
}
}
catch
{
XML.contentInstalled = false;
System.Diagnostics.Debug.WriteLine("Error reading xml");
//throw new Exception("Error reading XML");
}
}
///
/// Saves xml System settings in SystemSettings.xml.
///
public static void SaveUserPreferences()
{
XmlTextWriter settingsFile = new XmlTextWriter(
"_xml/UserSettings/UserSettings.xml", null);
settingsFile.Formatting = Formatting.Indented;
settingsFile.WriteStartDocument();
settingsFile.WriteStartElement("SystemSettings");
settingsFile.WriteStartElement("EnableShadowMap1");
if (Statics_Engine.SystemSettings.enableShadowMap1)
{
settingsFile.WriteAttributeString("value", "Yes");
}
else
{
settingsFile.WriteAttributeString("value", "No");
}
settingsFile.WriteEndElement();
settingsFile.WriteStartElement("EnableShadowMap2");
if (Statics_Engine.SystemSettings.enableShadowMap2)
{
settingsFile.WriteAttributeString("value", "Yes");
}
else
{
settingsFile.WriteAttributeString("value", "No");
}
settingsFile.WriteEndElement();
settingsFile.WriteStartElement("EnableTerrainBumpMapping");
if (Statics_Engine.SystemSettings.enableTerrainBumpMapping)
{
settingsFile.WriteAttributeString("value", "Yes");
}
else
{
settingsFile.WriteAttributeString("value", "No");
}
settingsFile.WriteEndElement();
settingsFile.WriteStartElement("EnableTerrainMultiTexturing");
if (Statics_Engine.SystemSettings.enableTerrainMultiTexturing)
{
settingsFile.WriteAttributeString("value", "Yes");
}
else
{
settingsFile.WriteAttributeString("value", "No");
}
settingsFile.WriteEndElement();
settingsFile.WriteStartElement("NumberOfTerrainTextures");
if (Statics_Engine.SystemSettings.numberOfTerrainTextures == 4)
{
settingsFile.WriteAttributeString("value", "4");
}
else if (Statics_Engine.SystemSettings.numberOfTerrainTextures == 3)
{
settingsFile.WriteAttributeString("value", "3");
}
else
{
settingsFile.WriteAttributeString("value", "2");
}
settingsFile.WriteEndElement();
settingsFile.WriteStartElement("SingleLightSource");
if (Statics_Engine.SystemSettings.singleLightSource)
{
settingsFile.WriteAttributeString("value", "Yes");
}
else
{
settingsFile.WriteAttributeString("value", "No");
}
settingsFile.WriteEndElement();
settingsFile.WriteStartElement("MusicEnabled");
if (Statics_Engine.SystemSettings.music)
{
settingsFile.WriteAttributeString("value", "Yes");
}
else
{
settingsFile.WriteAttributeString("value", "No");
}
settingsFile.WriteEndElement();
settingsFile.WriteStartElement("SoundEffects");
if (Statics_Engine.SystemSettings.soundFX)
{
settingsFile.WriteAttributeString("value", "Yes");
}
else
{
settingsFile.WriteAttributeString("value", "No");
}
settingsFile.WriteEndElement();
settingsFile.WriteEndElement();
settingsFile.WriteEndDocument();
settingsFile.Flush();
settingsFile.Close();
}
#endregion
#region Player Data
///
/// Contains the name, modelPath, texturePath, bumpTexturePath,
/// and scale information for a character.
///
public struct ModelInfo
{
///
/// User friendly name of character.
///
public string name;
///
/// Path to model file.
///
public string modelPath;
///
/// Path to texture file.
///
public string texPath;
///
/// Path to bump texture file.
///
public string bumpPath;
///
/// Model scale.
///
public Vector3 scale;
///
/// Model animated or not
///
public bool animated;
}
///
/// List of instantiations of the PlayerInfo struct, contained in PlayerModels.xml.
///
public static List playerInfo;
///
/// Loads availible Players from PlayerInfo.xml and stores them in the PlayerInfo list.
///
public static void LoadPlayerIndex()
{
/// This is wrong and hardcoded - need to go back and make it so that it uses the level that it is on version of the
/// characters on the board - bad commentary I know
/// JASON!!!! HELP PLEASE ;-)
string playerXMLFile = "_xml/LevelEdit/" + levelInfo[Statics_Engine.PlayerSettings.PlayerLevelIndexLoad].name + ".xml";
List modelNames = new List();
playerInfo = new List();
int index = 0;
//setup the player scrolling
//GameMenuImageScroller scroller = (GameMenuImageScroller) menuSystem.playerSetup.GetMenu().GetMenuElement(0);
//scroller.Clear();
try
{
// Load physics, music, and fog
XmlDocument reader = new XmlDocument();
reader.Load(playerXMLFile);
XmlNodeList allNodes = reader.ChildNodes;
foreach (XmlNode playerNode in allNodes)
{
if (playerNode.Name == "CharacterModels")
{
XmlNodeList playerNodes = playerNode.ChildNodes;
foreach (XmlNode node in playerNodes)
{
if (node.Name == "Model")
{
ModelInfo player = new ModelInfo();
player.name = node.Attributes["name"].Value;
modelNames.Add(player.name);
player.modelPath = node.Attributes["model"].Value;
player.texPath = node.Attributes["texture"].Value;
player.bumpPath = node.Attributes["bumpTexture"].Value;
player.scale = new Vector3(float.Parse(node.Attributes["maxScale"].Value));
string value = node.Attributes["animated"].Value;
if (value == "Yes")
{
player.animated = true;
}
else
{
player.animated = false;
}
playerInfo.Add(player);
index++;
//scroller.AddNew(player.name,
// Statics.SystemSettings.content.Load("Content/_textures/patient" + index),
// Statics.SystemSettings.content.Load("Content/_textures/patient" + index));
}
}
}
}
}
catch
{
System.Diagnostics.Debug.WriteLine("Error reading xml");
throw new Exception("Error reading XML");
}
}
#endregion
#region Level Data
public static string levelName;
public static string locationMapName;
public static float vertMapToLocMapRelate;
public static float terrainModWidth;
///
/// Contains the name, description, and filepath for each level.
///
public struct LevelInfo
{
///
/// User friendly name for level.
///
public string name;
///
/// User friendly description for level.
///
public string description;
///
/// Filepath of the level xml, which contains all xml data for that level.
///
public string filepath;
}
///
/// List of availible levels contained in _Levels.xml
///
public static List levelInfo;
///
/// Current level index
///
public static int levelInfoIndex = 0;
///
/// All nodes contained in the currently loaded level xml file
///
public static XmlNode levelNodes;
///
/// Environment settings include level size and other dependent parameters
/// We set these here to eliminate load-order dependencies in load sequence.
///
public static List environmentProperties;
///
/// Xml Data defining Engine Environment Info
///
public static List soloObjects;
///
/// Contains all GameObject instances before Load
///
public static List locationMapObjects;
///
/// Loads availible Levels from _Levels.xml and stores them in the LevelInfo list.
///
public static void LoadLevelIndex()
{
string LevelXMLFile = "_xml/LevelEdit/_Levels.xml";
levelInfo = new List();
try
{
// Load physics, music, and fog
XmlDocument reader = new XmlDocument();
reader.Load(LevelXMLFile);
XmlNodeList allNodes = reader.ChildNodes;
foreach (XmlNode levelNode in allNodes)
{
if (levelNode.Name == "levels")
{
XmlNodeList levelNodes = levelNode.ChildNodes;
foreach (XmlNode node in levelNodes)
{
if (node.Name == "level")
{
LevelInfo level = new LevelInfo();
level.name = node.Attributes["name"].Value;
level.filepath = node.Attributes["xmlFile"].Value;
level.description = node.Attributes["description"].Value;
levelInfo.Add(level);
}
}
}
}
}
catch
{
XML.contentInstalled = false;
System.Diagnostics.Debug.WriteLine("Error reading xml");
//throw new Exception("Error reading XML");
}
}
///
/// Uses information from the selected LevelInfo node to load an xml file that describes the level.
/// Each node is parsed from the main structure and stored in the GameObjectInfo struct.
/// GameObjects then access these nodes to load themselves.
///
/// Xml level description file stored in LevelInfo node.
public static void LoadLevel(string xmlFileName)
{
// (Re) Initialize LevelNodes
if (locationMapObjects != null)
locationMapObjects.Clear();
locationMapObjects = new List();
// Read the Level File
try
{
XmlDocument reader = new XmlDocument();
String fileLocation = xmlFileName;
reader.Load(fileLocation);
// Get all outer nodes (incl xml version info and level)
XmlNodeList allNodes = reader.ChildNodes;
foreach (XmlNode levelNode in allNodes)
{
// If level definition
if (levelNode.Name == "level")
{
levelNodes = levelNode;
// Parse Level
environmentProperties = LoadEnvironment(levelNode);
LoadProperties(levelNode);
soloObjects = LoadObjects_Indiv(levelNode);
locationMapObjects = LoadObjects_LocationMap(levelNode);
}
}
}
catch
{
System.Diagnostics.Debug.WriteLine("Error reading xml: " + xmlFileName);
// throw new Exception("Error reading XML");
}
// Start Game Timer
Statics_Engine.LevelSettings.gameTimer = new Stopwatch();
Statics_Engine.LevelSettings.gameTimer.Start();
}
private static void LoadProperties(XmlNode levelNode)
{
// Get Level and LocationMap names
levelName = levelNode.Attributes["name"].Value;
locationMapName = levelNode.Attributes["locationMap"].Value;
// Cycle through XmlNodes
for (int loadCount = 0; loadCount < levelNode.ChildNodes.Count; loadCount++)
{
XmlNode node = levelNode.ChildNodes[loadCount];
if (node.Name == "Terrain")
{
Texture2D terrain = Statics_Engine.SystemSettings.content.Load(node.Attributes["heightmap"].Value);
Statics_Engine.TerrainSettings.vertexMapSize = terrain.Width;
}
}
// Calculate the vertexmap/locationmap ratio for use in the for loop below
vertMapToLocMapRelate = Statics_Engine.TerrainSettings.vertexMapSize /
float.Parse(levelNode.Attributes["locationMapSize"].Value);
// Create a ruler 1 terrain mod long (distance between verticies
terrainModWidth = Statics_Engine.TerrainSettings.terrainScaleFactor * vertMapToLocMapRelate;
}
private static List LoadEnvironment(XmlNode levelNode)
{
List properties = new List();
// Cycle through XmlNodes
for (int loadCount = 0; loadCount < levelNode.ChildNodes.Count; loadCount++)
{
XmlNode node = levelNode.ChildNodes[loadCount];
// Audio
if (node.Name == "Music")
{
Audio.LoadXML(node);
}
// Dimensions
else if (node.Name == "Dimensions")
{
Statics_Engine.TerrainSettings.terrainScaleFactor = int.Parse(node.Attributes["scale"].Value);
}
// Physics
else if (node.Name == "Physics")
{
Statics_Engine.GameSettings.accelDueToGravity = new Vector3(0.0f, Statics_Engine.GameSettings.gravityForce, 0.0f);
Statics_Engine.GameSettings.gravityForce = float.Parse(node.Attributes["gravity"].Value);
Statics_Engine.LevelSettings.TERRAIN_FRICTION = float.Parse(node.Attributes["friction"].Value);
}
// Fog
else if (node.Name == "Fog")
{
Statics_Engine.LevelSettings.fogDensity = float.Parse(node.Attributes["density"].Value);
Statics_Engine.LevelSettings.fogStart = float.Parse(node.Attributes["startfog"].Value);
Statics_Engine.LevelSettings.fogEnd = float.Parse(node.Attributes["endfog"].Value);
Statics_Engine.LevelSettings.fogColor[0] = float.Parse(node.Attributes["red"].Value);
Statics_Engine.LevelSettings.fogColor[1] = float.Parse(node.Attributes["green"].Value);
Statics_Engine.LevelSettings.fogColor[2] = float.Parse(node.Attributes["blue"].Value);
Statics_Engine.LevelSettings.fogColor[3] = float.Parse(node.Attributes["alpha"].Value);
}
}
return properties;
}
private static List LoadObjects_Indiv(XmlNode levelNode)
{
List gameObjects = new List();
// Check each Object Node for a match
for (int nodeCount = 0; nodeCount < levelNode.ChildNodes.Count; nodeCount++)
{
XmlNode node = levelNode.ChildNodes[nodeCount];
// If Node contains x,y,z coordinates
if (node.Attributes != null &&
node.Attributes["x"] != null &&
node.Attributes["z"] != null)
{
// Get the Node's color value
float x = float.Parse(node.Attributes["x"].Value);
float y = 255.0f;
float z = float.Parse(node.Attributes["z"].Value);
float w = 255.0f;
// Clone node to get a new pointer
XmlNode cloneNode = node.Clone();
// Create Object or continue
GameObject gameObject = new GameObject(new Load(cloneNode, new Vector4(x, y, z, w)));
if (!CreateGameObjectType(ref gameObject))
{ continue; }
// Read by ObjectLibrary::Load
gameObjects.Add(gameObject);
}
}
return gameObjects;
}
private static List LoadObjects_LocationMap(XmlNode levelNode)
{
List gameObjects = new List();
// Linearize pixels in location map
Texture2D locationMap = Statics_Engine.SystemSettings.content.Load(locationMapName);
Color[] pixels = new Color[locationMap.Width * locationMap.Width];
locationMap.GetData(pixels);
// Process Pixels from LocationMap
for (int pixelCount = 0; pixelCount < pixels.Length; pixelCount++)
{
Color currentPixel = pixels[pixelCount];
// Skip this pixel if blank, or empty
if (currentPixel == Color.Black || currentPixel == Color.White)
continue;
// Check each Object Node for a match
for (int nodeCount = 0; nodeCount < levelNode.ChildNodes.Count; nodeCount++)
{
// If node contains r,g,b coordinates
if (levelNode.ChildNodes[nodeCount].Attributes != null &&
levelNode.ChildNodes[nodeCount].Attributes["red"] != null &&
levelNode.ChildNodes[nodeCount].Attributes["green"] != null &&
levelNode.ChildNodes[nodeCount].Attributes["blue"] != null)
{
// Get the Node's color value
float r = float.Parse(levelNode.ChildNodes[nodeCount].Attributes["red"].Value);
float g = float.Parse(levelNode.ChildNodes[nodeCount].Attributes["green"].Value);
float b = float.Parse(levelNode.ChildNodes[nodeCount].Attributes["blue"].Value);
// If Node color matches Pixel...
if (r == currentPixel.R && g == currentPixel.G && b == currentPixel.B)
{
// Get 2D Position from 1D array
// Y is set during GameObject.Load()
Vector4 startPosition = new Vector4(((int)pixelCount / locationMap.Width) * terrainModWidth,
0.0f,
(pixelCount % locationMap.Width) * terrainModWidth,
0.0f);
// Get Node
XmlNode cloneNode = levelNode.ChildNodes[nodeCount].Clone();
// Create Object or continue
GameObject gameObject = new GameObject(new Load(cloneNode, startPosition));
if (!CreateGameObjectType(ref gameObject))
{ continue; }
// Read by ObjectLibrary::Load
gameObjects.Add(gameObject);
break;
}
}
}
}
return gameObjects;
}
#endregion
#region Survey Data
///
/// G2L Pre, Post, and Survey list
///
public static List SurveyList;
///
/// Loads xml System settings from WhileLoopsPrePostSurvey.xml.
///
public static void LoadSurvey(string fileName)
{
SurveyList = new List();
try
{
// Load physics, music, and fog
XmlDocument reader = new XmlDocument();
reader.Load(fileName);
XmlNodeList allNodes = reader.ChildNodes;
foreach (XmlNode settingsNode in allNodes)
{
if (settingsNode.Name == "QuestionSet")
{
XmlNodeList settingsNodes = settingsNode.ChildNodes;
foreach (XmlNode node in settingsNodes)
{
if (node.Name == "ProblemSet")
{
SurveyList.Add(node);
}
}
}
}
}
catch
{
System.Diagnostics.Debug.WriteLine("Error reading xml");
throw new Exception("Error reading XML");
}
}
#endregion
#region G2L Challenges
///
/// Contains all the quest instructions for a particular quest
///
public static List ChallengeNodes;
// G2L Stuff - can be converted later
public static void LoadQuestInfo()
{
// Read the Quest File
try
{
ChallengeNodes = new List();
XmlDocument reader = new XmlDocument();
String fileLocation = "_xml/QuestSettings/WhileLoops.xml";
reader.Load(fileLocation);
// Get all outer nodes (incl xml version info and level)
XmlNodeList allNodes = reader.ChildNodes;
foreach (XmlNode questNode in allNodes)
{
// If level definition
if (questNode.Name == "QuestSet")
{
foreach (XmlNode problemSetNode in questNode)
{
// Post problems for GameForm to access
if (problemSetNode.Name == "ProblemSet")
{
ChallengeNodes.Add(problemSetNode);
}
}
}
}
}
catch
{
System.Diagnostics.Debug.WriteLine("Error reading xml");
//throw new Exception("Error reading XML");
}
}
#endregion
}
}