Compare commits

...

3 Commits

Author SHA1 Message Date
6b1e193c90 Better whitespace changes 2026-02-02 16:02:00 -08:00
28d8c145b5 Merge branch 'mh/dev'
# Conflicts:
#	SharpLib.csproj
#	exp/Exp.cs
#	imm/FSM.cs
#	imm/Imm.cs
#	imm/List.cs
#	imm/Util.cs
#	imm/io.cs
#	lib/XmlFormatter2.cs
#	logging/Log.cs
#	res/Resource.cs
2026-02-02 15:55:30 -08:00
2b5940bef6 Whitespace updates 2026-02-01 23:49:30 -08:00
125 changed files with 8999 additions and 8040 deletions

View File

@ -118,7 +118,8 @@ public sealed class PpmCompress
} }
// Else write context escape symbol and continue decrementing the order // Else write context escape symbol and continue decrementing the order
enc.write( ctx.frequencies, 256 ); enc.write( ctx.frequencies, 256 );
outerContinue:; outerContinue:
;
} }
//outerBreak: //outerBreak:

View File

@ -111,7 +111,8 @@ public sealed class PpmDecompress
return symbol; return symbol;
} }
// Else we read the context escape symbol, so continue decrementing the order // Else we read the context escape symbol, so continue decrementing the order
outerContinue:; outerContinue:
;
} }
//outerBreak: //outerBreak:

View File

