using System ;
using System.Collections.Generic ;
using System.Text ;
using System.Xml ;
using System.IO ;
namespace SCJMapper_V2
{
/// <summary>
/// should read the default profile - may be replacing the MappingVars once
/// </summary>
class DProfileReader
{
public Boolean ValidContent { get ; set ; }
private Stack < String > m_nodeNameStack = null ; // element name stack - keeping track where we are
// state for the parser
enum EState
{
idle = 0 ,
inActionMap ,
}
private EState m_state = EState . idle ;
// an action map and its actions
class Action
{
public String name { get ; set ; } // the action name
public String input { get ; set ; } // the input method K,J,X,P
public String defBinding { get ; set ; } // the default binding - may be useful
public String keyName
{ get { return input + name ; } } // prep for TreView usage - create a key from input+name
}
class ActionMap : List < Action > // carries the action list
{
public String name { get ; set ; } // the map name
} ;
Dictionary < String , ActionMap > m_aMap = null ; // key would be the actionmap name
ActionMap m_currentMap = null ;
// actionmap names to gather (do we need them to be cofigurable ??)
private String [ ] c_exMaps = { "spaceship_general" , "spaceship_view" , "spaceship_movement" , "spaceship_targeting" , "spaceship_weapons" , "spaceship_missiles" ,
"spaceship_defensive" , "spaceship_auto_weapons" , "spaceship_radar" , "spaceship_hud" , "IFCS_controls" , "" , "" , "" } ;
public DProfileReader ( )
{
ValidContent = false ; // default
}
/// <summary>
/// Returns the collected actionmaps as CSV (same format as MappingVars)
/// i.e. one line per actionmap where the first element is the actionmap and following are actions;defaultBinding lead by the input Key in uppercase (JKXP)
/// </summary>
public String CSVMap
{
get
{
String buf = "" ;
foreach ( ActionMap am in m_aMap . Values ) {
buf + = am . name + ";" ;
foreach ( Action a in am ) {
buf + = a . keyName + ";" + a . defBinding + ";" ; // add default binding to the CSV
}
buf + = String . Format ( "\n" ) ;
}
return buf ;
}
}
/// <summary>
/// Read one 'empty' XML element
///
/// <name [attr="" ..] />
///
/// </summary>
/// <param name="xr">An XML reader @ StartElement</param>
/// <returns>True if reading can continue</returns>
private Boolean ReadEmptyElement ( XmlReader xr )
{
Dictionary < String , String > attr = new Dictionary < string , string > ( ) ;
String eName = xr . Name ;
switch ( xr . NodeType ) {
case XmlNodeType . Element :
//Console.Write( "<{0}", xr.Name );
while ( xr . MoveToNextAttribute ( ) ) {
attr . Add ( xr . Name , xr . Value ) ; // save the attributes
//Console.Write( " {0}='{1}'", xr.Name, xr.Value );
}
if ( m_state = = EState . inActionMap ) {
// processing a valid action map - collect actions
if ( eName . ToLower ( ) = = "action" ) {
// this is an action.. - collect it
// we collect actions for each input ie for K,J,X and P
if ( attr . ContainsKey ( "joystick" ) ) {
Action ac = new Action ( ) ;
ac . name = attr [ "name" ] ;
ac . input = "J" ;
ac . defBinding = attr [ "joystick" ] ;
if ( ! String . IsNullOrEmpty ( ac . defBinding ) ) m_currentMap . Add ( ac ) ; // finally add it to the current map if it was bound
}
if ( attr . ContainsKey ( "keyboard" ) ) {
Action ac = new Action ( ) ;
ac . name = attr [ "name" ] ;
ac . input = "K" ;
ac . defBinding = attr [ "keyboard" ] ;
if ( ! String . IsNullOrEmpty ( ac . defBinding ) ) m_currentMap . Add ( ac ) ; // finally add it to the current map if it was bound
}
if ( attr . ContainsKey ( "xboxpad" ) ) {
Action ac = new Action ( ) ;
ac . name = attr [ "name" ] ;
ac . input = "X" ;
ac . defBinding = attr [ "xboxpad" ] ;
if ( ! String . IsNullOrEmpty ( ac . defBinding ) ) m_currentMap . Add ( ac ) ; // finally add it to the current map if it was bound
}
if ( attr . ContainsKey ( "ps3pad" ) ) {
Action ac = new Action ( ) ;
ac . name = attr [ "name" ] ;
ac . input = "P" ;
ac . defBinding = attr [ "ps3pad" ] ;
if ( ! String . IsNullOrEmpty ( ac . defBinding ) ) m_currentMap . Add ( ac ) ; // finally add it to the current map if it was bound
}
}
} // if inmap
//Console.Write( ">\n" );
m_nodeNameStack . Pop ( ) ;
break ;
case XmlNodeType . Text :
//Console.Write( xr.Value );
break ;
case XmlNodeType . EndElement :
//Console.Write( "</{0}>\n", xr.Name );
break ;
}
return true ;
}
/// <summary>
/// Read one XML element
///
/// <name attr="">
/// [ Xelement ]
/// </name>
///
/// </summary>
/// <param name="xr">An XML reader @ StartElement</param>
/// <returns>True if reading can continue</returns>
private Boolean ReadElement ( XmlReader xr )
{
Dictionary < String , String > attr = new Dictionary < string , string > ( ) ;
String eName = xr . Name ;
switch ( xr . NodeType ) {
case XmlNodeType . Element :
//Console.Write( "<{0}", xr.Name );
while ( xr . MoveToNextAttribute ( ) ) {
attr . Add ( xr . Name , xr . Value ) ; // save the attributes
//Console.Write( " {0}='{1}'", xr.Name, xr.Value );
}
// now here we could have an actionmap start
if ( m_state = = EState . idle ) {
if ( m_nodeNameStack . Peek ( ) . ToLower ( ) = = "actionmap" ) {
// check for a valid one
String mapName = attr [ "name" ] ;
String item = Array . Find ( c_exMaps , delegate ( String sstr ) {
return sstr = = mapName ;
} ) ;
if ( ! String . IsNullOrEmpty ( item ) ) {
// finally.... it is a valid actionmap
m_currentMap = new ActionMap ( ) ;
m_currentMap . name = mapName ;
m_aMap . Add ( mapName , m_currentMap ) ; // add to our inventory
m_state = EState . inActionMap ; // now we are in and processing the map
}
}
}
else if ( m_state = = EState . inActionMap ) {
// processing a valid action map - collect actions
if ( eName . ToLower ( ) = = "action" ) {
// this is an action.. - collect it
// we collect actions for each input ie for K,J,X and P
if ( attr . ContainsKey ( "joystick" ) ) {
Action ac = new Action ( ) ;
ac . name = attr [ "name" ] ;
ac . input = "J" ;
ac . defBinding = attr [ "joystick" ] ;
if ( ! String . IsNullOrEmpty ( ac . defBinding ) ) m_currentMap . Add ( ac ) ; // finally add it to the current map if it was bound
}
if ( attr . ContainsKey ( "keyboard" ) ) {
Action ac = new Action ( ) ;
ac . name = attr [ "name" ] ;
ac . input = "K" ;
ac . defBinding = attr [ "keyboard" ] ;
if ( ! String . IsNullOrEmpty ( ac . defBinding ) ) m_currentMap . Add ( ac ) ; // finally add it to the current map if it was bound
}
if ( attr . ContainsKey ( "xboxpad" ) ) {
Action ac = new Action ( ) ;
ac . name = attr [ "name" ] ;
ac . input = "X" ;
ac . defBinding = attr [ "xboxpad" ] ;
if ( ! String . IsNullOrEmpty ( ac . defBinding ) ) m_currentMap . Add ( ac ) ; // finally add it to the current map if it was bound
}
if ( attr . ContainsKey ( "ps3pad" ) ) {
Action ac = new Action ( ) ;
ac . name = attr [ "name" ] ;
ac . input = "P" ;
ac . defBinding = attr [ "ps3pad" ] ;
if ( ! String . IsNullOrEmpty ( ac . defBinding ) ) m_currentMap . Add ( ac ) ; // finally add it to the current map if it was bound
}
}
}
//Console.Write( ">\n" );
break ;
case XmlNodeType . Text :
//Console.Write( xr.Value );
break ;
case XmlNodeType . EndElement :
//Console.Write( "</{0}>\n", xr.Name );
break ;
}
return true ;
}
/// <summary>
/// Read the xml part
/// </summary>
/// <param name="xr"></param>
/// <returns></returns>
private Boolean ReadXML ( XmlReader xr )
{
Boolean retVal = true ;
do {
if ( xr . IsStartElement ( ) ) {
m_nodeNameStack . Push ( xr . Name ) ;
if ( xr . IsEmptyElement )
retVal = retVal & & ReadEmptyElement ( xr ) ;
else {
retVal = retVal & & ReadElement ( xr ) ;
}
}
else if ( xr . NodeType = = XmlNodeType . EndElement ) {
//Console.Write( "</{0}>\n", xr.Name );
String exitElement = m_nodeNameStack . Pop ( ) ;
if ( m_state = = EState . inActionMap )
if ( exitElement . ToLower ( ) = = "actionmap" ) m_state = EState . idle ; // finished
}
} while ( xr . Read ( ) ) ;
if ( m_nodeNameStack . Count = = 0 )
return retVal & & true ;
else
return false ;
}
/// <summary>
/// Read the defaultProfile.xml - do some sanity check
/// </summary>
/// <param name="xml">the XML action defaultProfile Content</param>
/// <returns>True if an action was decoded</returns>
public Boolean fromXML ( String xml )
{
XmlReaderSettings settings = new XmlReaderSettings ( ) ;
settings . ConformanceLevel = ConformanceLevel . Fragment ;
settings . IgnoreWhitespace = true ;
settings . IgnoreComments = true ;
XmlReader reader = XmlReader . Create ( new StringReader ( xml ) , settings ) ;
m_nodeNameStack = new Stack < String > ( ) ;
m_aMap = new Dictionary < String , ActionMap > ( ) ;
reader . Read ( ) ;
ValidContent = ReadXML ( reader ) ;
return ValidContent ;
}
}
}