2012-08-27 11:39:14 +00:00
#region = = = = = = = = = = = = = = = = = = Copyright ( c ) 2007 Pascal vd Heiden
/ *
* Copyright ( c ) 2007 Pascal vd Heiden , www . codeimp . com
* This program is released under GNU General Public License
*
* 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 .
*
* /
#endregion
#region = = = = = = = = = = = = = = = = = = Namespaces
using System ;
2014-11-03 13:02:59 +00:00
using System.Collections.Generic ;
using System.Windows.Forms ;
2012-08-27 11:39:14 +00:00
using CodeImp.DoomBuilder.IO ;
using CodeImp.DoomBuilder.Map ;
#endregion
namespace CodeImp.DoomBuilder.Config
{
public class ThingFlagsCompare
{
public enum CompareMethod
{
Equal ,
And
} ;
#region = = = = = = = = = = = = = = = = = = Constants
#endregion
#region = = = = = = = = = = = = = = = = = = Variables
2014-09-29 20:49:41 +00:00
private readonly string flag ;
2014-11-03 13:02:59 +00:00
private string requiredgroup ; //mxd. This flag only works if at least one flag is set in the "requiredgroup"
private string ignoredgroup ; //mxd. If this flag is set, flags from ignoredgroup can be... well... ignored!
private string requiredflag ; //mxd. This flag only works if requiredflag is set.
private readonly bool ingnorethisgroupwhenunset ; //mxd
2014-09-29 20:49:41 +00:00
private readonly CompareMethod comparemethod ;
private readonly bool invert ;
private readonly string group ;
2012-08-27 11:39:14 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Properties
public string Flag { get { return flag ; } }
public string Group { get { return group ; } }
2014-11-03 13:02:59 +00:00
public string RequiredGroup { get { return requiredgroup ; } internal set { requiredgroup = value ; } } //mxd
public string IgnoredGroup { get { return ignoredgroup ; } internal set { ignoredgroup = value ; } } //mxd
public string RequiredFlag { get { return requiredflag ; } internal set { requiredflag = value ; } } //mxd
2015-01-12 12:27:10 +00:00
public bool IgnoreGroupWhenUnset { get { return ingnorethisgroupwhenunset ; } } //mxd
2012-08-27 11:39:14 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Constructor / Disposer
// Constructor
public ThingFlagsCompare ( Configuration cfg , string group , string flag )
{
string cfgpath = "thingflagscompare." + group + "." + flag ;
this . flag = flag ;
this . group = group ;
string cm = cfg . ReadSetting ( cfgpath + ".comparemethod" , "and" ) ;
switch ( cm )
{
default :
General . ErrorLogger . Add ( ErrorType . Warning , "Unrecognized value \"" + cm + "\" for comparemethod in " + cfgpath + " in game configuration " + cfg . ReadSetting ( "game" , "<unnamed game>" ) + ". Defaulting to \"and\"." ) ;
goto case "and" ;
case "and" :
comparemethod = CompareMethod . And ;
break ;
case "equal" :
comparemethod = CompareMethod . Equal ;
break ;
}
invert = cfg . ReadSetting ( cfgpath + ".invert" , false ) ;
2014-11-03 13:02:59 +00:00
requiredgroup = cfg . ReadSetting ( cfgpath + ".requiredgroup" , string . Empty ) ; //mxd
ignoredgroup = cfg . ReadSetting ( cfgpath + ".ignoredgroup" , string . Empty ) ; //mxd
requiredflag = cfg . ReadSetting ( cfgpath + ".requiredflag" , string . Empty ) ; //mxd
ingnorethisgroupwhenunset = cfg . ReadSetting ( cfgpath + ".ingnorethisgroupwhenunset" , false ) ; //mxd
2012-08-27 11:39:14 +00:00
// We have no destructor
GC . SuppressFinalize ( this ) ;
}
#endregion
#region = = = = = = = = = = = = = = = = = = Methods
// Compares the flag of the two things.
// Returns:
// -1 if the flag does not overlap
// 0 if the flag should be ignored
// 1 if the flag overlaps
public int Compare ( Thing t1 , Thing t2 )
{
// Check if the flags exist
2014-11-03 13:02:59 +00:00
if ( ! t1 . Flags . ContainsKey ( flag ) | | ! t2 . Flags . ContainsKey ( flag ) ) return 0 ;
//mxd. We should ignore the flag if requiredgroup doesn't have any flags set
if ( ! string . IsNullOrEmpty ( requiredgroup ) )
{
bool t1hasrequiredflags = false ;
bool t2hasrequiredflags = false ;
foreach ( string key in General . Map . Config . ThingFlagsCompare [ requiredgroup ] . Keys )
{
2015-05-27 21:55:15 +00:00
if ( General . Map . Config . ThingFlagsCompare [ requiredgroup ] [ key ] . invert ? ! t1 . IsFlagSet ( key ) : t1 . IsFlagSet ( key ) )
2014-11-03 13:02:59 +00:00
t1hasrequiredflags = true ;
2015-05-27 21:55:15 +00:00
if ( General . Map . Config . ThingFlagsCompare [ requiredgroup ] [ key ] . invert ? ! t2 . IsFlagSet ( key ) : t2 . IsFlagSet ( key ) )
2014-11-03 13:02:59 +00:00
t2hasrequiredflags = true ;
}
// Can't compare...
if ( ! t1hasrequiredflags | | ! t2hasrequiredflags ) return 0 ;
}
//mxd. We should ignore the flag if requiredflag is not set
2014-11-03 23:03:13 +00:00
if ( ! string . IsNullOrEmpty ( requiredflag ) )
2014-11-03 13:02:59 +00:00
{
bool inverted = General . Map . Config . ThingFlagsCompare [ group ] . ContainsKey ( requiredflag ) & & General . Map . Config . ThingFlagsCompare [ group ] [ requiredflag ] . invert ;
2015-05-27 21:55:15 +00:00
bool t1hasrequiredflag = ( inverted ? ! t1 . IsFlagSet ( requiredflag ) : t1 . IsFlagSet ( requiredflag ) ) ;
bool t2hasrequiredflag = ( inverted ? ! t2 . IsFlagSet ( requiredflag ) : t2 . IsFlagSet ( requiredflag ) ) ;
2014-11-03 13:02:59 +00:00
// Can't compare...
if ( ! t1hasrequiredflag | | ! t2hasrequiredflag ) return 0 ;
}
//mxd. We should also ignore the flag if it's in ingoredgroup
foreach ( KeyValuePair < string , Dictionary < string , ThingFlagsCompare > > pair in General . Map . Config . ThingFlagsCompare )
{
foreach ( KeyValuePair < string , ThingFlagsCompare > flaggrp in pair . Value )
{
if ( ! string . IsNullOrEmpty ( flaggrp . Value . ignoredgroup ) & & group = = flaggrp . Value . ignoredgroup )
{
2015-05-27 21:55:15 +00:00
bool t1ignoreflagset = flaggrp . Value . invert ? ! t1 . IsFlagSet ( flaggrp . Key ) : t1 . IsFlagSet ( flaggrp . Key ) ;
bool t2ignoreflagset = flaggrp . Value . invert ? ! t2 . IsFlagSet ( flaggrp . Key ) : t2 . IsFlagSet ( flaggrp . Key ) ;
2014-11-03 13:02:59 +00:00
2015-04-17 13:46:55 +00:00
// Can be ignored?
if ( ! t1ignoreflagset & & ! t2ignoreflagset & & flaggrp . Value . IgnoreGroupWhenUnset ) continue ;
2014-11-03 13:02:59 +00:00
// Can't compare...
if ( ! t1ignoreflagset | | ! t2ignoreflagset ) return 0 ;
}
}
2012-11-09 17:40:47 +00:00
}
2014-11-03 13:02:59 +00:00
// Take flag inversion into account
2015-05-27 21:55:15 +00:00
bool t1flag = invert ? ! t1 . Flags [ flag ] : t1 . Flags [ flag ] ;
bool t2flag = invert ? ! t2 . Flags [ flag ] : t2 . Flags [ flag ] ;
2012-08-27 11:39:14 +00:00
2014-09-29 20:49:41 +00:00
if ( comparemethod = = CompareMethod . And & & ( t1flag & & t2flag ) ) return 1 ;
if ( comparemethod = = CompareMethod . Equal & & ( t1flag = = t2flag ) ) return 1 ;
2012-08-27 11:39:14 +00:00
return 0 ;
}
2014-11-03 13:02:59 +00:00
//mxd
public static string CheckThingEditFormFlags ( List < CheckBox > checkboxes )
{
Dictionary < string , bool > flags = new Dictionary < string , bool > ( checkboxes . Count ) ;
Dictionary < string , Dictionary < string , bool > > flagspergroup = new Dictionary < string , Dictionary < string , bool > > ( General . Map . Config . ThingFlagsCompare . Count ) ;
Dictionary < string , bool > requiredgroups = new Dictionary < string , bool > ( ) ;
Dictionary < string , bool > ignoredgroups = new Dictionary < string , bool > ( ) ;
// Gather flags
foreach ( CheckBox cb in checkboxes )
{
2014-11-03 23:06:02 +00:00
flags . Add ( cb . Tag . ToString ( ) , cb . CheckState ! = CheckState . Unchecked ) ;
2014-11-03 13:02:59 +00:00
}
// Gather flags per group
foreach ( KeyValuePair < string , Dictionary < string , ThingFlagsCompare > > group in General . Map . Config . ThingFlagsCompare )
{
flagspergroup . Add ( group . Key , new Dictionary < string , bool > ( ) ) ;
foreach ( KeyValuePair < string , ThingFlagsCompare > flaggrp in group . Value )
{
bool flagset = IsFlagSet ( flags , flaggrp . Key , flaggrp . Value . invert ) & & ( string . IsNullOrEmpty ( flaggrp . Value . requiredflag ) | | IsFlagSet ( flags , flaggrp . Value . requiredflag , group . Value [ flaggrp . Value . requiredflag ] . invert ) ) ;
if ( flagset )
{
flagspergroup [ group . Key ] . Add ( flaggrp . Key , true ) ;
if ( ! string . IsNullOrEmpty ( flaggrp . Value . requiredgroup ) & & ! requiredgroups . ContainsKey ( flaggrp . Value . requiredgroup ) )
requiredgroups . Add ( flaggrp . Value . requiredgroup , false ) ;
}
else if ( flaggrp . Value . ingnorethisgroupwhenunset )
{
ignoredgroups . Add ( group . Key , false ) ;
}
}
}
// Check dependancies
foreach ( KeyValuePair < string , Dictionary < string , bool > > group in flagspergroup )
{
foreach ( KeyValuePair < string , bool > flaggrp in group . Value )
{
if ( ! flaggrp . Value ) continue ;
string ignoredgrp = General . Map . Config . ThingFlagsCompare [ group . Key ] [ flaggrp . Key ] . ignoredgroup ;
if ( ! string . IsNullOrEmpty ( ignoredgrp ) & & ! requiredgroups . ContainsKey ( ignoredgrp ) )
{
ignoredgroups . Add ( ignoredgrp , false ) ;
}
}
}
// Get rid of ignoredgroups
foreach ( KeyValuePair < string , bool > group in ignoredgroups )
{
flagspergroup . Remove ( group . Key ) ;
}
// Return message
string result = string . Empty ;
foreach ( KeyValuePair < string , Dictionary < string , bool > > group in flagspergroup )
{
if ( group . Value . Count = = 0 )
{
switch ( group . Key )
{
case "skills" :
result + = "Thing is not used in any skill level." ;
break ;
case "gamemodes" :
result + = "Thing is not used in any game mode." ;
break ;
case "classes" :
result + = "Thing is not used by any class." ;
break ;
default :
result + = "At least one '" + group . Key + "' flag should be set." ;
break ;
}
}
}
return result ;
}
//mxd
private static bool IsFlagSet ( Dictionary < string , bool > flags , string flag , bool invert )
{
bool result = flags . ContainsKey ( flag ) & & flags [ flag ] ;
return ( invert ? ! result : result ) ;
}
2012-08-27 11:39:14 +00:00
#endregion
}
}