@ -61,9 +61,11 @@ public class DB<TID, T> where T : IID<TID>
var v = lookup( id ); var v = lookup( id );
v.Match( t => { v.Match( t =>
{
tx.checkout( id ); tx.checkout( id );
}, () => { }, () =>
{
} ); } );
return (tx, v); return (tx, v);
@ -111,7 +113,8 @@ public class DB<TID, T> where T : IID<TID>
{ {
for( int i = start; i < curCommitted.Count; ++i ) for( int i = start; i < curCommitted.Count; ++i )
{ {
if( !t.id.Equals( curCommitted[i] ) ) { } if( !t.id.Equals( curCommitted[i] ) )
{ }
else else
{ {
//collision = true; //collision = true;

View File

@ -9,7 +9,8 @@ namespace fsm;
public class Context{ public class Context
{
} }

View File

@ -261,7 +261,8 @@ public record class Recorded<T> : Versioned<T> where T : Recorded<T>
if( ReferenceEquals( current, next ) ) if( ReferenceEquals( current, next ) )
return current; return current;
var newMeta = current.Meta with { var newMeta = current.Meta with
{
Version = current.Meta.Version + 1, Version = current.Meta.Version + 1,
Reason = reason, Reason = reason,
MemberName = dbgName, MemberName = dbgName,

View File

@ -111,9 +111,12 @@ public class TypeStructureAnalyzer
{ {
var (hasDo, hasDont, propName) = GetMemberAttributes( mi, out var actualMiForAtts ); var (hasDo, hasDont, propName) = GetMemberAttributes( mi, out var actualMiForAtts );
if (hasDont) return false; if( hasDont )
if (mi.GetCustomAttribute<NonSerializedAttribute>(true) != null) return false; return false;
if (mi.Name.Contains("k__BackingField") && !propName.Any()) return false; // Skip if backing but no prop found if( mi.GetCustomAttribute<NonSerializedAttribute>( true ) != null )
return false;
if( mi.Name.Contains( "k__BackingField" ) && !propName.Any() )
return false; // Skip if backing but no prop found
string name = string.IsNullOrEmpty( propName ) ? mi.Name : propName; string name = string.IsNullOrEmpty( propName ) ? mi.Name : propName;
@ -135,7 +138,8 @@ public class TypeStructureAnalyzer
if( fi.Name.StartsWith( "<" ) && fi.Name.EndsWith( "BackingField" ) ) if( fi.Name.StartsWith( "<" ) && fi.Name.EndsWith( "BackingField" ) )
{ {
var gtIndex = fi.Name.IndexOf( '>' ); var gtIndex = fi.Name.IndexOf( '>' );
if (gtIndex > 1) { if( gtIndex > 1 )
{
return (true, fi.Name.Substring( 1, gtIndex - 1 )); return (true, fi.Name.Substring( 1, gtIndex - 1 ));
} }
} }
@ -150,8 +154,11 @@ public class TypeStructureAnalyzer
{ {
propName = IsBackingField( fi ).Item2; propName = IsBackingField( fi ).Item2;
var propInfo = mi.DeclaringType?.GetProperty( propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); var propInfo = mi.DeclaringType?.GetProperty( propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic );
if (propInfo != null) actualMi = propInfo; if( propInfo != null )
} else if (mi is PropertyInfo) { actualMi = propInfo;
}
else if( mi is PropertyInfo )
{
propName = mi.Name; propName = mi.Name;
} }
@ -164,8 +171,10 @@ public class TypeStructureAnalyzer
private Type GetElementType( Type collectionType ) private Type GetElementType( Type collectionType )
{ {
if (collectionType.IsArray) return collectionType.GetElementType()!; if( collectionType.IsArray )
if (collectionType.IsGenericType) return collectionType.GetGenericArguments().Last(); // Usually last (e.g., List<T>, Dict<K,V>) return collectionType.GetElementType()!;
if( collectionType.IsGenericType )
return collectionType.GetGenericArguments().Last(); // Usually last (e.g., List<T>, Dict<K,V>)
return typeof( object ); // Fallback return typeof( object ); // Fallback
} }

View File

@ -186,7 +186,8 @@ namespace lib
doc.Load( reader ); doc.Load( reader );
if( doc.DocumentElement == null ) return null; if( doc.DocumentElement == null )
return null;
if( t == null ) if( t == null )
return Deserialize( doc.DocumentElement ); return Deserialize( doc.DocumentElement );
@ -256,7 +257,8 @@ namespace lib
{ {
TypeCode typeCode = Type.GetTypeCode( type ); TypeCode typeCode = Type.GetTypeCode( type );
if( _cfg.VerboseLogging ) log.info( $"{type.FriendlyName()}.{name} {existing} {mi?.Name}" ); if( _cfg.VerboseLogging )
log.info( $"{type.FriendlyName()}.{name} {existing} {mi?.Name}" );
if( typeCode != TypeCode.Object ) if( typeCode != TypeCode.Object )
{ {
@ -276,7 +278,8 @@ namespace lib
if( obj is ser.I_Serialize iser ) if( obj is ser.I_Serialize iser )
{ {
if( _cfg.VerboseLogging ) log.info( $"" ); if( _cfg.VerboseLogging )
log.info( $"" );
obj = iser.OnDeserialize( null ); obj = iser.OnDeserialize( null );
} }
@ -314,7 +317,8 @@ namespace lib
private object DeserializeConcrete( XmlElement elem, MemberInfo mi, string name, Type type ) private object DeserializeConcrete( XmlElement elem, MemberInfo mi, string name, Type type )
{ {
if( _cfg.VerboseLogging ) log.info( $"" ); if( _cfg.VerboseLogging )
log.info( $"" );
string val = ""; string val = "";
@ -398,7 +402,8 @@ namespace lib
private object HydrateObject( XmlElement elem, MemberInfo mi, Type finalType, object obj ) private object HydrateObject( XmlElement elem, MemberInfo mi, Type finalType, object obj )
{ {
if( _cfg.VerboseLogging ) log.info( $"" ); if( _cfg.VerboseLogging )
log.info( $"" );
if( obj is IList ) if( obj is IList )
{ {
@ -488,7 +493,8 @@ namespace lib
private object HydrateObjectOfNarrowType( XmlElement elem, MemberInfo mi, Type narrowType, object obj ) private object HydrateObjectOfNarrowType( XmlElement elem, MemberInfo mi, Type narrowType, object obj )
{ {
if( _cfg.VerboseLogging ) log.info( $"" ); if( _cfg.VerboseLogging )
log.info( $"" );
var isImm = typeof( io.Obj ).IsAssignableFrom( narrowType ); var isImm = typeof( io.Obj ).IsAssignableFrom( narrowType );
@ -686,7 +692,8 @@ namespace lib
int refInt = refString.Length > 0 ? Convert.ToInt32( refString ) : -1; int refInt = refString.Length > 0 ? Convert.ToInt32( refString ) : -1;
if( _cfg.VerboseLogging ) log.info( $"{finalType?.FriendlyName()}({type?.FriendlyName()}) refInt {refInt} exitingObj = {obj?.ToString()}" ); if( _cfg.VerboseLogging )
log.info( $"{finalType?.FriendlyName()}({type?.FriendlyName()}) refInt {refInt} exitingObj = {obj?.ToString()}" );
obj = createObject( elem, finalType, refInt, obj ); obj = createObject( elem, finalType, refInt, obj );
@ -695,7 +702,8 @@ namespace lib
private object DeserializeList( XmlElement elem, MemberInfo mi, Type type, IList list ) private object DeserializeList( XmlElement elem, MemberInfo mi, Type type, IList list )
{ {
if( _cfg.VerboseLogging ) log.info( $"" ); if( _cfg.VerboseLogging )
log.info( $"" );
XmlNodeList arrNodeList = elem.ChildNodes; XmlNodeList arrNodeList = elem.ChildNodes;
@ -731,7 +739,8 @@ namespace lib
typeElem = typeof( KeyValuePair<,> ).MakeGenericType( type.GenericTypeArguments ); typeElem = typeof( KeyValuePair<,> ).MakeGenericType( type.GenericTypeArguments );
} }
if( _cfg.VerboseLogging ) log.info( $"DserCol {type.GetType().FriendlyName()} {typeElem.Name} into reflT {mi.ReflectedType.FriendlyName()} declT {mi.DeclaringType.FriendlyName()} {mi.Name}" ); if( _cfg.VerboseLogging )
log.info( $"DserCol {type.GetType().FriendlyName()} {typeElem.Name} into reflT {mi.ReflectedType.FriendlyName()} declT {mi.DeclaringType.FriendlyName()} {mi.Name}" );
string refString = elem.GetAttribute( "ref" ); string refString = elem.GetAttribute( "ref" );
int refInt = refString.Length > 0 ? Convert.ToInt32( refString ) : -1; int refInt = refString.Length > 0 ? Convert.ToInt32( refString ) : -1;
@ -776,7 +785,8 @@ namespace lib
var typeGen = Type.MakeGenericSignatureType( type ); var typeGen = Type.MakeGenericSignatureType( type );
if( _cfg.VerboseLogging ) log.info( $"TypeGen: {typeGen.FriendlyName()}" ); if( _cfg.VerboseLogging )
log.info( $"TypeGen: {typeGen.FriendlyName()}" );
if( type == typeof( ImmutableArray<> ).MakeGenericType( typeElem ) ) if( type == typeof( ImmutableArray<> ).MakeGenericType( typeElem ) )
{ {
@ -833,7 +843,8 @@ namespace lib
private object DeserializeArray( XmlElement elem, MemberInfo mi, Type type ) private object DeserializeArray( XmlElement elem, MemberInfo mi, Type type )
{ {
if( _cfg.VerboseLogging ) log.info( $"" ); if( _cfg.VerboseLogging )
log.info( $"" );
Type typeElem = type.GetElementType(); Type typeElem = type.GetElementType();
@ -883,7 +894,8 @@ namespace lib
if( _cfg.datastructure == Datastructure.Graph && refInt > 0 && m_alreadySerialized.ContainsKey( refInt ) ) if( _cfg.datastructure == Datastructure.Graph && refInt > 0 && m_alreadySerialized.ContainsKey( refInt ) )
{ {
if( _cfg.VerboseLogging ) log.info( $"Reuse object" ); if( _cfg.VerboseLogging )
log.info( $"Reuse object" );
return m_alreadySerialized[refInt]; return m_alreadySerialized[refInt];
} }
@ -893,7 +905,8 @@ namespace lib
if( isProxy ) if( isProxy )
{ {
if( _cfg.VerboseLogging ) log.info( $"use Proxy" ); if( _cfg.VerboseLogging )
log.info( $"use Proxy" );
object obj = null; object obj = null;
var tryType = type; var tryType = type;
@ -937,7 +950,8 @@ namespace lib
if( isSubclass ) if( isSubclass )
{ {
if( _cfg.VerboseLogging ) log.info( $"Using existing obj {existingObj?.ToString()}" ); if( _cfg.VerboseLogging )
log.info( $"Using existing obj {existingObj?.ToString()}" );
return existingObj; return existingObj;
} }
@ -953,12 +967,14 @@ namespace lib
try try
{ {
if( _cfg.VerboseLogging ) log.info( $"For {type.FriendlyName()} check for constructors" ); if( _cfg.VerboseLogging )
log.info( $"For {type.FriendlyName()} check for constructors" );
var cons = type.GetConstructor( Type.EmptyTypes ); var cons = type.GetConstructor( Type.EmptyTypes );
if( cons != null ) if( cons != null )
{ {
if( _cfg.VerboseLogging ) log.info( $"Activator.CreateInstance" ); if( _cfg.VerboseLogging )
log.info( $"Activator.CreateInstance" );
obj = Activator.CreateInstance( type ); obj = Activator.CreateInstance( type );
} }
else else
@ -967,15 +983,18 @@ namespace lib
obj = System.Runtime.Serialization.FormatterServices.GetUninitializedObject( type ); obj = System.Runtime.Serialization.FormatterServices.GetUninitializedObject( type );
} }
if( _cfg.VerboseLogging ) log.info( $"Got obj {obj?.ToString()}" ); if( _cfg.VerboseLogging )
log.info( $"Got obj {obj?.ToString()}" );
} }
catch( Exception ) catch( Exception )
{ {
try try
{ {
if( _cfg.VerboseLogging ) log.info( $"GetUninitializedObject" ); if( _cfg.VerboseLogging )
log.info( $"GetUninitializedObject" );
obj = System.Runtime.Serialization.FormatterServices.GetUninitializedObject( type ); obj = System.Runtime.Serialization.FormatterServices.GetUninitializedObject( type );
if( _cfg.VerboseLogging ) log.info( $"Got obj {obj?.ToString()}" ); if( _cfg.VerboseLogging )
log.info( $"Got obj {obj?.ToString()}" );
} }
catch( Exception exInner ) catch( Exception exInner )
{ {
@ -1323,8 +1342,10 @@ namespace lib
if( isImm ) if( isImm )
{ {
if( name == "MetaStorage" ) continue; if( name == "MetaStorage" )
if( name == "Fn" ) continue; continue;
if( name == "Fn" )
continue;
} }
if( !doAtt.Any() && FilterField( filterFields, doImpls, whitelistFields, childFi as MemberInfo, name ) ) if( !doAtt.Any() && FilterField( filterFields, doImpls, whitelistFields, childFi as MemberInfo, name ) )
@ -1365,8 +1386,10 @@ namespace lib
if( isImm ) if( isImm )
{ {
if( name == "MetaStorage" ) continue; if( name == "MetaStorage" )
if( name == "Fn" ) continue; continue;
if( name == "Fn" )
continue;
} }
if( FilterField( filterProps, doImpls, whitelistProps, childPi as MemberInfo, name ) ) if( FilterField( filterProps, doImpls, whitelistProps, childPi as MemberInfo, name ) )
@ -1413,8 +1436,10 @@ namespace lib
Type type = root.GetType(); Type type = root.GetType();
Type typeOfMember = typeof( object ); Type typeOfMember = typeof( object );
if( mi is FieldInfo fi ) typeOfMember = fi.FieldType; if( mi is FieldInfo fi )
if( mi is PropertyInfo pi ) typeOfMember = pi.PropertyType; typeOfMember = fi.FieldType;
if( mi is PropertyInfo pi )
typeOfMember = pi.PropertyType;
if( typeOfMember != type ) if( typeOfMember != type )
{ {
log.info( $"SerArr {typeOfMember.FriendlyName()} {mi?.Name} != {type.FriendlyName()}" ); log.info( $"SerArr {typeOfMember.FriendlyName()} {mi?.Name} != {type.FriendlyName()}" );

View File

@ -37,7 +37,8 @@ public static class LogGCExt
{ {
var index = te.PayloadIndex( name ); var index = te.PayloadIndex( name );
if( index <= 0 ) return default; if( index <= 0 )
return default;
var value = te.PayloadValue( index ); var value = te.PayloadValue( index );
@ -144,28 +145,33 @@ public class LogGC
{ {
var cat = catIn; var cat = catIn;
if( blacklist.Contains( te.EventName )) return; if( blacklist.Contains( te.EventName ) )
return;
{ {
var methodBeingCompiledNamespace = te.Get( "MethodBeingCompiledNamespace" ); var methodBeingCompiledNamespace = te.Get( "MethodBeingCompiledNamespace" );
if( ( methodBeingCompiledNamespace.StartsWith( "Microsoft" ) || methodBeingCompiledNamespace.StartsWith( "System" ) ) ) return; if( ( methodBeingCompiledNamespace.StartsWith( "Microsoft" ) || methodBeingCompiledNamespace.StartsWith( "System" ) ) )
return;
} }
{ {
var methodNamespace = te.PayloadStringByName( "MethodNamespace" ) ?? ""; var methodNamespace = te.PayloadStringByName( "MethodNamespace" ) ?? "";
if( ( methodNamespace.StartsWith( "Microsoft" ) || methodNamespace.StartsWith( "System" ) ) ) return; if( ( methodNamespace.StartsWith( "Microsoft" ) || methodNamespace.StartsWith( "System" ) ) )
return;
} }
{ {
var ns = te.PayloadStringByName( "TypeName" ) ?? ""; var ns = te.PayloadStringByName( "TypeName" ) ?? "";
if( ( ns.StartsWith( "Microsoft" ) || ns.StartsWith( "System" ) ) ) return; if( ( ns.StartsWith( "Microsoft" ) || ns.StartsWith( "System" ) ) )
return;
} }
{ {
var ns = te.PayloadStringByName( "TypeLoad/Stop" ) ?? ""; var ns = te.PayloadStringByName( "TypeLoad/Stop" ) ?? "";
if( ns.StartsWith( "Godot" ) ) return; if( ns.StartsWith( "Godot" ) )
return;
} }
{ {
@ -174,7 +180,8 @@ public class LogGC
if( payloadIndex > 0 ) if( payloadIndex > 0 )
{ {
var count = (int)te.PayloadValue( payloadIndex ); var count = (int)te.PayloadValue( payloadIndex );
if( count > 16 ) return; if( count > 16 )
return;
} }
} }
@ -192,8 +199,10 @@ public class LogGC
var optTier = te.Get( "OptimizationTier" ); var optTier = te.Get( "OptimizationTier" );
var methodNamespace = te.Get( "MethodNamespace" ); var methodNamespace = te.Get( "MethodNamespace" );
if( optTier == "MinOptJitted" ) return; if( optTier == "MinOptJitted" )
if( methodNamespace.StartsWith( "FastSerialization" )) return; return;
if( methodNamespace.StartsWith( "FastSerialization" ) )
return;
log.info( $"{optTier} {LogGCExt.MethodInfo( te )}", cat: te.EventName ); log.info( $"{optTier} {LogGCExt.MethodInfo( te )}", cat: te.EventName );
@ -204,7 +213,8 @@ public class LogGC
{ {
var methodNamespace = te.Get( "MethodBeingCompiledNamespace" ); var methodNamespace = te.Get( "MethodBeingCompiledNamespace" );
if( methodNamespace.StartsWith( "FastSerialization" )) return; if( methodNamespace.StartsWith( "FastSerialization" ) )
return;
log.info( $"Inlining {te.Get( "FailReason" )} {te.Get( "OptimizationTier" )} {LogGCExt.MethodInfo( te, "MethodBeingCompiled" )}", cat: te.EventName ); log.info( $"Inlining {te.Get( "FailReason" )} {te.Get( "OptimizationTier" )} {LogGCExt.MethodInfo( te, "MethodBeingCompiled" )}", cat: te.EventName );

View File

@ -128,7 +128,8 @@ namespace math
/// <inheritdoc/> /// <inheritdoc/>
public override bool Equals( object obj ) public override bool Equals( object obj )
{ {
if (ReferenceEquals(null, obj)) return false; if( ReferenceEquals( null, obj ) )
return false;
return obj is BoundingBoxExt && Equals( (BoundingBoxExt)obj ); return obj is BoundingBoxExt && Equals( (BoundingBoxExt)obj );
} }

View File

@ -192,7 +192,8 @@ namespace math
/// <param name="result">When the method completes, contains the newly constructed bounding sphere.</param> /// <param name="result">When the method completes, contains the newly constructed bounding sphere.</param>
public static unsafe void FromPoints( Vec3[] points, out BoundingSphere result ) public static unsafe void FromPoints( Vec3[] points, out BoundingSphere result )
{ {
if (points == null) throw new ArgumentNullException("points"); if( points == null )
throw new ArgumentNullException( "points" );
fixed( void* pointsPtr = points ) fixed( void* pointsPtr = points )
{ {
FromPoints( (IntPtr)pointsPtr, 0, points.Length, lib.Util.SizeOf<Vec3>(), out result ); FromPoints( (IntPtr)pointsPtr, 0, points.Length, lib.Util.SizeOf<Vec3>(), out result );

View File

@ -227,10 +227,14 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: return R; case 0:
case 1: return G; return R;
case 2: return B; case 1:
case 3: return A; return G;
case 2:
return B;
case 3:
return A;
} }
throw new ArgumentOutOfRangeException( nameof( index ), "Indices for Color run from 0 to 3, inclusive." ); throw new ArgumentOutOfRangeException( nameof( index ), "Indices for Color run from 0 to 3, inclusive." );
@ -240,11 +244,20 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: R = value; break; case 0:
case 1: G = value; break; R = value;
case 2: B = value; break; break;
case 3: A = value; break; case 1:
default: throw new ArgumentOutOfRangeException(nameof(index), "Indices for Color run from 0 to 3, inclusive."); G = value;
break;
case 2:
B = value;
break;
case 3:
A = value;
break;
default:
throw new ArgumentOutOfRangeException( nameof( index ), "Indices for Color run from 0 to 3, inclusive." );
} }
} }
} }
@ -356,11 +369,15 @@ namespace math
max = r; max = r;
min = r; min = r;
if (g > max) max = g; if( g > max )
if (b > max) max = b; max = g;
if( b > max )
max = b;
if (g < min) min = g; if( g < min )
if (b < min) min = b; min = g;
if( b < min )
min = b;
return ( max + min ) / 2; return ( max + min ) / 2;
} }
@ -385,11 +402,15 @@ namespace math
max = r; max = r;
min = r; min = r;
if (g > max) max = g; if( g > max )
if (b > max) max = b; max = g;
if( b > max )
max = b;
if (g < min) min = g; if( g < min )
if (b < min) min = b; min = g;
if( b < min )
min = b;
delta = max - min; delta = max - min;
@ -430,11 +451,15 @@ namespace math
max = r; max = r;
min = r; min = r;
if (g > max) max = g; if( g > max )
if (b > max) max = b; max = g;
if( b > max )
max = b;
if (g < min) min = g; if( g < min )
if (b < min) min = b; min = g;
if( b < min )
min = b;
// if max == min, then there is no color and // if max == min, then there is no color and
// the saturation is zero. // the saturation is zero.

View File

@ -149,9 +149,12 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: return R; case 0:
case 1: return G; return R;
case 2: return B; case 1:
return G;
case 2:
return B;
} }
throw new ArgumentOutOfRangeException( nameof( index ), "Indices for Color3 run from 0 to 2, inclusive." ); throw new ArgumentOutOfRangeException( nameof( index ), "Indices for Color3 run from 0 to 2, inclusive." );
@ -161,10 +164,17 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: R = value; break; case 0:
case 1: G = value; break; R = value;
case 2: B = value; break; break;
default: throw new ArgumentOutOfRangeException(nameof(index), "Indices for Color3 run from 0 to 2, inclusive."); case 1:
G = value;
break;
case 2:
B = value;
break;
default:
throw new ArgumentOutOfRangeException( nameof( index ), "Indices for Color3 run from 0 to 2, inclusive." );
} }
} }
} }

View File

@ -231,10 +231,14 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: return R; case 0:
case 1: return G; return R;
case 2: return B; case 1:
case 3: return A; return G;
case 2:
return B;
case 3:
return A;
} }
throw new ArgumentOutOfRangeException( nameof( index ), "Indices for Color4 run from 0 to 3, inclusive." ); throw new ArgumentOutOfRangeException( nameof( index ), "Indices for Color4 run from 0 to 3, inclusive." );
@ -244,11 +248,20 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: R = value; break; case 0:
case 1: G = value; break; R = value;
case 2: B = value; break; break;
case 3: A = value; break; case 1:
default: throw new ArgumentOutOfRangeException(nameof(index), "Indices for Color4 run from 0 to 3, inclusive."); G = value;
break;
case 2:
B = value;
break;
case 3:
A = value;
break;
default:
throw new ArgumentOutOfRangeException( nameof( index ), "Indices for Color4 run from 0 to 3, inclusive." );
} }
} }
} }

View File

@ -189,10 +189,14 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: return B; case 0:
case 1: return G; return B;
case 2: return R; case 1:
case 3: return A; return G;
case 2:
return R;
case 3:
return A;
} }
throw new ArgumentOutOfRangeException( nameof( index ), "Indices for ColorBGRA run from 0 to 3, inclusive." ); throw new ArgumentOutOfRangeException( nameof( index ), "Indices for ColorBGRA run from 0 to 3, inclusive." );
@ -202,11 +206,20 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: B = value; break; case 0:
case 1: G = value; break; B = value;
case 2: R = value; break; break;
case 3: A = value; break; case 1:
default: throw new ArgumentOutOfRangeException(nameof(index), "Indices for ColorBGRA run from 0 to 3, inclusive."); G = value;
break;
case 2:
R = value;
break;
case 3:
A = value;
break;
default:
throw new ArgumentOutOfRangeException( nameof( index ), "Indices for ColorBGRA run from 0 to 3, inclusive." );
} }
} }
} }
@ -290,11 +303,15 @@ namespace math
max = r; max = r;
min = r; min = r;
if (g > max) max = g; if( g > max )
if (b > max) max = b; max = g;
if( b > max )
max = b;
if (g < min) min = g; if( g < min )
if (b < min) min = b; min = g;
if( b < min )
min = b;
return ( max + min ) / 2; return ( max + min ) / 2;
} }
@ -319,11 +336,15 @@ namespace math
max = r; max = r;
min = r; min = r;
if (g > max) max = g; if( g > max )
if (b > max) max = b; max = g;
if( b > max )
max = b;
if (g < min) min = g; if( g < min )
if (b < min) min = b; min = g;
if( b < min )
min = b;
delta = max - min; delta = max - min;
@ -364,11 +385,15 @@ namespace math
max = r; max = r;
min = r; min = r;
if (g > max) max = g; if( g > max )
if (b > max) max = b; max = g;
if( b > max )
max = b;
if (g < min) min = g; if( g < min )
if (b < min) min = b; min = g;
if( b < min )
min = b;
// if max == min, then there is no color and // if max == min, then there is no color and
// the saturation is zero. // the saturation is zero.

View File

@ -127,8 +127,10 @@ namespace math
/// <inheritdoc/> /// <inheritdoc/>
public override bool Equals( object obj ) public override bool Equals( object obj )
{ {
if (ReferenceEquals(null, obj)) return false; if( ReferenceEquals( null, obj ) )
if (obj.GetType() != typeof(ColorHSV)) return false; return false;
if( obj.GetType() != typeof( ColorHSV ) )
return false;
return Equals( (ColorHSV)obj ); return Equals( (ColorHSV)obj );
} }

View File

@ -124,8 +124,10 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: return X; case 0:
case 1: return Y; return X;
case 1:
return Y;
} }
throw new ArgumentOutOfRangeException( "index", "Indices for Double2 run from 0 to 1, inclusive." ); throw new ArgumentOutOfRangeException( "index", "Indices for Double2 run from 0 to 1, inclusive." );
@ -135,9 +137,14 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: X = value; break; case 0:
case 1: Y = value; break; X = value;
default: throw new ArgumentOutOfRangeException("index", "Indices for Double2 run from 0 to 1, inclusive."); break;
case 1:
Y = value;
break;
default:
throw new ArgumentOutOfRangeException( "index", "Indices for Double2 run from 0 to 1, inclusive." );
} }
} }
} }

View File

@ -152,9 +152,12 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: return X; case 0:
case 1: return Y; return X;
case 2: return Z; case 1:
return Y;
case 2:
return Z;
} }
throw new ArgumentOutOfRangeException( "index", "Indices for Double3 run from 0 to 2, inclusive." ); throw new ArgumentOutOfRangeException( "index", "Indices for Double3 run from 0 to 2, inclusive." );
@ -164,10 +167,17 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: X = value; break; case 0:
case 1: Y = value; break; X = value;
case 2: Z = value; break; break;
default: throw new ArgumentOutOfRangeException("index", "Indices for Double3 run from 0 to 2, inclusive."); case 1:
Y = value;
break;
case 2:
Z = value;
break;
default:
throw new ArgumentOutOfRangeException( "index", "Indices for Double3 run from 0 to 2, inclusive." );
} }
} }
} }

View File

@ -183,10 +183,14 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: return X; case 0:
case 1: return Y; return X;
case 2: return Z; case 1:
case 3: return W; return Y;
case 2:
return Z;
case 3:
return W;
} }
throw new ArgumentOutOfRangeException( "index", "Indices for Double4 run from 0 to 3, inclusive." ); throw new ArgumentOutOfRangeException( "index", "Indices for Double4 run from 0 to 3, inclusive." );
@ -196,11 +200,20 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: X = value; break; case 0:
case 1: Y = value; break; X = value;
case 2: Z = value; break; break;
case 3: W = value; break; case 1:
default: throw new ArgumentOutOfRangeException("index", "Indices for Double4 run from 0 to 3, inclusive."); Y = value;
break;
case 2:
Z = value;
break;
case 3:
W = value;
break;
default:
throw new ArgumentOutOfRangeException( "index", "Indices for Double4 run from 0 to 3, inclusive." );
} }
} }
} }

View File

@ -139,8 +139,10 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: return X; case 0:
case 1: return Y; return X;
case 1:
return Y;
} }
throw new ArgumentOutOfRangeException( "index", "Indices for Int2 run from 0 to 1, inclusive." ); throw new ArgumentOutOfRangeException( "index", "Indices for Int2 run from 0 to 1, inclusive." );
@ -150,9 +152,14 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: X = value; break; case 0:
case 1: Y = value; break; X = value;
default: throw new ArgumentOutOfRangeException("index", "Indices for Int2 run from 0 to 1, inclusive."); break;
case 1:
Y = value;
break;
default:
throw new ArgumentOutOfRangeException( "index", "Indices for Int2 run from 0 to 1, inclusive." );
} }
} }
} }

View File

@ -156,9 +156,12 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: return X; case 0:
case 1: return Y; return X;
case 2: return Z; case 1:
return Y;
case 2:
return Z;
} }
throw new ArgumentOutOfRangeException( "index", "Indices for Int3 run from 0 to 2, inclusive." ); throw new ArgumentOutOfRangeException( "index", "Indices for Int3 run from 0 to 2, inclusive." );
@ -168,10 +171,17 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: X = value; break; case 0:
case 1: Y = value; break; X = value;
case 2: Z = value; break; break;
default: throw new ArgumentOutOfRangeException("index", "Indices for Int3 run from 0 to 2, inclusive."); case 1:
Y = value;
break;
case 2:
Z = value;
break;
default:
throw new ArgumentOutOfRangeException( "index", "Indices for Int3 run from 0 to 2, inclusive." );
} }
} }
} }

View File

@ -453,7 +453,8 @@ namespace math
/// <returns>A linear value.</returns> /// <returns>A linear value.</returns>
public static float SRgbToLinear( float sRgbValue ) public static float SRgbToLinear( float sRgbValue )
{ {
if (sRgbValue < 0.04045f) return sRgbValue / 12.92f; if( sRgbValue < 0.04045f )
return sRgbValue / 12.92f;
return (float)Math.Pow( ( sRgbValue + 0.055 ) / 1.055, 2.4 ); return (float)Math.Pow( ( sRgbValue + 0.055 ) / 1.055, 2.4 );
} }
@ -464,7 +465,8 @@ namespace math
/// <returns>The encoded sRGB value.</returns> /// <returns>The encoded sRGB value.</returns>
public static float LinearToSRgb( float linearValue ) public static float LinearToSRgb( float linearValue )
{ {
if (linearValue < 0.0031308f) return linearValue * 12.92f; if( linearValue < 0.0031308f )
return linearValue * 12.92f;
return (float)( 1.055 * Math.Pow( linearValue, 1 / 2.4 ) - 0.055 ); return (float)( 1.055 * Math.Pow( linearValue, 1 / 2.4 ) - 0.055 );
} }

View File

@ -175,10 +175,22 @@ namespace math
float M31, float M32, float M33, float M34, float M31, float M32, float M33, float M34,
float M41, float M42, float M43, float M44 ) float M41, float M42, float M43, float M44 )
{ {
this.M11 = M11; this.M12 = M12; this.M13 = M13; this.M14 = M14; this.M11 = M11;
this.M21 = M21; this.M22 = M22; this.M23 = M23; this.M24 = M24; this.M12 = M12;
this.M31 = M31; this.M32 = M32; this.M33 = M33; this.M34 = M34; this.M13 = M13;
this.M41 = M41; this.M42 = M42; this.M43 = M43; this.M44 = M44; this.M14 = M14;
this.M21 = M21;
this.M22 = M22;
this.M23 = M23;
this.M24 = M24;
this.M31 = M31;
this.M32 = M32;
this.M33 = M33;
this.M34 = M34;
this.M41 = M41;
this.M42 = M42;
this.M43 = M43;
this.M44 = M44;
} }
/// <summary> /// <summary>
@ -400,22 +412,38 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: return M11; case 0:
case 1: return M12; return M11;
case 2: return M13; case 1:
case 3: return M14; return M12;
case 4: return M21; case 2:
case 5: return M22; return M13;
case 6: return M23; case 3:
case 7: return M24; return M14;
case 8: return M31; case 4:
case 9: return M32; return M21;
case 10: return M33; case 5:
case 11: return M34; return M22;
case 12: return M41; case 6:
case 13: return M42; return M23;
case 14: return M43; case 7:
case 15: return M44; return M24;
case 8:
return M31;
case 9:
return M32;
case 10:
return M33;
case 11:
return M34;
case 12:
return M41;
case 13:
return M42;
case 14:
return M43;
case 15:
return M44;
} }
throw new ArgumentOutOfRangeException( "index", "Indices for Matrix run from 0 to 15, inclusive." ); throw new ArgumentOutOfRangeException( "index", "Indices for Matrix run from 0 to 15, inclusive." );
@ -425,23 +453,56 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: M11 = value; break; case 0:
case 1: M12 = value; break; M11 = value;
case 2: M13 = value; break; break;
case 3: M14 = value; break; case 1:
case 4: M21 = value; break; M12 = value;
case 5: M22 = value; break; break;
case 6: M23 = value; break; case 2:
case 7: M24 = value; break; M13 = value;
case 8: M31 = value; break; break;
case 9: M32 = value; break; case 3:
case 10: M33 = value; break; M14 = value;
case 11: M34 = value; break; break;
case 12: M41 = value; break; case 4:
case 13: M42 = value; break; M21 = value;
case 14: M43 = value; break; break;
case 15: M44 = value; break; case 5:
default: throw new ArgumentOutOfRangeException("index", "Indices for Matrix run from 0 to 15, inclusive."); M22 = value;
break;
case 6:
M23 = value;
break;
case 7:
M24 = value;
break;
case 8:
M31 = value;
break;
case 9:
M32 = value;
break;
case 10:
M33 = value;
break;
case 11:
M34 = value;
break;
case 12:
M41 = value;
break;
case 13:
M42 = value;
break;
case 14:
M43 = value;
break;
case 15:
M44 = value;
break;
default:
throw new ArgumentOutOfRangeException( "index", "Indices for Matrix run from 0 to 15, inclusive." );
} }
} }
} }
@ -510,14 +571,26 @@ namespace math
{ {
float temp; float temp;
temp = M21; M21 = M12; M12 = temp; temp = M21;
temp = M31; M31 = M13; M13 = temp; M21 = M12;
temp = M41; M41 = M14; M14 = temp; M12 = temp;
temp = M31;
M31 = M13;
M13 = temp;
temp = M41;
M41 = M14;
M14 = temp;
temp = M32; M32 = M23; M23 = temp; temp = M32;
temp = M42; M42 = M24; M24 = temp; M32 = M23;
M23 = temp;
temp = M42;
M42 = M24;
M24 = temp;
temp = M43; M43 = M34; M34 = temp; temp = M43;
M43 = M34;
M34 = temp;
} }
/// <summary> /// <summary>
@ -1405,10 +1478,22 @@ namespace math
float d43 = value.M31 * -a4 + value.M32 * a2 + value.M34 * a0; float d43 = value.M31 * -a4 + value.M32 * a2 + value.M34 * a0;
float d44 = value.M31 * a3 + value.M32 * -a1 + value.M33 * a0; float d44 = value.M31 * a3 + value.M32 * -a1 + value.M33 * a0;
result.M11 = +d11 * det; result.M12 = -d21 * det; result.M13 = +d31 * det; result.M14 = -d41 * det; result.M11 = +d11 * det;
result.M21 = -d12 * det; result.M22 = +d22 * det; result.M23 = -d32 * det; result.M24 = +d42 * det; result.M12 = -d21 * det;
result.M31 = +d13 * det; result.M32 = -d23 * det; result.M33 = +d33 * det; result.M34 = -d43 * det; result.M13 = +d31 * det;
result.M41 = -d14 * det; result.M42 = +d24 * det; result.M43 = -d34 * det; result.M44 = +d44 * det; result.M14 = -d41 * det;
result.M21 = -d12 * det;
result.M22 = +d22 * det;
result.M23 = -d32 * det;
result.M24 = +d42 * det;
result.M31 = +d13 * det;
result.M32 = -d23 * det;
result.M33 = +d33 * det;
result.M34 = -d43 * det;
result.M41 = -d14 * det;
result.M42 = +d24 * det;
result.M43 = -d34 * det;
result.M44 = +d44 * det;
} }
/// <summary> /// <summary>
@ -1883,7 +1968,8 @@ namespace math
if( j != r ) if( j != r )
{ {
float sub = matrix[j, lead]; float sub = matrix[j, lead];
for (int k = 0; k < columncount; k++) matrix[j, k] -= (sub * matrix[r, k]); for( int k = 0; k < columncount; k++ )
matrix[j, k] -= ( sub * matrix[r, k] );
} }
} }
@ -1983,14 +2069,22 @@ namespace math
public static void LookAtLH( ref Vec3 eye, ref Vec3 target, ref Vec3 up, out Matrix result ) public static void LookAtLH( ref Vec3 eye, ref Vec3 target, ref Vec3 up, out Matrix result )
{ {
Vec3 xaxis, yaxis, zaxis; Vec3 xaxis, yaxis, zaxis;
Vec3.Subtract(ref target, ref eye, out zaxis); zaxis.Normalize(); Vec3.Subtract( ref target, ref eye, out zaxis );
Vec3.Cross(ref up, ref zaxis, out xaxis); xaxis.Normalize(); zaxis.Normalize();
Vec3.Cross( ref up, ref zaxis, out xaxis );
xaxis.Normalize();
Vec3.Cross( ref zaxis, ref xaxis, out yaxis ); Vec3.Cross( ref zaxis, ref xaxis, out yaxis );
result = Matrix.Identity; result = Matrix.Identity;
result.M11 = xaxis.X; result.M21 = xaxis.Y; result.M31 = xaxis.Z; result.M11 = xaxis.X;
result.M12 = yaxis.X; result.M22 = yaxis.Y; result.M32 = yaxis.Z; result.M21 = xaxis.Y;
result.M13 = zaxis.X; result.M23 = zaxis.Y; result.M33 = zaxis.Z; result.M31 = xaxis.Z;
result.M12 = yaxis.X;
result.M22 = yaxis.Y;
result.M32 = yaxis.Z;
result.M13 = zaxis.X;
result.M23 = zaxis.Y;
result.M33 = zaxis.Z;
Vec3.Dot( ref xaxis, ref eye, out result.M41 ); Vec3.Dot( ref xaxis, ref eye, out result.M41 );
Vec3.Dot( ref yaxis, ref eye, out result.M42 ); Vec3.Dot( ref yaxis, ref eye, out result.M42 );
@ -2025,14 +2119,22 @@ namespace math
public static void LookAtRH( ref Vec3 eye, ref Vec3 target, ref Vec3 up, out Matrix result ) public static void LookAtRH( ref Vec3 eye, ref Vec3 target, ref Vec3 up, out Matrix result )
{ {
Vec3 xaxis, yaxis, zaxis; Vec3 xaxis, yaxis, zaxis;
Vec3.Subtract(ref eye, ref target, out zaxis); zaxis.Normalize(); Vec3.Subtract( ref eye, ref target, out zaxis );
Vec3.Cross(ref up, ref zaxis, out xaxis); xaxis.Normalize(); zaxis.Normalize();
Vec3.Cross( ref up, ref zaxis, out xaxis );
xaxis.Normalize();
Vec3.Cross( ref zaxis, ref xaxis, out yaxis ); Vec3.Cross( ref zaxis, ref xaxis, out yaxis );
result = Matrix.Identity; result = Matrix.Identity;
result.M11 = xaxis.X; result.M21 = xaxis.Y; result.M31 = xaxis.Z; result.M11 = xaxis.X;
result.M12 = yaxis.X; result.M22 = yaxis.Y; result.M32 = yaxis.Z; result.M21 = xaxis.Y;
result.M13 = zaxis.X; result.M23 = zaxis.Y; result.M33 = zaxis.Z; result.M31 = xaxis.Z;
result.M12 = yaxis.X;
result.M22 = yaxis.Y;
result.M32 = yaxis.Z;
result.M13 = zaxis.X;
result.M23 = zaxis.Y;
result.M33 = zaxis.Z;
Vec3.Dot( ref xaxis, ref eye, out result.M41 ); Vec3.Dot( ref xaxis, ref eye, out result.M41 );
Vec3.Dot( ref yaxis, ref eye, out result.M42 ); Vec3.Dot( ref yaxis, ref eye, out result.M42 );

View File

@ -153,10 +153,14 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: return Normal.X; case 0:
case 1: return Normal.Y; return Normal.X;
case 2: return Normal.Z; case 1:
case 3: return D; return Normal.Y;
case 2:
return Normal.Z;
case 3:
return D;
} }
throw new ArgumentOutOfRangeException( "index", "Indices for Plane run from 0 to 3, inclusive." ); throw new ArgumentOutOfRangeException( "index", "Indices for Plane run from 0 to 3, inclusive." );
@ -166,11 +170,20 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: Normal.X = value; break; case 0:
case 1: Normal.Y = value; break; Normal.X = value;
case 2: Normal.Z = value; break; break;
case 3: D = value; break; case 1:
default: throw new ArgumentOutOfRangeException("index", "Indices for Plane run from 0 to 3, inclusive."); Normal.Y = value;
break;
case 2:
Normal.Z = value;
break;
case 3:
D = value;
break;
default:
throw new ArgumentOutOfRangeException( "index", "Indices for Plane run from 0 to 3, inclusive." );
} }
} }
} }

View File

@ -78,8 +78,10 @@ namespace math
/// <inheritdoc/> /// <inheritdoc/>
public override bool Equals( object obj ) public override bool Equals( object obj )
{ {
if (ReferenceEquals(null, obj)) return false; if( ReferenceEquals( null, obj ) )
if (obj.GetType() != typeof(Point)) return false; return false;
if( obj.GetType() != typeof( Point ) )
return false;
return Equals( (Point)obj ); return Equals( (Point)obj );
} }

View File

@ -244,10 +244,14 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: return X; case 0:
case 1: return Y; return X;
case 2: return Z; case 1:
case 3: return W; return Y;
case 2:
return Z;
case 3:
return W;
} }
throw new ArgumentOutOfRangeException( "index", "Indices for Quaternion run from 0 to 3, inclusive." ); throw new ArgumentOutOfRangeException( "index", "Indices for Quaternion run from 0 to 3, inclusive." );
@ -257,11 +261,20 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: X = value; break; case 0:
case 1: Y = value; break; X = value;
case 2: Z = value; break; break;
case 3: W = value; break; case 1:
default: throw new ArgumentOutOfRangeException("index", "Indices for Quaternion run from 0 to 3, inclusive."); Y = value;
break;
case 2:
Z = value;
break;
case 3:
W = value;
break;
default:
throw new ArgumentOutOfRangeException( "index", "Indices for Quaternion run from 0 to 3, inclusive." );
} }
} }
} }

View File

@ -425,8 +425,10 @@ namespace math
/// </returns> /// </returns>
public override bool Equals( object obj ) public override bool Equals( object obj )
{ {
if (ReferenceEquals(null, obj)) return false; if( ReferenceEquals( null, obj ) )
if (obj.GetType() != typeof(Rectangle)) return false; return false;
if( obj.GetType() != typeof( Rectangle ) )
return false;
return Equals( (Rectangle)obj ); return Equals( (Rectangle)obj );
} }

View File

@ -418,8 +418,10 @@ namespace math
/// </returns> /// </returns>
public override bool Equals( object obj ) public override bool Equals( object obj )
{ {
if (ReferenceEquals(null, obj)) return false; if( ReferenceEquals( null, obj ) )
if (obj.GetType() != typeof(RectangleF)) return false; return false;
if( obj.GetType() != typeof( RectangleF ) )
return false;
return Equals( (RectangleF)obj ); return Equals( (RectangleF)obj );
} }

View File

@ -83,8 +83,10 @@ namespace math
/// <inheritdoc/> /// <inheritdoc/>
public override bool Equals( object obj ) public override bool Equals( object obj )
{ {
if (ReferenceEquals(null, obj)) return false; if( ReferenceEquals( null, obj ) )
if (obj.GetType() != typeof(Size2)) return false; return false;
if( obj.GetType() != typeof( Size2 ) )
return false;
return Equals( (Size2)obj ); return Equals( (Size2)obj );
} }

View File

@ -83,8 +83,10 @@ namespace math
/// <inheritdoc/> /// <inheritdoc/>
public override bool Equals( object obj ) public override bool Equals( object obj )
{ {
if (ReferenceEquals(null, obj)) return false; if( ReferenceEquals( null, obj ) )
if (obj.GetType() != typeof(Size2F)) return false; return false;
if( obj.GetType() != typeof( Size2F ) )
return false;
return Equals( (Size2F)obj ); return Equals( (Size2F)obj );
} }

View File

@ -101,7 +101,8 @@ namespace math
/// <inheritdoc/> /// <inheritdoc/>
public override bool Equals( object obj ) public override bool Equals( object obj )
{ {
if (ReferenceEquals(null, obj)) return false; if( ReferenceEquals( null, obj ) )
return false;
return obj is Size3 && Equals( (Size3)obj ); return obj is Size3 && Equals( (Size3)obj );
} }

View File

@ -138,8 +138,10 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: return X; case 0:
case 1: return Y; return X;
case 1:
return Y;
} }
throw new ArgumentOutOfRangeException( "index", "Indices for Vector2 run from 0 to 1, inclusive." ); throw new ArgumentOutOfRangeException( "index", "Indices for Vector2 run from 0 to 1, inclusive." );
@ -149,9 +151,14 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: X = value; break; case 0:
case 1: Y = value; break; X = value;
default: throw new ArgumentOutOfRangeException("index", "Indices for Vector2 run from 0 to 1, inclusive."); break;
case 1:
Y = value;
break;
default:
throw new ArgumentOutOfRangeException( "index", "Indices for Vector2 run from 0 to 1, inclusive." );
} }
} }
} }

View File

@ -166,9 +166,12 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: return X; case 0:
case 1: return Y; return X;
case 2: return Z; case 1:
return Y;
case 2:
return Z;
} }
throw new ArgumentOutOfRangeException( "index", "Indices for Vector3 run from 0 to 2, inclusive." ); throw new ArgumentOutOfRangeException( "index", "Indices for Vector3 run from 0 to 2, inclusive." );
@ -178,10 +181,17 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: X = value; break; case 0:
case 1: Y = value; break; X = value;
case 2: Z = value; break; break;
default: throw new ArgumentOutOfRangeException("index", "Indices for Vector3 run from 0 to 2, inclusive."); case 1:
Y = value;
break;
case 2:
Z = value;
break;
default:
throw new ArgumentOutOfRangeException( "index", "Indices for Vector3 run from 0 to 2, inclusive." );
} }
} }
} }

View File

@ -195,10 +195,14 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: return X; case 0:
case 1: return Y; return X;
case 2: return Z; case 1:
case 3: return W; return Y;
case 2:
return Z;
case 3:
return W;
} }
throw new ArgumentOutOfRangeException( "index", "Indices for Vector4 run from 0 to 3, inclusive." ); throw new ArgumentOutOfRangeException( "index", "Indices for Vector4 run from 0 to 3, inclusive." );
@ -208,11 +212,20 @@ namespace math
{ {
switch( index ) switch( index )
{ {
case 0: X = value; break; case 0:
case 1: Y = value; break; X = value;
case 2: Z = value; break; break;
case 3: W = value; break; case 1:
default: throw new ArgumentOutOfRangeException("index", "Indices for Vector4 run from 0 to 3, inclusive."); Y = value;
break;
case 2:
Z = value;
break;
case 3:
W = value;
break;
default:
throw new ArgumentOutOfRangeException( "index", "Indices for Vector4 run from 0 to 3, inclusive." );
} }
} }
} }

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;

View File

@ -15,17 +15,21 @@ namespace Tracing
// No need to override GetHashCode because we don't want to use it as a key in a dictionary // No need to override GetHashCode because we don't want to use it as a key in a dictionary
public override bool Equals( object obj ) public override bool Equals( object obj )
{ {
if (obj == null) return false; if( obj == null )
return false;
var stack = obj as AddressStack; var stack = obj as AddressStack;
if (stack == null) return false; if( stack == null )
return false;
var frameCount = _stack.Count; var frameCount = _stack.Count;
if (frameCount != stack._stack.Count) return false; if( frameCount != stack._stack.Count )
return false;
for( int i = 0; i < frameCount; i++ ) for( int i = 0; i < frameCount; i++ )
{ {
if (_stack[i] != stack._stack[i]) return false; if( _stack[i] != stack._stack[i] )
return false;
} }
return true; return true;

View File

@ -144,7 +144,8 @@ namespace ProfilerHelpers
if( baseAddress == 0 ) if( baseAddress == 0 )
{ {
// should work if the same module is added more than once // should work if the same module is added more than once
if (Marshal.GetLastWin32Error() == ERROR_SUCCESS) return; if( Marshal.GetLastWin32Error() == ERROR_SUCCESS )
return;
Console.WriteLine( $"SymLoadModule64 failed for {filename}" ); Console.WriteLine( $"SymLoadModule64 failed for {filename}" );
} }

View File

@ -20,7 +20,8 @@ namespace Tracing
public void Dispose() public void Dispose()
{ {
if (_disposed) return; if( _disposed )
return;
_disposed = true; _disposed = true;
foreach( var methodStore in _methods.Values ) foreach( var methodStore in _methods.Values )

View File

@ -107,7 +107,8 @@ namespace Tracing
for( int i = 0; i < _stacks.Count; i++ ) for( int i = 0; i < _stacks.Count; i++ )
{ {
var info = _stacks[i]; var info = _stacks[i];
if (stack.Equals(info.Stack)) return info; if( stack.Equals( info.Stack ) )
return info;
} }
return null; return null;

View File

@ -67,7 +67,8 @@ public static class scr
public static FieldInfo? GetFieldInfo( Type? t, string name ) public static FieldInfo? GetFieldInfo( Type? t, string name )
{ {
if (t == null) return null; if( t == null )
return null;
var fi = t.GetField( name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly ); var fi = t.GetField( name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly );
@ -82,7 +83,8 @@ public static class scr
// From stack overflow // From stack overflow
static Lazy<ISet<Type>> typeSetLazy = static Lazy<ISet<Type>> typeSetLazy =
new Lazy<ISet<Type>>(() => { new Lazy<ISet<Type>>( () =>
{
var types = AppDomain var types = AppDomain
.CurrentDomain .CurrentDomain
.GetAssemblies() .GetAssemblies()
@ -115,14 +117,16 @@ public static class scr
for( int i = 0; i < safeStr.Length; ++i ) for( int i = 0; i < safeStr.Length; ++i )
{ {
if( s_badChars.Contains(safeStr[i]) ) safeStr[i] = '_'; if( s_badChars.Contains( safeStr[i] ) )
safeStr[i] = '_';
} }
return safeStr.ToString(); return safeStr.ToString();
} }
static public FileSystemWatcher s_watcher = new(); static public FileSystemWatcher s_watcher = new();
static public Action<Assembly> s_fnAss = (ass) => { static public Action<Assembly> s_fnAss = ( ass ) =>
{
log.warn( $"Need to replace s_fnAss with custom function" ); log.warn( $"Need to replace s_fnAss with custom function" );
}; };

View File

@ -17,6 +17,52 @@ namespace ser;
#region Attributes & Enums (Mostly unchanged, ensure these exist) #region Attributes & Enums (Mostly unchanged, ensure these exist)
/*
public CoolClass
{
private string Rare = "Rare Change";
private float TestF = 1.0f;
}
public class Bag
{
public string Owner { get; set; }
public CoolClass Cool { get; set; } = new();
}
public class BasicTest
{
public Bag MyBag { get; set; } = new();
}
<root>
<MyBag Owner="John" Cool.Rare="Changed" >
<Cool TestF="2.5" />
</MyBag>
</root>
public abstract class Item
{
public int Id { get; set; }
}
public class Key : Item
{
public int Code { get; set; }
}
public class Orb : Item
{
private float Power = 1.0f;
public bool IsDark = true;
}
*/
public interface I_Serialize public interface I_Serialize
{ {
@ -708,7 +754,8 @@ public class XmlSer // : IFormatter
} }
catch( Exception ex ) catch( Exception ex )
{ {
log.exception( ex, $"XML Load failed: {ex.Message}" ); return; log.exception( ex, $"XML Load failed: {ex.Message}" );
return;
} }
if( doc.DocumentElement == null ) if( doc.DocumentElement == null )

View File

@ -150,7 +150,8 @@ public partial class ObjectHandler : ITypeHandler
{ {
foreach( var memberMeta in ti.Members ) foreach( var memberMeta in ti.Members )
{ {
if( !memberMeta.IsPodAttribute ) continue; if( !memberMeta.IsPodAttribute )
continue;
var value = memberMeta.GetValue( obj ); var value = memberMeta.GetValue( obj );
if( value != null ) if( value != null )
@ -169,7 +170,8 @@ public partial class ObjectHandler : ITypeHandler
foreach( var memberMeta in ti.Members ) foreach( var memberMeta in ti.Members )
{ {
if( memberMeta.IsPodAttribute ) continue; if( memberMeta.IsPodAttribute )
continue;
var value = memberMeta.GetValue( obj ); var value = memberMeta.GetValue( obj );
if( value != null ) if( value != null )

View File

@ -1,4 +1,4 @@

Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 17
VisualStudioVersion = 17.5.002.0 VisualStudioVersion = 17.5.002.0

View File

@ -1,4 +1,4 @@

Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 17
VisualStudioVersion = 17.5.002.0 VisualStudioVersion = 17.5.002.0

375
srl/srl.Core.cs Normal file
View File

@ -0,0 +1,375 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
namespace srl;
// --- INTERFACES ---
public interface Driver
{
// Structural
void BeginScope( string name, Type type, int id );
void EndScope();
void BeginCollection( string name, int count );
void EndCollection();
// Data
void WriteAttr( string name, string value ); // Primitives & Compact Strings
void WriteRef( string name, int id ); // DAG/Cycle Reference
// Metadata Hook
void OnProp( MemberInfo member, string name );
}
public interface IInput
{
string? Value { get; }
bool IsLeaf { get; }
IInput? GetAttr( string name );
IInput? GetChild( string name );
}
// --- THE MODEL (Introspection) ---
public class TypePlan
{
public string Name;
public bool IsCollection;
public bool IsHybrid; // True if Type has a StringParser registered
public StringParser Parser; // The "Compact" converter
public List<PropPlan> Props = new();
}
public class PropPlan
{
public string Name;
public string MemberName;
public Type Type;
public bool IsSmart; // Primitive/Enum/String
public MemberInfo Info;
// Fast Accessors
public Func<object, object?> Getter;
public Action<object, object?> Setter;
}
public static class Model
{
private static Dictionary<Type, TypePlan> _cache = new();
public static TypePlan Get( Type t )
{
if( _cache.TryGetValue( t, out var plan ) )
return plan;
plan = new TypePlan { Name = t.Name };
// 1. Check for Custom Parsers (Hybrid Mode)
if( Parsers.TryGet( t, out var parser ) )
{
plan.IsHybrid = true;
plan.Parser = parser;
}
// 2. Check for Collections
if( t != typeof( string ) && typeof( IEnumerable ).IsAssignableFrom( t ) )
{
plan.IsCollection = true;
_cache[t] = plan;
return plan;
}
// 3. Scan Properties
foreach( var p in t.GetProperties( BindingFlags.Public | BindingFlags.Instance ) )
{
if( Attribute.IsDefined( p, typeof( IgnoreAttribute ) ) )
continue;
var prop = new PropPlan
{
Name = p.Name, // Default to PascalCase, Drivers can lower if needed
MemberName = p.Name,
Type = p.PropertyType,
Info = p,
Getter = ( o ) => p.GetValue( o ),
Setter = ( o, v ) => p.SetValue( o, v )
};
// Override name
var nameAttr = p.GetCustomAttribute<NameAttribute>();
if( nameAttr != null )
prop.Name = nameAttr.Name;
// Is "Smart" (Atomic)?
prop.IsSmart = prop.Type.IsPrimitive || prop.Type.IsEnum ||
prop.Type == typeof( string ) || prop.Type == typeof( Guid );
plan.Props.Add( prop );
}
_cache[t] = plan;
return plan;
}
}
// --- ATTRIBUTES ---
public class IgnoreAttribute : Attribute { }
public class NameAttribute : Attribute { public string Name; public NameAttribute( string n ) => Name = n; }
// --- UTILITIES ---
public struct StringParser
{
public Func<object, string> To;
public Func<string, object> From;
}
public static class Parsers
{
private static Dictionary<Type, StringParser> _registry = new();
public static void Register<T>( Func<T, string> to, Func<string, T> from )
{
_registry[typeof( T )] = new StringParser { To = o => to( (T)o ), From = s => from( s ) };
}
public static bool TryGet( Type t, out StringParser p )
{
if( _registry.TryGetValue( t, out p ) )
return true;
// Auto-Discovery could go here (Static Parse methods)
return false;
}
}
public static class Binder
{
// Handles "Cool.Rare" dot notation
public static void Apply( object root, string path, string value )
{
var current = root;
var parts = path.Split( '.' );
for( int i = 0; i < parts.Length; i++ )
{
var part = parts[i];
var isLast = i == parts.Length - 1;
var plan = Model.Get( current.GetType() );
// Case-Insensitive Match
var prop = plan.Props.Find( p => p.Name.Equals( part, StringComparison.OrdinalIgnoreCase ) );
if( prop == null )
return;
if( isLast )
{
var val = ParseUtils.Convert( value, prop.Type );
prop.Setter( current, val );
}
else
{
var next = prop.Getter( current );
if( next == null )
{
next = Activator.CreateInstance( prop.Type );
prop.Setter( current, next );
}
current = next;
}
}
}
}
public static class ParseUtils
{
public static object Convert( string raw, Type t )
{
if( t == typeof( string ) )
return raw;
if( t == typeof( int ) )
return int.Parse( raw );
if( t == typeof( float ) )
return float.Parse( raw.Replace( "f", "" ) );
if( t == typeof( bool ) )
return bool.Parse( raw );
if( t.IsEnum )
return Enum.Parse( t, raw );
// Fallback to TypeConverter
var cv = TypeDescriptor.GetConverter( t );
if( cv != null && cv.CanConvertFrom( typeof( string ) ) )
return cv.ConvertFrom( raw );
return null;
}
public static void CopyFields( object src, object dst )
{
foreach( var p in src.GetType().GetProperties() )
if( p.CanRead && p.CanWrite )
p.SetValue( dst, p.GetValue( src ) );
}
}
// --- THE ENGINE (Walker & Loader) ---
public static class Walker
{
public class Context
{
private Dictionary<object, int> _seen = new( ReferenceEqualityComparer.Instance );
private int _nextId = 1;
public (int, bool) GetId( object o )
{
if( _seen.TryGetValue( o, out var id ) )
return (id, false);
_seen[o] = _nextId;
return (_nextId++, true);
}
}
public static void Serialize( object root, Driver d )
{
if( root == null )
return;
SerializeRecursive( root, d, new Context(), "root", null );
}
private static void SerializeRecursive( object obj, Driver d, Context ctx, string name, MemberInfo? member )
{
if( obj == null )
return;
Type type = obj.GetType();
var plan = Model.Get( type );
// STRATEGY 1: COMPACT (Hybrid Parser)
if( plan.IsHybrid )
{
if( member != null )
d.OnProp( member, name );
d.WriteAttr( name, plan.Parser.To( obj ) );
return;
}
// STRATEGY 2: DAG CHECK
bool isRef = !type.IsValueType && type != typeof( string );
if( isRef )
{
var (id, isNew) = ctx.GetId( obj );
if( !isNew )
{ d.WriteRef( name, id ); return; }
if( member != null )
d.OnProp( member, name );
d.BeginScope( name, type, id );
}
else
{
if( member != null )
d.OnProp( member, name );
d.BeginScope( name, type, 0 );
}
// STRATEGY 3: COLLECTIONS
if( plan.IsCollection )
{
var list = (IEnumerable)obj;
int count = 0; // Simple count (could optimize for ICollection)
foreach( var _ in list )
count++;
d.BeginCollection( name, count );
foreach( var item in list )
SerializeRecursive( item, d, ctx, "item", null );
d.EndCollection();
}
else
{
// STRATEGY 4: STANDARD OBJECT
foreach( var prop in plan.Props )
{
var val = prop.Getter( obj );
if( prop.IsSmart )
{
d.OnProp( prop.Info, prop.Name );
d.WriteAttr( prop.Name, val?.ToString() ?? "" );
}
else
{
if( val != null )
SerializeRecursive( val, d, ctx, prop.Name, prop.Info );
}
}
}
d.EndScope();
}
}
public static class Loader
{
public static void Load( object target, IInput input )
{
if( target == null || input == null )
return;
var plan = Model.Get( target.GetType() );
// 1. HYBRID PARSE (Compact String)
// If we have a parser AND input is just a value "1,1"
if( plan.IsHybrid && input.IsLeaf && !string.IsNullOrWhiteSpace( input.Value ) )
{
try
{
var newObj = plan.Parser.From( input.Value );
ParseUtils.CopyFields( newObj, target );
return;
}
catch { }
}
// 2. STRUCTURAL MAP
foreach( var prop in plan.Props )
{
// Look for Attribute OR Child Element
var sub = input.GetAttr( prop.Name ) ?? input.GetChild( prop.Name );
// Look for Dot Notation (e.g. "Pos.X") in attributes
// (Note: This simple loop doesn't scan ALL attrs for dots,
// it relies on the caller or specific recursive logic.
// For full dot support on root, we need to iterate input attributes if possible.
// But 'Binder' below handles it if we pass the specific attr key).
if( sub != null )
{
if( prop.IsSmart )
{
if( sub.Value != null )
prop.Setter( target, ParseUtils.Convert( sub.Value, prop.Type ) );
}
else
{
var child = prop.Getter( target );
if( child == null )
{
child = Activator.CreateInstance( prop.Type );
prop.Setter( target, child );
}
Load( child, sub );
}
}
}
}
// Helper to scan all attributes on an element for "Cool.Rare" patterns
public static void LoadDotNotations( object target, IEnumerable<(string k, string v)> attrs )
{
foreach( var (k, v) in attrs )
{
if( k.Contains( '.' ) )
Binder.Apply( target, k, v );
}
}
}

47
srl/srl.Debug.cs Normal file
View File

@ -0,0 +1,47 @@
using System;
using System.Reflection;
using System.Text;
namespace srl.Debug;
public class DebugDriver : Driver
{
private StringBuilder _sb = new();
private int _indent = 0;
public override string ToString() => _sb.ToString();
private void Line( string s ) => _sb.AppendLine( new string( ' ', _indent * 2 ) + s );
public void BeginScope( string name, Type type, int id )
{
var refStr = id > 0 ? $" #{id}" : "";
Line( $"[{name}] <{type.Name}>{refStr}" );
_indent++;
}
public void EndScope() => _indent--;
public void BeginCollection( string name, int count )
{
Line( $"[{name}] (Count: {count})" );
_indent++;
}
public void EndCollection() => _indent--;
public void WriteAttr( string name, string value )
{
Line( $"{name} = {value}" );
}
public void WriteRef( string name, int id )
{
Line( $"{name} -> See #{id}" );
}
public void OnProp( MemberInfo m, string name )
{
// Could log attributes here, e.g. [Tooltip]
}
}

131
srl/srl.Xml.cs Normal file
View File

@ -0,0 +1,131 @@
using System;
using System.Collections.Generic;
using System.Xml.Linq;
using System.Reflection;
namespace srl.Xml;
// --- INPUT ADAPTER ---
public class XmlAdapter : IInput
{
private XElement _e;
private XAttribute _a;
public XmlAdapter( XElement e ) => _e = e;
public XmlAdapter( XAttribute a ) => _a = a;
public string? Value => _e?.Value ?? _a?.Value;
public bool IsLeaf => _a != null || ( _e != null && !_e.HasElements );
public IInput? GetAttr( string name )
{
if( _e == null )
return null;
// Case-Insensitive search
var a = _e.Attribute( name ) ?? _e.Attribute( name.ToLower() );
return a != null ? new XmlAdapter( a ) : null;
}
public IInput? GetChild( string name )
{
if( _e == null )
return null;
var c = _e.Element( name ) ?? _e.Element( name.ToLower() );
return c != null ? new XmlAdapter( c ) : null;
}
// Extra helper for Dot Notation scanning
public IEnumerable<(string, string)> GetAllAttrs()
{
if( _e == null )
yield break;
foreach( var a in _e.Attributes() )
yield return (a.Name.LocalName, a.Value);
}
}
// --- OUTPUT DRIVER ---
public class XmlDriver : Driver
{
private Stack<XElement> _stack = new();
private XDocument _doc;
public XDocument Document => _doc;
public XmlDriver()
{
_doc = new XDocument();
}
public void BeginScope( string name, Type type, int id )
{
var el = new XElement( name );
// Polymorphism Metadata (if needed, e.g. <Item type="Sword">)
// el.Add(new XAttribute("_type", type.Name));
if( id > 0 )
el.Add( new XAttribute( "_id", id ) ); // DAG ID
if( _stack.Count > 0 )
_stack.Peek().Add( el );
else
_doc.Add( el );
_stack.Push( el );
}
public void EndScope() => _stack.Pop();
public void BeginCollection( string name, int count )
{
// XML doesn't strictly need array wrappers, but it helps structure
// We use the same BeginScope logic effectively
var el = new XElement( name, new XAttribute( "_count", count ) );
if( _stack.Count > 0 )
_stack.Peek().Add( el );
_stack.Push( el );
}
public void EndCollection() => _stack.Pop();
public void WriteAttr( string name, string value )
{
if( _stack.Count == 0 )
return;
_stack.Peek().Add( new XAttribute( name, value ) );
}
public void WriteRef( string name, int id )
{
var el = new XElement( name, new XAttribute( "_ref", id ) );
_stack.Peek().Add( el );
}
public void OnProp( MemberInfo m, string name ) { /* Optional: Write tooltips/comments */ }
}
// --- FACADE ---
public static class XmlSerializer
{
public static string Serialize( object obj )
{
var driver = new XmlDriver();
srl.Walker.Serialize( obj, driver );
return driver.Document.ToString();
}
public static void Deserialize( object root, string xml )
{
var doc = XDocument.Parse( xml );
var adapter = new XmlAdapter( doc.Root );
// 1. Standard Load
srl.Loader.Load( root, adapter );
// 2. Dot Notation Pass (MyBag Cool.Rare="Changed")
srl.Loader.LoadDotNotations( root, adapter.GetAllAttrs() );
}
}