diff --git a/StgSharp.Common/Collections/ListSegment.cs b/StgSharp.Common/Collections/ListSegment.cs index 54fb0c39..73efea66 100644 --- a/StgSharp.Common/Collections/ListSegment.cs +++ b/StgSharp.Common/Collections/ListSegment.cs @@ -1,4 +1,34 @@ -using System; +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// file="ListSegment.cs" +// Project: StgSharp +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and +// this permission notice shall be included in all copies +// or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, +// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +using System; using System.Collections; using System.Collections.Generic; using System.Linq; @@ -10,42 +40,67 @@ using System.Xml.Serialization; namespace StgSharp.Collections { /// - /// Part of a collection. This contains a direct reference to origin collection, - /// so all change to origin collection will be reflected in this object. + /// Part of a collection. This contains a direct reference to _origin collection, so all change + /// to _origin collection will be reflected in this object. /// /// public struct ListSegment : ICollection { - private List _collection; + private int _begin; private int _length; + private List _collection; - - public ListSegment(List collection, int begin, int length) + public ListSegment( List collection, int begin, int length ) { - ArgumentNullException.ThrowIfNull(collection); - ArgumentOutOfRangeException.ThrowIfLessThan(begin, 0); - ArgumentOutOfRangeException.ThrowIfLessThan(length, 0); - ArgumentOutOfRangeException.ThrowIfLessThan(begin + length, collection.Count); + ArgumentNullException.ThrowIfNull( collection ); + ArgumentOutOfRangeException.ThrowIfLessThan( begin, 0 ); + ArgumentOutOfRangeException.ThrowIfLessThan( length, 0 ); + ArgumentOutOfRangeException.ThrowIfLessThan( + begin + length, collection.Count ); _collection = collection; _begin = begin; _length = length; - } + } - public int Count => _length; - - public bool IsReadOnly => true; - - public T this[int indexValue] + public T this[ int indexValue ] { - get { - ArgumentOutOfRangeException.ThrowIfLessThan(indexValue, 0); - ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(indexValue, _length); - return _collection[indexValue + _begin]; + get + { + ArgumentOutOfRangeException.ThrowIfLessThan( indexValue, 0 ); + ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual( + indexValue, _length ); + return _collection[ indexValue + _begin ]; } } - void ICollection.Add(T item) + public bool IsReadOnly => true; + + public int Count => _length; + + public bool Contains( T item ) + { + int index = _collection.IndexOf( item ); + return index >= _begin && index < _length + index; + } + + public void CopyTo( T[] array, int arrayIndex ) + { + ArgumentNullException.ThrowIfNull( array ); + Span span = CollectionsMarshal.AsSpan( _collection ) + .Slice( _begin, _length ); + Span target = new Span( array, arrayIndex, _length ); + span.CopyTo( target ); + } + + public IEnumerator GetEnumerator() + { + for( int i = _begin; i < _length; i++ ) { + yield return this[ i ]; + } + } + + void ICollection.Add( T item ) { throw new NotSupportedException(); } @@ -55,29 +110,7 @@ namespace StgSharp.Collections throw new NotSupportedException(); } - public bool Contains(T item) - { - var index= _collection.IndexOf(item); - return index >= _begin && index < _length + index; - } - - public void CopyTo(T[] array, int arrayIndex) - { - ArgumentNullException.ThrowIfNull(array); - var span = CollectionsMarshal.AsSpan(_collection).Slice(_begin, _length); - var target = new Span(array, arrayIndex,_length); - span.CopyTo(target); - } - - public IEnumerator GetEnumerator() - { - for (int i = _begin; i < _length; i++) - { - yield return this[i]; - } - } - - bool ICollection.Remove(T item) + bool ICollection.Remove( T item ) { throw new NotSupportedException(); } @@ -86,5 +119,6 @@ namespace StgSharp.Collections { return GetEnumerator(); } + } } diff --git a/StgSharp.Common/Counter.cs b/StgSharp.Common/Counter.cs new file mode 100644 index 00000000..28045a5a --- /dev/null +++ b/StgSharp.Common/Counter.cs @@ -0,0 +1,117 @@ +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// file="Counter.cs" +// Project: StgSharp +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and +// this permission notice shall be included in all copies +// or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, +// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +using System; +using System.Numerics; + +namespace StgSharp +{ + public class Counter where T: struct, INumber + { + + internal dynamic _value; + internal readonly T _defaultValue; + internal readonly T _defualtDecreament; + + internal readonly T _defualtIncreament; + + public Counter( + T defualtValue, + T defualtIncreament, + T defualtDecreament ) + { + _value = defualtValue; + _defaultValue = defualtValue; + _defualtIncreament = defualtIncreament; + _defualtDecreament = defualtDecreament; + } + + public T DecreamentSoan => _defualtDecreament; + + public T IncreamentSpan => _defualtIncreament; + + public T CurrentSpan => _value - _defaultValue; + + public T Value + { + get => _value; + set => _value = value; + } + + public void Add( T value ) + { + _value += value; + } + + public void QuickAdd() + { + _value += _defualtIncreament; + } + + public void QuickSub() + { + _value -= _defualtDecreament; + } + + public void Reset() + { + _value = _defaultValue; + } + + public void Sub( T value ) + { + _value -= value; + } + + public override string ToString() => Value.ToString(); + + public static Counter operator --( Counter counter ) + { + counter.QuickSub(); + return counter; + } + + public static Counter operator ++( Counter counter ) + { + counter.QuickAdd(); + return counter; + } + + public static implicit operator T( Counter counter ) + { + return counter switch + { + null => T.Zero, + _ => counter.Value + }; + } + + } +} \ No newline at end of file diff --git a/StgSharp.Common/Data/ValueBox.cs b/StgSharp.Common/Data/ValueBox.cs index 31a8111c..9bf6bd74 100644 --- a/StgSharp.Common/Data/ValueBox.cs +++ b/StgSharp.Common/Data/ValueBox.cs @@ -75,7 +75,7 @@ namespace StgSharp.Data /// /// A class attempt to reduce cost of boxing, though still a bit slower than direct access to - /// origin value type instance. + /// _origin value type instance. /// /// Type of instance to be boxed. public class ValueBox : IValueBox, IValueBox where T: struct diff --git a/StgSharp.Common/Geometries/IInstancing.cs b/StgSharp.Common/Geometries/IInstancing.cs index 33e26535..2c1162d9 100644 --- a/StgSharp.Common/Geometries/IInstancing.cs +++ b/StgSharp.Common/Geometries/IInstancing.cs @@ -88,7 +88,7 @@ namespace StgSharp.Geometries { get { return GlobalBuffer.CoordAndRotationList[ BufferId ].XYZ; } set { GlobalBuffer.CoordAndRotationList[ BufferId ] = new Vec4( - value.vec ); } + value.reg ); } } public void Move() diff --git a/StgSharp.Common/Geometries/PlainGeometry/Cordinate.cs b/StgSharp.Common/Geometries/PlainGeometry/Cordinate.cs index b90df786..e16686bf 100644 --- a/StgSharp.Common/Geometries/PlainGeometry/Cordinate.cs +++ b/StgSharp.Common/Geometries/PlainGeometry/Cordinate.cs @@ -47,14 +47,14 @@ namespace StgSharp.Geometries internal Matrix32 axis; /// - /// The origin of this coordinate. + /// The _origin of this coordinate. /// public Vec3 origin; public PartialPlainCoordinate( - Vec3 origin, - Vec3 horiziontial, - Vec3 vertical ) + Vec3 origin, + Vec3 horiziontial, + Vec3 vertical ) { this.origin = origin; axis = new Matrix32(); diff --git a/StgSharp.Common/Geometries/PlainGeometry/Plain.cs b/StgSharp.Common/Geometries/PlainGeometry/Plain.cs index 2338a379..98ea38b6 100644 --- a/StgSharp.Common/Geometries/PlainGeometry/Plain.cs +++ b/StgSharp.Common/Geometries/PlainGeometry/Plain.cs @@ -38,30 +38,22 @@ namespace StgSharp.Geometries { internal readonly float d = -1; - internal Vec3 origin; + internal Vec3 _origin; internal Vec3 plainParameter; internal Vec3 vec1; internal Vec3 vec2; - internal Plain( Vector4 origin, Vector4 p1, Vector4 p2 ) - { - this.origin = new Vec3( origin ); - - vec1 = new Vec3( p1 - origin ); - vec2 = new Vec3( p2 - origin ); - } - public Plain( Vec3 o, Vec3 v1, Vec3 v2 ) { - this.origin = o; - this.vec1 = v1 - ( v2 * ( v1.Y / v2.Y ) ); //计算平面在xz平面上的方向投影 - this.vec2 = v2 - ( vec1 * ( v2.X / v1.X ) ); //计算平面在yz平面上的方向投影 + this._origin = o; + this.vec1 = v1 - ( v2 * ( v1.Y / v2.Y ) ); //xz + this.vec2 = v2 - ( vec1 * ( v2.X / v1.X ) ); //yz - //|origin|-k1*|vec1|-k2*|vec2|计算plainParameter.Z; - plainParameter.Z = origin.Z - ( vec1.Z * ( origin.X / vec1.X ) ) - ( vec2.Z * ( origin.Y / vec2.Y ) ); + //|_origin|-k1*|vec1|-k2*|vec2| --> plainParameter.Z; + plainParameter.Z = _origin.Z - ( vec1.Z * ( _origin.X / vec1.X ) ) - ( vec2.Z * ( _origin.Y / vec2.Y ) ); - //根据plainParameter.Z和对应的方向矢量计算plainParameter.X和plainParameter.Y + //plainParameter.Z -> plainParameter.X, plainParameter.Y plainParameter.X = vec1.X * ( vec1.Z / plainParameter.Z ); plainParameter.Y = vec2.Y * ( vec2.Z / plainParameter.Z ); @@ -77,13 +69,13 @@ namespace StgSharp.Geometries Vec3 v2 = p3.Coord - origin; - vec1 = v1 - ( v2 * ( v1.Y / v2.Y ) ); //计算平面在xz平面上的方向投影 - vec2 = v2 - ( vec1 * ( v2.X / v1.X ) ); //计算平面在yz平面上的方向投影 + vec1 = v1 - ( v2 * ( v1.Y / v2.Y ) ); //xz + vec2 = v2 - ( vec1 * ( v2.X / v1.X ) ); //yz - //|origin|-k1*|vec1|-k2*|vec2|计算plainParameter.Z; + //|_origin|-k1*|vec1|-k2*|vec2| --> plainParameter.Z; plainParameter.Z = origin.Z - ( vec1.Z * ( origin.X / vec1.X ) ) - ( vec2.Z * ( origin.Y / vec2.Y ) ); - //根据plainParameter.Z和对应的方向矢量计算plainParameter.X和plainParameter.Y + //plainParameter.Z --> plainParameter.X, plainParameter.Y plainParameter.X = vec1.X * ( vec1.Z / plainParameter.Z ); plainParameter.Y = vec2.Y * ( vec2.Z / plainParameter.Z ); diff --git a/StgSharp.Common/Geometries/PlainGeometry/Polygon6.cs b/StgSharp.Common/Geometries/PlainGeometry/Polygon6.cs index be3813b0..a7b45881 100644 --- a/StgSharp.Common/Geometries/PlainGeometry/Polygon6.cs +++ b/StgSharp.Common/Geometries/PlainGeometry/Polygon6.cs @@ -48,24 +48,24 @@ namespace StgSharp.Geometries } public Polygon6( - PlainCoordinate coordination, - Vec2 vert0, - Vec2 vert1, - Vec2 vert2, - Vec2 vert3, - Vec2 vert4, - Vec2 vert5, - Vec2 vert6 ) + PlainCoordinate coordination, + Vec2 vert0, + Vec2 vert1, + Vec2 vert2, + Vec2 vert3, + Vec2 vert4, + Vec2 vert5, + Vec2 vert6 ) : base( coordination ) { vertexMat = new Vec4[6]; - vertexMat[ 0 ].vec = vert0.vec; - vertexMat[ 1 ].vec = vert1.vec; - vertexMat[ 2 ].vec = vert2.vec; - vertexMat[ 3 ].vec = vert3.vec; - vertexMat[ 4 ].vec = vert4.vec; - vertexMat[ 5 ].vec = vert5.vec; - vertexMat[ 6 ].vec = vert6.vec; + vertexMat[ 0 ].reg = vert0.reg; + vertexMat[ 1 ].reg = vert1.reg; + vertexMat[ 2 ].reg = vert2.reg; + vertexMat[ 3 ].reg = vert3.reg; + vertexMat[ 4 ].reg = vert4.reg; + vertexMat[ 5 ].reg = vert5.reg; + vertexMat[ 6 ].reg = vert6.reg; } public override ReadOnlySpan VertexIndices => Indices; diff --git a/StgSharp.Common/Graphics/OpenGL/Buffer/VBO.cs b/StgSharp.Common/Graphics/OpenGL/Buffer/VBO.cs index fe72ae61..08335369 100644 --- a/StgSharp.Common/Graphics/OpenGL/Buffer/VBO.cs +++ b/StgSharp.Common/Graphics/OpenGL/Buffer/VBO.cs @@ -72,10 +72,10 @@ namespace StgSharp.Graphics.OpenGL /// Data to write in /// How OpenGL use these _data, defined by public void WriteMatrixData( - int index, - T bufferData, - BufferUsage usage ) - where T: struct, IMat + int index, + T bufferData, + BufferUsage usage ) + where T: struct, IMatrix { GL.BindBuffer( BufferType.ArrayBuffer, _bufferHandle[ index ] ); GL.SetBufferData( BufferType.ArrayBuffer, bufferData, usage ); @@ -89,9 +89,9 @@ namespace StgSharp.Graphics.OpenGL /// Data to write in /// How OpenGL use these _data, defined by public void WriteScalerData( - int index, - T[] bufferArray, - BufferUsage usage ) + int index, + T[] bufferArray, + BufferUsage usage ) where T: struct, INumber { GL.BindBuffer( BufferType.ArrayBuffer, _bufferHandle[ index ] ); @@ -106,9 +106,9 @@ namespace StgSharp.Graphics.OpenGL /// A of _data to write in /// How OpenGL use these _data, defined by public void WriteScalerData( - int index, - ReadOnlySpan scalerSpan, - BufferUsage usage ) + int index, + ReadOnlySpan scalerSpan, + BufferUsage usage ) where T: struct,INumber { GL.BindBuffer( BufferType.ArrayBuffer, _bufferHandle[ index ] ); @@ -123,10 +123,10 @@ namespace StgSharp.Graphics.OpenGL /// A of _data to write in /// How OpenGL use these _data, defined by public void WriteVectorData( - int index, - ReadOnlySpan vectorSpan, - BufferUsage usage ) - where T: struct, IVector + int index, + ReadOnlySpan vectorSpan, + BufferUsage usage ) + where T: struct, IVector { GL.BindBuffer( BufferType.ArrayBuffer, _bufferHandle[ index ] ); GL.SetBufferVectorData( BufferType.ArrayBuffer, vectorSpan, usage ); @@ -140,10 +140,10 @@ namespace StgSharp.Graphics.OpenGL /// A array of _data to write in /// How OpenGL use these _data, defined by public void WriteVectorData( - int index, - T[] vectorArray, - BufferUsage usage ) - where T: struct, IVector + int index, + T[] vectorArray, + BufferUsage usage ) + where T: struct, IVector { GL.BindBuffer( BufferType.ArrayBuffer, _bufferHandle[ index ] ); GL.SetBufferVectorData( BufferType.ArrayBuffer, vectorArray, diff --git a/StgSharp.Common/Graphics/OpenGL/glFunction.cs b/StgSharp.Common/Graphics/OpenGL/glFunction.cs index e9e5916e..6636edb7 100644 --- a/StgSharp.Common/Graphics/OpenGL/glFunction.cs +++ b/StgSharp.Common/Graphics/OpenGL/glFunction.cs @@ -157,7 +157,7 @@ namespace StgSharp.Graphics.OpenGL [MethodImpl( MethodImplOptions.AggressiveInlining )] public FrameBufferStatus CheckFrameBufferStatus( - FrameBufferTarget target ) + FrameBufferTarget target ) { return ( FrameBufferStatus )Context.glCheckFramebufferStatus( ( uint )target ); @@ -201,8 +201,8 @@ namespace StgSharp.Graphics.OpenGL [MethodImpl( MethodImplOptions.AggressiveInlining )] public void CombineFrameBufferRenderBuffer( - FrameBufferAttachment attachment, - GlHandle rboHandle ) + FrameBufferAttachment attachment, + GlHandle rboHandle ) { Context.glFramebufferRenderbuffer( glConst.FRAMEBUFFER, ( uint )attachment, glConst.RENDERBUFFER, @@ -298,10 +298,10 @@ namespace StgSharp.Graphics.OpenGL [MethodImpl( MethodImplOptions.AggressiveInlining )] public unsafe void DrawElements( - GeometryType mode, - uint count, - TypeCode type, - IntPtr ptr ) + GeometryType mode, + uint count, + TypeCode type, + IntPtr ptr ) { uint a; a = type switch @@ -317,11 +317,11 @@ namespace StgSharp.Graphics.OpenGL [MethodImpl( MethodImplOptions.AggressiveInlining )] public void DrawElementsInstanced( - GeometryType mode, - uint count, - TypeCode type, - IntPtr ptr, - uint amount ) + GeometryType mode, + uint count, + TypeCode type, + IntPtr ptr, + uint amount ) { uint a; switch( type ) { @@ -355,11 +355,11 @@ namespace StgSharp.Graphics.OpenGL [MethodImpl( MethodImplOptions.AggressiveInlining )] public void FrameBufferTexture2d( - FrameBufferTarget target, - uint attachment, - Texture2DTarget texTarget, - GlHandle textureHandle, - int level ) + FrameBufferTarget target, + uint attachment, + Texture2DTarget texTarget, + GlHandle textureHandle, + int level ) { Context.glFramebufferTexture2D( ( uint )target, attachment, ( uint )texTarget, @@ -439,7 +439,8 @@ namespace StgSharp.Graphics.OpenGL { IntPtr sptr = IntPtr.Zero; if( InternalIO.glCheckShaderStatus( - ref Context, s.handle[ index ].Value, key, ref sptr ) == 0 ) { + ref Context, s.handle[ index ].Value, key, ref sptr ) == + 0 ) { return Marshal.PtrToStringAnsi( sptr ); } return string.Empty; @@ -447,11 +448,11 @@ namespace StgSharp.Graphics.OpenGL [MethodImpl( MethodImplOptions.AggressiveInlining )] public unsafe void GetTextureImage( - Texture2DTarget target, - int level, - ImageChannel channel, - PixelChannelLayout channelLayout, - T[] dataStream ) + Texture2DTarget target, + int level, + ImageChannel channel, + PixelChannelLayout channelLayout, + T[] dataStream ) where T: struct,INumber { #pragma warning disable CS8500 @@ -465,10 +466,10 @@ namespace StgSharp.Graphics.OpenGL [MethodImpl( MethodImplOptions.AggressiveInlining )] public void GetTextureLevelProperty( - uint textureTypeMask, - int level, - uint propertyMask, - out int propertyValue ) + uint textureTypeMask, + int level, + uint propertyMask, + out int propertyValue ) { fixed( int* iptr = &propertyValue ) { Context.glGetTexLevelParameteriv( @@ -478,14 +479,15 @@ namespace StgSharp.Graphics.OpenGL [MethodImpl( MethodImplOptions.AggressiveInlining )] public unsafe GlHandle GetUniformLocation( - GlHandle program, - string name ) + GlHandle program, + string name ) { byte[] code = Encoding.UTF8.GetBytes( name ); fixed( byte* ptr = code ) { int ret = Context.glGetUniformLocation( program.Value, ptr ); #if DEBUG - if( ( ret == glConst.INVALID_OPERATION ) || ( ret == glConst.INVALID_VALUE ) ) { + if( ( ret == glConst.INVALID_OPERATION ) || ( ret == + glConst.INVALID_VALUE ) ) { throw new InvalidOperationException(); } if( ret == -1 ) { @@ -499,8 +501,8 @@ namespace StgSharp.Graphics.OpenGL [MethodImpl( MethodImplOptions.AggressiveInlining )] public unsafe void LoadShaderSource( - GlHandle shaderHandle, - byte[] codeStream ) + GlHandle shaderHandle, + byte[] codeStream ) { fixed( byte* streamPtr = codeStream ) { Context.glShaderSource( @@ -509,24 +511,23 @@ namespace StgSharp.Graphics.OpenGL } public unsafe void LoadShaderSource( - GlHandle shaderHandle, - ReadOnlySpan codeStream) + GlHandle shaderHandle, + ReadOnlySpan codeStream ) { - fixed (char* streamPtr = codeStream) - { - byte* bptr = (byte*)streamPtr; + fixed( char* streamPtr = codeStream ) { + byte* bptr = ( byte* )streamPtr; Context.glShaderSource( - shaderHandle.Value, 1, &bptr, (void*)0); + shaderHandle.Value, 1, &bptr, ( void* )0 ); } } [MethodImpl( MethodImplOptions.AggressiveInlining )] public void ReadPixels( - (int X, int Y) beginPosition, - (int width, int height) size, - FrameBufferChannel format, - PixelChannelLayout dataType, - ref byte[] stream ) + (int X, int Y) beginPosition, + (int width, int height) size, + FrameBufferChannel format, + PixelChannelLayout dataType, + ref byte[] stream ) { fixed( byte* bptr = stream ) { Context.glReadPixels( @@ -536,10 +537,10 @@ namespace StgSharp.Graphics.OpenGL } public void RereadImage( - in Image i, - (int X, int Y) beginPosition, - FrameBufferChannel format, - PixelChannelLayout dataType ) + in Image i, + (int X, int Y) beginPosition, + FrameBufferChannel format, + PixelChannelLayout dataType ) { byte[] pixels = i.PixelBuffer; if( !pixels.CheckArrayFormat( dataType ) ) { @@ -555,9 +556,9 @@ namespace StgSharp.Graphics.OpenGL [MethodImpl( MethodImplOptions.AggressiveInlining )] public unsafe void SetBufferData( - BufferType bufferType, - T bufferData, - BufferUsage usage ) + BufferType bufferType, + T bufferData, + BufferUsage usage ) where T: struct { int size = Marshal.SizeOf(); @@ -571,30 +572,9 @@ namespace StgSharp.Graphics.OpenGL [MethodImpl( MethodImplOptions.AggressiveInlining )] public unsafe void SetBufferData( - BufferType bufferType, - T[] bufferArray, - BufferUsage usage ) - where T: struct,INumber - { - int size = bufferArray.Length * Marshal.SizeOf( typeof( T ) ); - if( bufferArray == null ) { - return; - } - #pragma warning disable CS8500 - fixed( void* bufferPtr = bufferArray ) - #pragma warning restore CS8500 - { - Context.glBufferData( - ( uint )bufferType, ( IntPtr )size, ( IntPtr )bufferPtr, - ( uint )usage ); - } - } - - [MethodImpl( MethodImplOptions.AggressiveInlining )] - public unsafe void SetBufferData( - BufferType bufferType, - ReadOnlySpan bufferArray, - BufferUsage usage ) + BufferType bufferType, + T[] bufferArray, + BufferUsage usage ) where T: struct,INumber { int size = bufferArray.Length * Marshal.SizeOf( typeof( T ) ); @@ -613,9 +593,30 @@ namespace StgSharp.Graphics.OpenGL [MethodImpl( MethodImplOptions.AggressiveInlining )] public unsafe void SetBufferData( - BufferType bufferType, - Span bufferArray, - BufferUsage usage ) + BufferType bufferType, + ReadOnlySpan bufferArray, + BufferUsage usage ) + where T: struct,INumber + { + int size = bufferArray.Length * Marshal.SizeOf( typeof( T ) ); + if( bufferArray == null ) { + return; + } + #pragma warning disable CS8500 + fixed( void* bufferPtr = bufferArray ) + #pragma warning restore CS8500 + { + Context.glBufferData( + ( uint )bufferType, ( IntPtr )size, ( IntPtr )bufferPtr, + ( uint )usage ); + } + } + + [MethodImpl( MethodImplOptions.AggressiveInlining )] + public unsafe void SetBufferData( + BufferType bufferType, + Span bufferArray, + BufferUsage usage ) where T: struct, INumber { int size = bufferArray.Length * Marshal.SizeOf( typeof( T ) ); @@ -635,10 +636,10 @@ namespace StgSharp.Graphics.OpenGL [MethodImpl( MethodImplOptions.AggressiveInlining )] public unsafe void SetBufferVectorData( - BufferType bufferType, - ReadOnlySpan bufferArray, - BufferUsage usage ) - where T: struct, IVector + BufferType bufferType, + ReadOnlySpan bufferArray, + BufferUsage usage ) + where T: struct, IVector { int size = bufferArray.Length * Marshal.SizeOf( typeof( T ) ); if( bufferArray == null ) { @@ -656,10 +657,10 @@ namespace StgSharp.Graphics.OpenGL [MethodImpl( MethodImplOptions.AggressiveInlining )] public unsafe void SetBufferVectorData( - BufferType bufferType, - T[] bufferArray, - BufferUsage usage ) - where T: struct, IVector + BufferType bufferType, + T[] bufferArray, + BufferUsage usage ) + where T: struct, IVector { int size = bufferArray.Length * Marshal.SizeOf( typeof( T ) ); if( bufferArray == null ) { @@ -677,8 +678,8 @@ namespace StgSharp.Graphics.OpenGL [MethodImpl( MethodImplOptions.AggressiveInlining )] public unsafe void SetRenderBufferStorage( - RenderBufferInternalFormat internalFormat, - (int width, int height) size ) + RenderBufferInternalFormat internalFormat, + (int width, int height) size ) { Context.glRenderbufferStorage( glConst.RENDERBUFFER, ( uint )internalFormat, size.width, @@ -687,8 +688,8 @@ namespace StgSharp.Graphics.OpenGL [MethodImpl( MethodImplOptions.AggressiveInlining )] public unsafe void SetRenderBufferStorage( - RenderBufferInternalFormat internalFormat, - (uint width, uint height) size ) + RenderBufferInternalFormat internalFormat, + (uint width, uint height) size ) { Context.glRenderbufferStorage( glConst.RENDERBUFFER, ( uint )internalFormat, ( int )size.width, @@ -697,12 +698,12 @@ namespace StgSharp.Graphics.OpenGL [MethodImpl( MethodImplOptions.AggressiveInlining )] public void SetVertexAttribute( - uint index, - int size, - TypeCode t, - bool normalized, - uint stride, - int pointer ) + uint index, + int size, + TypeCode t, + bool normalized, + uint stride, + int pointer ) { uint type = InternalIO.GLtype[ t ]; Context.glVertexAttribPointer( @@ -713,20 +714,20 @@ namespace StgSharp.Graphics.OpenGL [MethodImpl( MethodImplOptions.AggressiveInlining )] public void TextureImage2d( - Texture2DTarget target, - int level, - ImageChannel sourceChannel, - uint width, - uint height, - ImageChannel targetChannel, - PixelChannelLayout type, - T[] pixels ) + Texture2DTarget target, + int level, + ImageChannel sourceChannel, + uint width, + uint height, + ImageChannel targetChannel, + PixelChannelLayout type, + T[] pixels ) where T: struct, INumber { #pragma warning disable CS8500 fixed( T* tptr = pixels ) { T* ptr = ( ( pixels == null ) || ( pixels.Length == 0 ) ) ? - ( T* )IntPtr.Zero : tptr; + ( T* )IntPtr.Zero : tptr; Context.glTexImage2D( ( uint )target, level, ( uint )sourceChannel, width, height, 0, ( uint )targetChannel, ( uint )type, tptr ); @@ -736,23 +737,23 @@ namespace StgSharp.Graphics.OpenGL [MethodImpl( MethodImplOptions.AggressiveInlining )] public void TextureImage2d( - Texture2DTarget target, - int level, - ImageChannel sourceChannel, - uint width, - uint height, - ImageChannel targetChannel, - PixelChannelLayout type, - Span pixelSpan ) + Texture2DTarget target, + int level, + ImageChannel sourceChannel, + uint width, + uint height, + ImageChannel targetChannel, + PixelChannelLayout type, + Span pixelSpan ) where T: struct, INumber { -#pragma warning disable CS8500 + #pragma warning disable CS8500 fixed( T* tptr = pixelSpan ) { Context.glTexImage2D( ( uint )target, level, ( uint )sourceChannel, width, height, 0, ( uint )targetChannel, ( uint )type, tptr ); } -#pragma warning restore CS8500 + #pragma warning restore CS8500 } [MethodImpl( MethodImplOptions.AggressiveInlining )] @@ -762,8 +763,8 @@ namespace StgSharp.Graphics.OpenGL } public static bool TryGetFunctionPackage( - IntPtr handle, - out OpenGLFunction functionPackage ) + IntPtr handle, + out OpenGLFunction functionPackage ) { return contextToGLMap.TryGetValue( handle, out functionPackage ); } diff --git a/StgSharp.Common/Graphics/Pixels.cs b/StgSharp.Common/Graphics/Pixels.cs index 9424725e..dd4b3d15 100644 --- a/StgSharp.Common/Graphics/Pixels.cs +++ b/StgSharp.Common/Graphics/Pixels.cs @@ -70,11 +70,36 @@ namespace StgSharp.Graphics } [StructLayout( LayoutKind.Explicit, Size = 32 )] - public unsafe struct Pixel32 + public unsafe struct Pixel32RGBA : IPixel { + [FieldOffset( 0 )] private unsafe fixed byte data[ 4 ]; - internal int Size => 4; + public int Size => 4; + + float IPixel.Alpha + { + get => data[ 3 ] / 256 ; + set => data[ 3 ] = ( byte )( value * 256 ); + } + + float IPixel.Blue + { + get => data[ 2 ] / 256 ; + set => data[ 2 ] = ( byte )( value * 256 ); + } + + float IPixel.Green + { + get => data[ 1 ] / 256 ; + set => data[ 1 ] = ( byte )( value * 256 ); + } + + float IPixel.Red + { + get => data[ 0 ] / 256 ; + set => data[ 0 ] = ( byte )( value * 256 ); + } } } diff --git a/StgSharp.Common/Graphics/PlainGeometryMesh.cs b/StgSharp.Common/Graphics/PlainGeometryMesh.cs index 0f506367..11666a61 100644 --- a/StgSharp.Common/Graphics/PlainGeometryMesh.cs +++ b/StgSharp.Common/Graphics/PlainGeometryMesh.cs @@ -47,8 +47,8 @@ namespace StgSharp.Graphics private TextureProvider _texture; public PlainGeometryMesh( - [NotNull] PlainGeometry shape, - [NotNull] TextureProvider texture ) + [NotNull] PlainGeometry shape, + [NotNull] TextureProvider texture ) { if( shape.VertexCount > texture.TextureCoordinate.Length ) { throw new ArgumentException( @@ -62,16 +62,12 @@ namespace StgSharp.Graphics //private Image _texture; public PlainGeometryMesh( - PlainGeometry shape, - Image texture, - Vec2[] texCoord ) + PlainGeometry shape, + Image texture, + Vec2[] texCoord ) { - if( shape == null ) { - throw new ArgumentNullException( nameof( shape ) ); - } - if( texCoord == null ) { - throw new ArgumentNullException( nameof( texCoord ) ); - } + ArgumentNullException.ThrowIfNull( shape ); + ArgumentNullException.ThrowIfNull( texCoord ); if( shape.VertexCount > texCoord.Length ) { throw new ArgumentException( diff --git a/StgSharp.Common/Graphics/TexturePipeline.cs b/StgSharp.Common/Graphics/TexturePipeline.cs index bd9c3b64..6bfc4c68 100644 --- a/StgSharp.Common/Graphics/TexturePipeline.cs +++ b/StgSharp.Common/Graphics/TexturePipeline.cs @@ -29,7 +29,7 @@ //----------------------------------------------------------------------- //----------------------------------------------------------------------- -using StgSharp.Blueprint; +using StgSharp.PipeLine; using System; using System.Collections.Generic; @@ -39,7 +39,7 @@ using System.Threading.Tasks; namespace StgSharp.Graphics { - public class TexturePipeline : BlueprintPipelineArgs + public class TexturePipeline : PipeLineConnectorArgs { private Image _value; diff --git a/StgSharp.Common/HighPerformance/M128.cs b/StgSharp.Common/HighPerformance/M128.cs index 19b7062d..2df924a1 100644 --- a/StgSharp.Common/HighPerformance/M128.cs +++ b/StgSharp.Common/HighPerformance/M128.cs @@ -34,10 +34,8 @@ using System.Diagnostics.CodeAnalysis; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if NET5_0_OR_GREATER using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; -#endif using System.Text; @@ -48,11 +46,11 @@ namespace StgSharp.HighPerformance { [FieldOffset( 0 )] internal fixed byte Buffer[ 16 ]; - [FieldOffset( 0 )] internal Vector128 Vec; + [FieldOffset( 0 )] internal Vector128 Vec; internal M128( Vector4 v ) { - Vec = v.AsVector128().AsByte(); + Vec = v.AsVector128(); } public ref T AsRef() where T: struct, INumber @@ -60,6 +58,12 @@ namespace StgSharp.HighPerformance return ref Unsafe.As( ref Buffer[ 0 ] ); } + [MethodImpl( MethodImplOptions.AggressiveInlining )] + public Vector4 AsVector4() + { + return Vec.As().AsVector4(); + } + public override bool Equals( [NotNullWhen( true )] object obj ) { if( obj is not M128 other ) { @@ -123,61 +127,61 @@ namespace StgSharp.HighPerformance [MethodImpl( MethodImplOptions.AggressiveInlining )] public static explicit operator Vector128( M128 m ) { - return m.Vec.As(); + return m.Vec.As(); } [MethodImpl( MethodImplOptions.AggressiveInlining )] public static explicit operator Vector128( M128 m ) { - return m.Vec.As(); + return m.Vec.As(); } [MethodImpl( MethodImplOptions.AggressiveInlining )] public static explicit operator Vector128( M128 m ) { - return m.Vec.As(); + return m.Vec.As(); } [MethodImpl( MethodImplOptions.AggressiveInlining )] public static explicit operator Vector128( M128 m ) { - return m.Vec.As(); + return m.Vec.As(); } [MethodImpl( MethodImplOptions.AggressiveInlining )] public static explicit operator Vector128( M128 m ) { - return m.Vec.As(); + return m.Vec.As(); } [MethodImpl( MethodImplOptions.AggressiveInlining )] public static explicit operator Vector128( M128 m ) { - return m.Vec.As(); + return m.Vec.As(); } [MethodImpl( MethodImplOptions.AggressiveInlining )] public static explicit operator Vector128( M128 m ) { - return m.Vec.As(); + return m.Vec.As(); } [MethodImpl( MethodImplOptions.AggressiveInlining )] public static explicit operator Vector128( M128 m ) { - return m.Vec.As(); + return m.Vec.As(); } [MethodImpl( MethodImplOptions.AggressiveInlining )] public static explicit operator Vector128( M128 m ) { - return m.Vec.As(); + return m.Vec.As(); } [MethodImpl( MethodImplOptions.AggressiveInlining )] public static explicit operator Vector128( M128 m ) { - return m.Vec.As(); + return m.Vec.As(); } } diff --git a/StgSharp.Common/Internal/Intrinsic/ColumnSet3.cs b/StgSharp.Common/Internal/Intrinsic/ColumnSet3.cs index 809eaf36..4fe9b0e2 100644 --- a/StgSharp.Common/Internal/Intrinsic/ColumnSet3.cs +++ b/StgSharp.Common/Internal/Intrinsic/ColumnSet3.cs @@ -39,8 +39,9 @@ using System.Runtime.InteropServices; namespace StgSharp.Internal.Intrinsic { [StructLayout( LayoutKind.Explicit, Size = 12 * sizeof( float ), Pack = 16 )] - internal struct ColumnSet3 : IEquatable, IMat + internal struct ColumnSet3 : IEquatable { + [FieldOffset( 0 * sizeof( float ) )] internal float m00; [FieldOffset( 4 * sizeof( float ) )] internal float m01; [FieldOffset( 8 * sizeof( float ) )] internal float m02; diff --git a/StgSharp.Common/Internal/Intrinsic/ColumnSet4.cs b/StgSharp.Common/Internal/Intrinsic/ColumnSet4.cs index b3781305..8093c0f5 100644 --- a/StgSharp.Common/Internal/Intrinsic/ColumnSet4.cs +++ b/StgSharp.Common/Internal/Intrinsic/ColumnSet4.cs @@ -39,7 +39,7 @@ using System.Runtime.InteropServices; namespace StgSharp.Internal.Intrinsic { [StructLayout( LayoutKind.Explicit, Size = 16 * sizeof( float ) )] - internal struct ColumnSet4 : IEquatable, IMat + internal struct ColumnSet4 : IEquatable { [FieldOffset( 0 )] internal Vector4 colum0; diff --git a/StgSharp.Common/Math/Graphic/Camera.cs b/StgSharp.Common/Math/Graphic/Camera.cs index 5e9f06bc..14195980 100644 --- a/StgSharp.Common/Math/Graphic/Camera.cs +++ b/StgSharp.Common/Math/Graphic/Camera.cs @@ -111,12 +111,13 @@ namespace StgSharp.Graphics /// /// public unsafe void GainAllUniforms( - ShaderProgram source, - params string[] uniformName ) + ShaderProgram source, + params string[] uniformName ) { - if( uniformName.Length != 1 ) { + if( uniformName is null || uniformName.Length != 1 ) { throw new ArgumentException( - "Camera needs only one uniform.", nameof( uniformName ) ); + "Camera needs exactly one uniform.", + nameof( uniformName ) ); } convertedUniform = source.GetUniform( uniformName[ 0 ] ); } @@ -143,13 +144,14 @@ namespace StgSharp.Graphics { //Console.WriteLine(Projection * ViewBase); OpenGL.OpenGLFunction.CurrentGL - .SetUniformValue( convertedUniform, Projection * View ); + .SetUniformValue( convertedUniform, Projection * View ); } public void SetViewDirection( Vec3 position, Vec3 target, Vec3 up ) { Vec3 direction = position - target; - if( ( position.vec == cameraAtt.colum3.vec ) && ( this.up == up ) && ( cameraAtt.colum2.vec == direction.vec ) ) { + if( ( position.reg == cameraAtt.colum3.reg ) && ( this.up == up ) && ( cameraAtt.colum2.reg == + direction.reg ) ) { //no difference with precious value return; } @@ -169,10 +171,10 @@ namespace StgSharp.Graphics Vec3 right = Linear.Orthogonalize( Linear.Cross( up, direction ) ); - cameraAtt.colum0.vec = right.vec; - cameraAtt.colum1.vec = up.vec; - cameraAtt.colum2.vec = direction.vec; - cameraAtt.colum3.vec = position.vec; + cameraAtt.colum0.reg = right. reg; + cameraAtt.colum1.reg = up.reg; + cameraAtt.colum2.reg = direction.reg; + cameraAtt.colum3.reg = position. reg; InternalPitch(); InternalRow(); @@ -180,10 +182,10 @@ namespace StgSharp.Graphics } public void SetViewRange( - Radius fovRadius, - Vec2 size, - Vec2 offset, - (float front, float back) dephRange ) + Radius fovRadius, + Vec2 size, + Vec2 offset, + (float front, float back) dephRange ) { float distance = _target.GetLength(), @@ -264,8 +266,8 @@ namespace StgSharp.Graphics Scaler.Cos( angle ) ); partialCoord *= rotation; - rotationAtt.colum1.vec = partialCoord.colum0.vec; - rotationAtt.colum2.vec = partialCoord.colum1.vec; + rotationAtt.colum1.reg = partialCoord.colum0.reg; + rotationAtt.colum2.reg = partialCoord.colum1.reg; rotationAtt.isTransposed = false; } @@ -282,8 +284,8 @@ namespace StgSharp.Graphics Scaler.Cos( angle ) ); partialCoord *= rotation; - rotationAtt.colum0.vec = partialCoord.colum0.vec; - rotationAtt.colum1.vec = partialCoord.colum1.vec; + rotationAtt.colum0.reg = partialCoord.colum0.reg; + rotationAtt.colum1.reg = partialCoord.colum1.reg; rotationAtt.isTransposed = false; } @@ -299,8 +301,8 @@ namespace StgSharp.Graphics Scaler.Cos( angle ) ); partialCoord *= rotation; - rotationAtt.colum0.vec = partialCoord.colum0.vec; - rotationAtt.colum2.vec = partialCoord.colum1.vec; + rotationAtt.colum0.reg = partialCoord.colum0.reg; + rotationAtt.colum2.reg = partialCoord.colum1.reg; rotationAtt.isTransposed = false; } diff --git a/StgSharp.Common/Math/Linear/IMatrix.cs b/StgSharp.Common/Math/Linear/IMatrix.cs new file mode 100644 index 00000000..7d97ce24 --- /dev/null +++ b/StgSharp.Common/Math/Linear/IMatrix.cs @@ -0,0 +1,40 @@ +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// file="IMatrix.cs" +// Project: StgSharp +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and +// this permission notice shall be included in all copies +// or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, +// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +using StgSharp.Graphics; + +using System; +using System.Collections.Generic; +using System.Text; + +namespace StgSharp.Math +{ + public interface IMatrix where TSelf: IMatrix { } +} diff --git a/StgSharp.Common/Math/Linear/IVector.cs b/StgSharp.Common/Math/Linear/IVector.cs index ad02839a..e033b654 100644 --- a/StgSharp.Common/Math/Linear/IVector.cs +++ b/StgSharp.Common/Math/Linear/IVector.cs @@ -37,14 +37,30 @@ using System.Threading.Tasks; namespace StgSharp.Math { - public interface IVector + public interface IVector where TSelf: struct, IVector { - /* - public static TItem Create(Vector4 source) where TItem : IVector + + public static abstract TSelf Zero { - return TItem + get; + } + + public static abstract TSelf One + { + get; + } + + public Vec2 XY + { + get; + set; + } + + public Vec3 XYZ + { + get; + set; } - /**/ } } diff --git a/StgSharp.Common/Math/Linear/Matrix22.cs b/StgSharp.Common/Math/Linear/Matrix22.cs index 176c6996..99f9df32 100644 --- a/StgSharp.Common/Math/Linear/Matrix22.cs +++ b/StgSharp.Common/Math/Linear/Matrix22.cs @@ -40,7 +40,7 @@ namespace StgSharp.Math LayoutKind.Explicit, Size = ( 2 * 2 * 4 * sizeof( float ) ) + sizeof( bool ), Pack = 16 )] - public struct Matrix22 : IMat + public struct Matrix22 : IMatrix { [FieldOffset( 2 * 2 * 4 * sizeof( float ) )] @@ -101,7 +101,6 @@ namespace StgSharp.Math float cache = _transpose.m10; _transpose.m10 = _transpose.m01; _transpose.m01 = cache; - isTransposed = true; } } diff --git a/StgSharp.Common/Math/Linear/Matrix23.cs b/StgSharp.Common/Math/Linear/Matrix23.cs index e41238cf..a0c2a81e 100644 --- a/StgSharp.Common/Math/Linear/Matrix23.cs +++ b/StgSharp.Common/Math/Linear/Matrix23.cs @@ -41,7 +41,7 @@ namespace StgSharp.Math LayoutKind.Explicit, Size = ( ( 3 + 2 ) * 4 * sizeof( float ) ) + sizeof( bool ), Pack = 16 )] - public struct Matrix23 : IMat + public struct Matrix23 : IMatrix { [FieldOffset( 5 * 4 * sizeof( float ) )] internal bool isTransposed = false; diff --git a/StgSharp.Common/Math/Linear/Matrix24.cs b/StgSharp.Common/Math/Linear/Matrix24.cs index 4c29c648..6e1f007c 100644 --- a/StgSharp.Common/Math/Linear/Matrix24.cs +++ b/StgSharp.Common/Math/Linear/Matrix24.cs @@ -41,7 +41,7 @@ namespace StgSharp.Math LayoutKind.Explicit, Size = ( ( 4 + 2 ) * 4 * sizeof( float ) ) + sizeof( bool ), Pack = 16 )] - public struct Matrix24 : IMat + public struct Matrix24 : IMatrix { [FieldOffset( 6 * 4 * sizeof( float ) )] internal bool isTransposed; diff --git a/StgSharp.Common/Math/Linear/Matrix32.cs b/StgSharp.Common/Math/Linear/Matrix32.cs index 460a7fdf..213fb909 100644 --- a/StgSharp.Common/Math/Linear/Matrix32.cs +++ b/StgSharp.Common/Math/Linear/Matrix32.cs @@ -41,7 +41,7 @@ namespace StgSharp.Math LayoutKind.Explicit, Size = ( 5 * 4 * sizeof( float ) ) + sizeof( bool ), Pack = 16 )] - public struct Matrix32 : IMat + public struct Matrix32 : IMatrix { [FieldOffset( 5 * 4 * sizeof( float ) )] internal bool isTransposed; diff --git a/StgSharp.Common/Math/Linear/Matrix33.cs b/StgSharp.Common/Math/Linear/Matrix33.cs index b7bb3f50..bd77da3f 100644 --- a/StgSharp.Common/Math/Linear/Matrix33.cs +++ b/StgSharp.Common/Math/Linear/Matrix33.cs @@ -41,7 +41,7 @@ namespace StgSharp.Math LayoutKind.Explicit, Size = ( 6 * 4 * sizeof( float ) ) + sizeof( bool ), Pack = 16 )] - public struct Matrix33 : IMat + public struct Matrix33 : IMatrix { [FieldOffset( 6 * 4 * sizeof( float ) )] internal bool isTransposed; @@ -162,9 +162,9 @@ namespace StgSharp.Math { left.InternalTranspose(); return new Vec3( - Vector4.Dot( left.transpose.colum0, right.vec ), - Vector4.Dot( left.transpose.colum1, right.vec ), - Vector4.Dot( left.transpose.colum2, right.vec ) ); + Vector4.Dot( left.transpose.colum0, right.reg.AsVector4() ), + Vector4.Dot( left.transpose.colum1, right.reg.AsVector4() ), + Vector4.Dot( left.transpose.colum2, right.reg.AsVector4() ) ); } [MethodImpl( MethodImplOptions.AggressiveInlining )] diff --git a/StgSharp.Common/Math/Linear/Matrix34.cs b/StgSharp.Common/Math/Linear/Matrix34.cs index 7d5dcaf3..765c022c 100644 --- a/StgSharp.Common/Math/Linear/Matrix34.cs +++ b/StgSharp.Common/Math/Linear/Matrix34.cs @@ -42,7 +42,7 @@ namespace StgSharp.Math LayoutKind.Explicit, Size = ( 7 * 4 * sizeof( float ) ) + sizeof( bool ), Pack = 16 )] - public struct Matrix34 : IMat + public struct Matrix34 : IMatrix { [FieldOffset( 7 * 4 * sizeof( float ) )] internal bool isTransposed; diff --git a/StgSharp.Common/Math/Linear/Matrix42.cs b/StgSharp.Common/Math/Linear/Matrix42.cs index fc580a3c..f971c83e 100644 --- a/StgSharp.Common/Math/Linear/Matrix42.cs +++ b/StgSharp.Common/Math/Linear/Matrix42.cs @@ -41,7 +41,7 @@ namespace StgSharp.Math LayoutKind.Explicit, Size = ( ( 16 + 8 ) * sizeof( float ) ) + sizeof( bool ), Pack = 16 )] - public struct Matrix42 : IMat + public struct Matrix42 : IMatrix { [FieldOffset( ( 16 + 8 ) * sizeof( float ) )] internal bool isTransposed; diff --git a/StgSharp.Common/Math/Linear/Matrix43.cs b/StgSharp.Common/Math/Linear/Matrix43.cs index 14f32935..af978c6d 100644 --- a/StgSharp.Common/Math/Linear/Matrix43.cs +++ b/StgSharp.Common/Math/Linear/Matrix43.cs @@ -40,10 +40,10 @@ using System.Security.AccessControl; namespace StgSharp.Math { [StructLayout( - layoutKind: LayoutKind.Explicit, - Size = ( 7 * 4 * sizeof( float ) ) + sizeof( bool ), - Pack = 16 )] - public struct Matrix43 : IEquatable, IMat + layoutKind: LayoutKind.Explicit, + Size = ( 7 * 4 * sizeof( float ) ) + sizeof( bool ), + Pack = 16 )] + public struct Matrix43 : IEquatable, IMatrix { [FieldOffset( 7 * 4 * sizeof( float ) )] @@ -54,36 +54,36 @@ namespace StgSharp.Math [FieldOffset( 3 * 4 * sizeof( float ) )] internal ColumnSet4 transpose; - public Matrix43() - { - Unsafe.SkipInit(out this); - isTransposed = false; - } - internal Matrix43( Vector4 c0, Vector4 c1, Vector4 c2 ) { - Unsafe.SkipInit(out this); + Unsafe.SkipInit( out this ); isTransposed = false; mat.colum0 = c0; mat.colum1 = c1; mat.colum2 = c2; } - public Matrix43( - float a00, - float a01, - float a02, - float a10, - float a11, - float a12, - float a20, - float a21, - float a22, - float a30, - float a31, - float a32 ) + public Matrix43() { - Unsafe.SkipInit(out this); + Unsafe.SkipInit( out this ); + isTransposed = false; + } + + public Matrix43( + float a00, + float a01, + float a02, + float a10, + float a11, + float a12, + float a20, + float a21, + float a22, + float a30, + float a31, + float a32 ) + { + Unsafe.SkipInit( out this ); isTransposed = false; mat.colum0 = new Vector4( a00, a10, a20, a30 ); mat.colum1 = new Vector4( a01, a11, a21, a31 ); @@ -145,10 +145,12 @@ namespace StgSharp.Math internal unsafe void InternalTranspose() { if( !isTransposed ) { - fixed( ColumnSet3* source = &this.mat ) - fixed( ColumnSet4* target = &this.transpose ) { - InternalIO.Intrinsic.transpose34( source, target ); + fixed( ColumnSet3* source = &this.mat ) { + fixed( ColumnSet4* target = &this.transpose ) { + InternalIO.Intrinsic.transpose34( source, target ); + } } + isTransposed = true; } } @@ -250,10 +252,12 @@ namespace StgSharp.Math } [MethodImpl( MethodImplOptions.AggressiveInlining )] - public static unsafe Matrix43 operator +( Matrix43 left, Matrix43 right ) + public static unsafe Matrix43 operator +( + Matrix43 left, + Matrix43 right ) { Matrix43 ret = new Matrix43(); - InternalIO.Intrinsic.add_mat_3(&left.mat, &right.mat, &ret.mat); + InternalIO.Intrinsic.add_mat_3( &left.mat, &right.mat, &ret.mat ); return ret; } diff --git a/StgSharp.Common/Math/Linear/Matrix44.cs b/StgSharp.Common/Math/Linear/Matrix44.cs index 6e633415..84756810 100644 --- a/StgSharp.Common/Math/Linear/Matrix44.cs +++ b/StgSharp.Common/Math/Linear/Matrix44.cs @@ -40,10 +40,10 @@ using System.Runtime.InteropServices; namespace StgSharp.Math { [StructLayout( - LayoutKind.Explicit, - Size = ( 2 * 16 * sizeof( float ) ) + sizeof( bool ), - Pack = 16 )] - public unsafe struct Matrix44 : IEquatable, IMat + LayoutKind.Explicit, + Size = ( 2 * 16 * sizeof( float ) ) + sizeof( bool ), + Pack = 16 )] + public unsafe struct Matrix44 : IEquatable, IMatrix { [FieldOffset( 2 * 64 * sizeof( float ) )] internal bool isTransposed; @@ -55,26 +55,20 @@ namespace StgSharp.Math [FieldOffset( 8 * sizeof( float ) )] internal Vec4 colum2; [FieldOffset( 12 * sizeof( float ) )] internal Vec4 colum3; - public Matrix44() - { - Unsafe.SkipInit(out this); - isTransposed = false; - } - internal Matrix44( ColumnSet4 mat ) { - Unsafe.SkipInit(out this); + Unsafe.SkipInit( out this ); isTransposed = false; this.mat = mat; } internal Matrix44( - Vector4 vec0, - Vector4 vec1, - Vector4 vec2, - Vector4 vec3 ) + Vector4 vec0, + Vector4 vec1, + Vector4 vec2, + Vector4 vec3 ) { - Unsafe.SkipInit(out this); + Unsafe.SkipInit( out this ); isTransposed = false; mat.colum0 = vec0; mat.colum1 = vec1; @@ -82,25 +76,31 @@ namespace StgSharp.Math mat.colum3 = vec3; } - public unsafe Matrix44( - float a00, - float a01, - float a02, - float a03, - float a10, - float a11, - float a12, - float a13, - float a20, - float a21, - float a22, - float a23, - float a30, - float a31, - float a32, - float a33 ) + public Matrix44() { - Unsafe.SkipInit(out this); + Unsafe.SkipInit( out this ); + isTransposed = false; + } + + public unsafe Matrix44( + float a00, + float a01, + float a02, + float a03, + float a10, + float a11, + float a12, + float a13, + float a20, + float a21, + float a22, + float a23, + float a30, + float a31, + float a32, + float a33 ) + { + Unsafe.SkipInit( out this ); isTransposed = false; mat.colum0 = new Vector4( a00, a10, a20, a30 ); mat.colum1 = new Vector4( a01, a11, a21, a31 ); @@ -195,6 +195,35 @@ namespace StgSharp.Math mat.colum2.GetHashCode(), mat.colum3.GetHashCode() ); } + [MethodImpl( MethodImplOptions.AggressiveInlining )] + public unsafe Matrix42 Multiple( in Matrix42 right ) + { + InternalTranspose(); + Matrix42 ans = new Matrix42(); + fixed( ColumnSet4* lptr = &transpose ) { + fixed( Vector4* rptr = &right.mat.colum0 ) { + InternalIO.Intrinsic.dot_42( lptr, rptr, &ans.mat.colum0 ); + } + } + + return ans; + } + + public unsafe Matrix43 Multiple( in Matrix43 right ) + { + InternalTranspose(); + + Matrix43 ans = new Matrix43(); + + fixed( Vector4* rptr = &right.mat.colum0 ) { + fixed( ColumnSet4* lptr = &transpose ) { + InternalIO.Intrinsic.dot_43( lptr, rptr, &ans.mat.colum0 ); + } + } + + return ans; + } + public override string ToString() { InternalTranspose(); @@ -214,8 +243,8 @@ namespace StgSharp.Math [MethodImpl( MethodImplOptions.AggressiveInlining )] public static unsafe Matrix44 operator -( - Matrix44 left, - Matrix44 right ) + Matrix44 left, + Matrix44 right ) { return new Matrix44( right.mat.colum0 - left.mat.colum0, @@ -237,50 +266,26 @@ namespace StgSharp.Math mat.mat.colum2 * value, mat.mat.colum3 * value ); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public unsafe Matrix42 Multiple(in Matrix42 right) - { - InternalTranspose(); - Matrix42 ans = new Matrix42(); - fixed (ColumnSet4* lptr = &transpose) - fixed (Vector4* rptr = &right.mat.colum0) - { - InternalIO.Intrinsic.dot_42(lptr,rptr, &ans.mat.colum0); - } - return ans; - } - - [Obsolete("The operand may cause performance loss, use Matrix.Multiple() method instead.",false)] + [Obsolete( + "The operand may cause performance loss, use Matrix.Multiple() method instead.", + false )] [MethodImpl( MethodImplOptions.AggressiveInlining )] public static unsafe Matrix42 operator *( - Matrix44 left, - Matrix42 right ) + Matrix44 left, + Matrix42 right ) { - return left.Multiple(right); + return left.Multiple( right ); } - public unsafe Matrix43 Multiple(in Matrix43 right) - { - InternalTranspose(); - - Matrix43 ans = new Matrix43(); - - fixed(Vector4* rptr = &right.mat.colum0) - fixed (ColumnSet4* lptr = &transpose) - { - InternalIO.Intrinsic.dot_43(lptr,rptr,&ans.mat.colum0); - } - return ans; - } - - [Obsolete("The operand may cause performance loss, use Matrix.Multiple() method instead.", false)] + [Obsolete( + "The operand may cause performance loss, use Matrix.Multiple() method instead.", + false )] [MethodImpl( MethodImplOptions.AggressiveInlining )] public static Matrix43 operator *( Matrix44 left, Matrix43 right ) { - return left.Multiple(in right); + return left.Multiple( in right ); } - [MethodImpl( MethodImplOptions.AggressiveInlining )] public static Matrix44 operator *( Matrix44 left, Matrix44 right ) { @@ -308,10 +313,12 @@ namespace StgSharp.Math } [MethodImpl( MethodImplOptions.AggressiveInlining )] - public static unsafe Matrix44 operator +(Matrix44 left, Matrix44 right ) + public static unsafe Matrix44 operator +( + Matrix44 left, + Matrix44 right ) { Matrix44 ret = new Matrix44(); - InternalIO.Intrinsic.add_mat_4(&left.mat, &right.mat, &ret.mat); + InternalIO.Intrinsic.add_mat_4( &left.mat, &right.mat, &ret.mat ); return ret; } diff --git a/StgSharp.Common/Math/Linear/Vec2.cs b/StgSharp.Common/Math/Linear/Vec2.cs index a7c7ea12..1d8da84d 100644 --- a/StgSharp.Common/Math/Linear/Vec2.cs +++ b/StgSharp.Common/Math/Linear/Vec2.cs @@ -28,6 +28,9 @@ // //----------------------------------------------------------------------- //----------------------------------------------------------------------- +using StgSharp.HighPerformance; + +using System.Net.Http.Headers; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -35,20 +38,20 @@ using System.Runtime.InteropServices; namespace StgSharp.Math { /// - /// A two dimension vector defined by two elements. Vec2Ds in StgSharp are default used as colum + /// A two dimension vector defined by two elements. Vec2 in StgSharp are default used as colum /// vector. /// [StructLayout( LayoutKind.Explicit, Size = 16, Pack = 16 )] - public struct Vec2 : IVector + public struct Vec2 : IVector { [FieldOffset( 0 )] internal unsafe fixed float num[ 2 ]; [FieldOffset( 0 )] - internal Vector2 v; + internal M128 reg; [FieldOffset( 0 )] - internal Vector4 vec; + internal Vector2 v; [FieldOffset( 0 )] public float X; @@ -57,12 +60,19 @@ namespace StgSharp.Math internal Vec2( Vector2 vec ) { + Unsafe.SkipInit( out reg ); + Unsafe.SkipInit( out X ); + Unsafe.SkipInit( out Y ); v = vec; } - internal Vec2( Vector4 vec ) + internal Vec2( M128 vec ) { - this.vec = vec; + Unsafe.SkipInit( out reg ); + Unsafe.SkipInit( out X ); + Unsafe.SkipInit( out Y ); + reg = vec; + reg.Write( 1, 0 ); } public Vec2( float x, float y ) @@ -74,6 +84,27 @@ namespace StgSharp.Math public static Vec2 Zero => new Vec2( 0, 0 ); + public static Vec2 One + { + get => new Vec2( 1, 1 ); + } + + public Vec2 XY + { + get => this; + set => this = value; + } + + public Vec3 XYZ + { + get => new Vec3( reg ); + set + { + reg = value.reg; + reg.Write( 1, 0 ); + } + } + [MethodImpl( MethodImplOptions.AggressiveInlining )] public float Cross( Vec2 right ) { diff --git a/StgSharp.Common/Math/Linear/Vec3.cs b/StgSharp.Common/Math/Linear/Vec3.cs index 9fba0367..e24de603 100644 --- a/StgSharp.Common/Math/Linear/Vec3.cs +++ b/StgSharp.Common/Math/Linear/Vec3.cs @@ -38,26 +38,26 @@ using System.Runtime.InteropServices; namespace StgSharp.Math { [StructLayout( LayoutKind.Explicit, Size = 16, Pack = 16 )] - public struct Vec3 : IEquatable, IVector + public struct Vec3 : IEquatable, IVector { [FieldOffset( 0 )] internal unsafe fixed float num[ 3 ]; - [FieldOffset( 0 )] - internal M128 reg; + [FieldOffset( 0 )] internal M128 reg; - [FieldOffset( 0 )] - internal Vector3 v; - - [FieldOffset( 0 )] - internal Vector4 vec; + [FieldOffset( 0 )] internal Vector3 v; [FieldOffset( 0 )] public float X; [FieldOffset( 4 )] public float Y; [FieldOffset( 8 )] public float Z; - internal Vec3( Vector4 vector ) + internal Vec3( M128 vector ) { - vec = vector; + Unsafe.SkipInit( out X ); + Unsafe.SkipInit( out Y ); + Unsafe.SkipInit( out Z ); + Unsafe.SkipInit( out v ); + reg = vector; + reg.Write( 3, 0 ); } internal Vec3( Vector3 vector ) @@ -67,21 +67,26 @@ namespace StgSharp.Math public Vec3( Vec2 xy, float z ) { - vec = xy.vec; + Unsafe.SkipInit( out X ); + Unsafe.SkipInit( out Y ); + Unsafe.SkipInit( out Z ); + Unsafe.SkipInit( out v ); + reg = xy.reg; Z = z; } public Vec3( float x, float y, float z ) { - #if NET5_0_OR_GREATER - Unsafe.SkipInit( out vec ); - #endif + Unsafe.SkipInit( out reg ); + Unsafe.SkipInit( out X ); + Unsafe.SkipInit( out Y ); + Unsafe.SkipInit( out Z ); v = new Vector3( x, y, z ); } public unsafe Vec2 XY { - get => new Vec2( this.vec ); + get => new Vec2( this.reg ); set { fixed( Vector3* vptr = &v ) { @@ -93,6 +98,7 @@ namespace StgSharp.Math public Vec3 XYZ { get { return new Vec3( v ); } + set { this = value; } } public static Vec3 Zero @@ -122,7 +128,7 @@ namespace StgSharp.Math public bool Equals( Vec3 other ) { - return this.vec == other.vec; + return this.reg == other.reg; } public override bool Equals( object obj ) @@ -168,7 +174,7 @@ namespace StgSharp.Math [MethodImpl( MethodImplOptions.AggressiveInlining )] public static Vec3 operator -( Vec3 vec ) { - return new Vec3( -vec.vec ); + return new Vec3( -vec.v ); } [MethodImpl( MethodImplOptions.AggressiveInlining )] @@ -204,7 +210,7 @@ namespace StgSharp.Math [MethodImpl( MethodImplOptions.AggressiveInlining )] public static Vec3 operator +( Vec3 left, Vec3 right ) { - return new Vec3( left.vec + right.vec ); + return new Vec3( left.v + right.v ); } [MethodImpl( MethodImplOptions.AggressiveInlining )] @@ -217,9 +223,8 @@ namespace StgSharp.Math public static unsafe implicit operator Vec3( (float, float, float) tuple ) { - Vec3 v = *( Vec3* )&tuple; - v.vec.W = 0.0f; - return v; + Vec3 vec = new Vec3( *( Vector3* )&tuple ); + return vec; } } diff --git a/StgSharp.Common/Math/Linear/Vec4.cs b/StgSharp.Common/Math/Linear/Vec4.cs index 6382a4f4..0e8e798c 100644 --- a/StgSharp.Common/Math/Linear/Vec4.cs +++ b/StgSharp.Common/Math/Linear/Vec4.cs @@ -41,7 +41,7 @@ using System.Runtime.InteropServices; namespace StgSharp.Math { [StructLayout( LayoutKind.Explicit, Size = 16, Pack = 16 )] - public struct Vec4 : IEquatable, IVector + public struct Vec4 : IEquatable, IVector { [FieldOffset( 0 )] internal unsafe fixed float num[ 4 ]; @@ -57,12 +57,33 @@ namespace StgSharp.Math internal Vec4( Vector4 v ) { + Unsafe.SkipInit( out X ); + Unsafe.SkipInit( out Y ); + Unsafe.SkipInit( out Z ); + Unsafe.SkipInit( out W ); + Unsafe.SkipInit( out reg ); + vec = v; } - public Vec4( Vec3 v, float w ) + internal Vec4( M128 v ) { - vec = v.vec; + Unsafe.SkipInit( out X ); + Unsafe.SkipInit( out Y ); + Unsafe.SkipInit( out Z ); + Unsafe.SkipInit( out W ); + Unsafe.SkipInit( out vec ); + + reg = v; + } + + public Vec4( Vec3 v3, float w ) + { + Unsafe.SkipInit( out X ); + Unsafe.SkipInit( out Y ); + Unsafe.SkipInit( out Z ); + Unsafe.SkipInit( out W ); + reg = v3.reg; W = w; } @@ -73,7 +94,7 @@ namespace StgSharp.Math public unsafe Vec2 XY { - get => new Vec2( vec ); + get => new Vec2( reg ); set { X = value.X; @@ -83,23 +104,23 @@ namespace StgSharp.Math public unsafe Vec3 XYZ { - get => new Vec3( vec ); + get => new Vec3( reg ); set { float w = W; - vec = value.vec; + reg = value.reg; W = w; } } public static Vec4 One { - get => new Vec4( Vector4.One ); + get => new Vec4( 1, 1, 1, 1 ); } public static Vec4 Zero { - get => new Vec4( Vector4.Zero ); + get => new Vec4( 0, 0, 0, 0 ); } [MethodImpl( MethodImplOptions.AggressiveInlining )] diff --git a/StgSharp.Common/Math/Linear/Vector.Normalize.cs b/StgSharp.Common/Math/Linear/Vector.Normalize.cs index 5ba9919a..060e6d97 100644 --- a/StgSharp.Common/Math/Linear/Vector.Normalize.cs +++ b/StgSharp.Common/Math/Linear/Vector.Normalize.cs @@ -51,7 +51,7 @@ namespace StgSharp.Math public static Vec3 Normalize( Vec3 vec ) { - return new Vec3 { vec = Vector4.Normalize( vec.vec ) }; + return new Vec3 { v = Vector3.Normalize( vec.v ) }; } public static unsafe void Normalize( ref Vec4 source, ref Vec4 target ) diff --git a/StgSharp.Common/Math/Linear/Vector.Orthogonalize.cs b/StgSharp.Common/Math/Linear/Vector.Orthogonalize.cs index 5cd1da89..37ac187e 100644 --- a/StgSharp.Common/Math/Linear/Vector.Orthogonalize.cs +++ b/StgSharp.Common/Math/Linear/Vector.Orthogonalize.cs @@ -55,8 +55,8 @@ namespace StgSharp.Math } public static unsafe void Orthogonalize( - ref Vec4 source, - ref Vec4 target ) + ref Vec4 source, + ref Vec4 target ) { Vector4 s = source.vec; Vector4 t = target.vec; @@ -79,8 +79,8 @@ namespace StgSharp.Math /// /// public static unsafe void Orthogonalize( - ref Vec3 source, - ref Vec3 target ) + ref Vec3 source, + ref Vec3 target ) { Vector3 s = source.v; Vector3 t = target.v; diff --git a/StgSharp.Common/Math/Scalar/ACos.cs b/StgSharp.Common/Math/Scalar/ACos.cs index 90e8744d..c352f2a6 100644 --- a/StgSharp.Common/Math/Scalar/ACos.cs +++ b/StgSharp.Common/Math/Scalar/ACos.cs @@ -60,7 +60,7 @@ namespace StgSharp.Math throw new ArgumentException(); } - float r, s, u, v = 0.0f; + float r, s, u, vec = 0.0f; bool transform = (y >= 0.5f); if (transform) @@ -93,16 +93,16 @@ namespace StgSharp.Math c = (r - s1 * s1) / (s + s1); p = 2.0F * s * u - (piby2_tail - 2.0F * c); q = hpiby2_head - 2.0F * s1; - v = hpiby2_head - (p - q); + vec = hpiby2_head - (p - q); } else { - v = y + y * u; + vec = y + y * u; } - v = sign * v; + vec = sign * vec; - return piby2 - v; + return piby2 - vec; */ } diff --git a/StgSharp.Common/Math/Scalar/ASin.cs b/StgSharp.Common/Math/Scalar/ASin.cs index 7b32d995..bb32dd13 100644 --- a/StgSharp.Common/Math/Scalar/ASin.cs +++ b/StgSharp.Common/Math/Scalar/ASin.cs @@ -68,7 +68,7 @@ namespace StgSharp.Math throw new ArgumentException(); } - float r, s, u, v = 0.0f; + float r, s, u, vec = 0.0f; bool transform = (y >= 0.5f); if (transform) @@ -101,14 +101,14 @@ namespace StgSharp.Math c = (r - s1 * s1) / (s + s1); p = 2.0F * s * u - (piby2_tail - 2.0F * c); q = hpiby2_head - 2.0F * s1; - v = hpiby2_head - (p - q); + vec = hpiby2_head - (p - q); } else { - v = y + y * u; + vec = y + y * u; }/* - return sign * v; + return sign * vec; */ } diff --git a/StgSharp.Common/Math/Scalar/ATan.cs b/StgSharp.Common/Math/Scalar/ATan.cs index e9068cd2..b3a8c1b0 100644 --- a/StgSharp.Common/Math/Scalar/ATan.cs +++ b/StgSharp.Common/Math/Scalar/ATan.cs @@ -63,11 +63,11 @@ namespace StgSharp.Math angle = 0.7853981634f; } - float v = 0.7853981634f * x + x * (1 - x) * (0.2447f + 0.0663f * x); - v += angle; - v *= sign; + float vec = 0.7853981634f * x + x * (1 - x) * (0.2447f + 0.0663f * x); + vec += angle; + vec *= sign; - return v; + return vec; } @@ -105,13 +105,13 @@ namespace StgSharp.Math angle2 = 0.7853981634f; } - float v = 0.7853981634f * z + z * (1 - z) * (0.2447f + 0.0663f * z); - v *= 57.29577951f; - v += angle2; - v += angle; - v *= sign; + float vec = 0.7853981634f * z + z * (1 - z) * (0.2447f + 0.0663f * z); + vec *= 57.29577951f; + vec += angle2; + vec += angle; + vec *= sign; - return v; + return vec; */ } diff --git a/StgSharp.Common/PipeLine/Blueprint.NodeCraeater.cs b/StgSharp.Common/PipeLine/Blueprint.NodeCraeater.cs new file mode 100644 index 00000000..ba758b68 --- /dev/null +++ b/StgSharp.Common/PipeLine/Blueprint.NodeCraeater.cs @@ -0,0 +1,58 @@ +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// file="PipeLine.NodeCraeater.cs" +// Project: StgSharp +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and +// this permission notice shall be included in all copies +// or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, +// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +using System; +using System.Collections.Generic; +using System.Text; + +namespace StgSharp.PipeLine +{ + public partial class BlueprintScheduler + { + + public PipeLineNode CreateBlueprintNode( + string name, + BlueprintNodeOperation operation, + string[] inputPort, + string[] outputPort, + bool isNative ) + { + PipeLineNode node = new PipeLineNode( + operation, name, isNative, inputPort, outputPort ); + if( isNative ) { + mainThreadNodeList.Add( node ); + } else { + globalNodeList.Add( node ); + } + return node; + } + + } +} diff --git a/StgSharp.Common/PipeLine/Blueprint.cs b/StgSharp.Common/PipeLine/Blueprint.cs new file mode 100644 index 00000000..9d872be0 --- /dev/null +++ b/StgSharp.Common/PipeLine/Blueprint.cs @@ -0,0 +1,177 @@ +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// file="Blueprint.cs" +// Project: StgSharp +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and +// this permission notice shall be included in all copies +// or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, +// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Threading; + +namespace StgSharp.PipeLine +{ + /// + /// A sets of complex logic designed for running in multi threads environment. Warning: do not + /// run a instance in multi threads more than once. + /// + public partial class BlueprintScheduler : IConvertableToBlueprintNode + { + + private List[] _concurrentNodes, _mainThreadNodes; + + private BeginningNode beginNode; + private Dictionary allNode; + private EndingNode endNode; + + private Func terminate; + private List globalNodeList; + private List mainThreadNodeList; + + private SemaphoreSlim runningStat; + + internal int currentGlobalNodeIndex; + internal int currentNativeNodeIndex; + + public BlueprintScheduler() + { + allNode = new Dictionary(); + globalNodeList = new List(); + mainThreadNodeList = new List(); + runningStat = new SemaphoreSlim( 1, 1 ); + beginNode = new BeginningNode( this ); + endNode = new EndingNode( this ); + } + + public BlueprintNodeOperation Operation + { + get => ExecuteMain; + } + + public bool IsRunning + { + get => runningStat.CurrentCount == 0; + } + + public IEnumerable InputInterfacesName + { + get { return beginNode.OutputInterfaces.Keys; } + } + + public IEnumerable OutputInterfacesName + { + get { return beginNode.OutputInterfaces.Keys; } + } + + public PipeLineNode BeginLayer => beginNode; + + public PipeLineNode EndLayer => endNode; + + /**/ + + internal SemaphoreSlim RunningStat + { + get => runningStat; + } + /**/ + + public void AddNode( PipeLineNode node, bool isNative ) + { + _ = node ?? throw new ArgumentNullException( nameof( node ) ); + node.IsNative = isNative; + allNode.Add( node.Name, node ); + } + + public void ExecuteMain( + in Dictionary input, + in Dictionary output ) + { + PipeLineRunner.Run( this ); + } + + [MethodImpl( MethodImplOptions.AggressiveInlining )] + public (string name, PipeLineConnectorArgs arg)[] GetOutput() + { + return endNode.OutputData; + } + + public void Init() + { + foreach( KeyValuePair item in allNode ) { + if( item.Value.IsNative ) { + mainThreadNodeList.Add( item.Value ); + } else { + globalNodeList.Add( item.Value ); + } + } + mainThreadNodeList.Sort(); + globalNodeList.Sort(); + } + + [MethodImpl( MethodImplOptions.AggressiveInlining )] + public void SetInput( + params (string name, PipeLineConnectorArgs arg)[] parameters ) + { + beginNode.InputData = parameters; + } + + public void Terminate() + { + Interlocked.Exchange( ref currentGlobalNodeIndex, int.MaxValue ); + Interlocked.Exchange( ref currentNativeNodeIndex, int.MaxValue ); + } + + internal bool RequestNexGlobalNode( out PipeLineNode node ) + { + if( currentGlobalNodeIndex < globalNodeList.Count ) { + node = globalNodeList[ currentGlobalNodeIndex ]; + Interlocked.Increment( ref currentGlobalNodeIndex ); + return true; + } + node = default!; + return false; + } + + internal bool RequestNextNativeNode( out PipeLineNode node ) + { + if( currentNativeNodeIndex < mainThreadNodeList.Count ) { + node = mainThreadNodeList[ currentNativeNodeIndex ]; + Interlocked.Increment( ref currentNativeNodeIndex ); + return true; + } + node = default!; + return false; + } + + ~BlueprintScheduler() + { + runningStat.Dispose(); + } + + } +} diff --git a/StgSharp.Common/PipeLine/Connector.cs b/StgSharp.Common/PipeLine/Connector.cs new file mode 100644 index 00000000..b79289af --- /dev/null +++ b/StgSharp.Common/PipeLine/Connector.cs @@ -0,0 +1,168 @@ +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// file="Connector.cs" +// Project: StgSharp +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and +// this permission notice shall be included in all copies +// or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, +// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Security.Authentication.ExtendedProtection; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace StgSharp.PipeLine +{ + public class PipelineConnector + { + + private protected PipeLineNode after; + private protected PipeLineNode former; + private protected PipeLineConnectorArgs args; + private protected SemaphoreSlim formerCompleteSemaphore; + + public PipelineConnector( PipeLineNode former, PipeLineNode after ) + { + this.former = former; + this.after = after; + formerCompleteSemaphore = new SemaphoreSlim( + initialCount: 0, maxCount: 1 ); + } + + public PipeLineNode After => after; + + public PipeLineNode Former => former; + + public PipeLineConnectorArgs Args + { + get => args; + set => args = value; + } + + public int Level => former.Level; + + public static void SkipAll( + Dictionary ports ) + { + if( ports == null ) { + return; + } + foreach( KeyValuePair item in ports ) { + if( item.Value != null ) { + item.Value.CompleteAndSkip(); + } + } + } + + public static void WaitAll( + Dictionary ports ) + { + if( ports == null ) { + return; + } + foreach( KeyValuePair item in ports ) { + if( item.Value != null ) { + item.Value.WaitForStart(); + } + } + } + + public virtual void WaitForStart() + { + //Console.WriteLine($"Waiting \t{former.ContextName}\t->\t{after.ContextName}"); + formerCompleteSemaphore.Wait(); + } + + ~PipelineConnector() + { + formerCompleteSemaphore.Dispose(); + } + + #region pipline op + + [MethodImpl( MethodImplOptions.AggressiveInlining )] + public void CompleteAndSkip() + { + //Console.WriteLine($"Complete\t{former.Name}\t->\t{after.Name}"); + formerCompleteSemaphore.Release(); + } + + [MethodImpl( MethodImplOptions.AggressiveInlining )] + public void CompleteAndWriteData( PipeLineConnectorArgs args ) + { + this.args = args; + CompleteAndSkip(); + } + + #endregion + } + + public abstract class PipeLineConnectorArgs + { + + public object? Value + { + get; + set; + } + + public object? ValueDefault + { + get; + } + + } + + public sealed class SealedBlueprintPiipeline : PipelineConnector + { + + internal SealedBlueprintPiipeline( + PipeLineNode former, + PipeLineNode after ) + : base( former, after ) { } + + public static SealedBlueprintPiipeline SealInput( + PipeLineNode node, + string portName ) + { + return new SealedBlueprintPiipeline( PipeLineNode.Empty, node ); + } + + public static SealedBlueprintPiipeline SealOutput( + PipeLineNode node, + string portName ) + { + return new SealedBlueprintPiipeline( node, PipeLineNode.Empty ); + } + + public override sealed void WaitForStart() { } + + } +} diff --git a/StgSharp.Common/PipeLine/CrossFramePipelineNode.cs b/StgSharp.Common/PipeLine/CrossFramePipelineNode.cs new file mode 100644 index 00000000..917d3874 --- /dev/null +++ b/StgSharp.Common/PipeLine/CrossFramePipelineNode.cs @@ -0,0 +1,91 @@ +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// file="CrossFramePipelineNode.cs" +// Project: StgSharp +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and +// this permission notice shall be included in all copies +// or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, +// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +using StgSharp.PipeLine; + +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace StgSharp.PipeLine +{ + public class CrossFrameOperation : IConvertableToBlueprintNode + { + + private static string[] _inputName = ["TaskIn"]; + private static string[] _outputName = ["TaskOut"]; + private Action _mainExecution; + private int currentCount; + private readonly int cycleCount; + + public CrossFrameOperation( Action startup, int cycleCount ) + { + MainExecution = startup; + this.cycleCount = ( cycleCount > 1 ) ? + cycleCount : throw new ArgumentException( + $"{$"The {typeof(CrossFrameOperation).Name} crosses only one cycle, "}{$"please use a {typeof(PipeLineNode).Name} instead."}" ); + this.cycleCount = cycleCount; + currentCount = cycleCount; + } + + public Action MainExecution + { + get => _mainExecution; + private protected set => _mainExecution = value; + } + + public BlueprintNodeOperation Operation + { + get => ExecuteMain; + } + + public IEnumerable InputInterfacesName => _inputName; + + public IEnumerable OutputInterfacesName => _outputName; + + public void ExecuteMain( + in Dictionary input, + in Dictionary output ) + { + if( currentCount < cycleCount ) { + Interlocked.Increment( ref currentCount ); + } else { + Interlocked.Exchange( ref currentCount, 0 ); + Task.Run( MainExecution ); + } + + //Console.WriteLine(currentCount); + PipelineConnector.SkipAll( output ); + } + + } +} diff --git a/StgSharp.Common/PipeLine/IConvertableToBlueprintNode.cs b/StgSharp.Common/PipeLine/IConvertableToBlueprintNode.cs new file mode 100644 index 00000000..5fe329db --- /dev/null +++ b/StgSharp.Common/PipeLine/IConvertableToBlueprintNode.cs @@ -0,0 +1,86 @@ +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// file="IConvertableToBlueprintNode.cs" +// Project: StgSharp +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and +// this permission notice shall be included in all copies +// or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, +// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Text; + +namespace StgSharp.PipeLine +{ + public delegate void BlueprintNodeOperation( + in Dictionary input, + in Dictionary output ); + + public interface IConvertableToBlueprintNode + { + + BlueprintNodeOperation Operation + { + get; + } + + public IEnumerable InputInterfacesName + { + get; + } + + public IEnumerable OutputInterfacesName + { + get; + } + + } + + internal class DefaultConvertableToBlueprintNode : IConvertableToBlueprintNode + { + + private string[] _input; + private string[] _output; + private BlueprintNodeOperation _execution; + + public DefaultConvertableToBlueprintNode( + BlueprintNodeOperation execution, + string[] input, + string[] output ) + { + _input = input; + _output = output; + _execution = execution; + } + + public BlueprintNodeOperation Operation => _execution; + + public IEnumerable InputInterfacesName => _input; + + public IEnumerable OutputInterfacesName => _output; + + } +} diff --git a/StgSharp.Common/PipeLine/PipeLineNode.cs b/StgSharp.Common/PipeLine/PipeLineNode.cs new file mode 100644 index 00000000..3cdb8bc6 --- /dev/null +++ b/StgSharp.Common/PipeLine/PipeLineNode.cs @@ -0,0 +1,300 @@ +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// file="PipeLineNode.cs" +// Project: StgSharp +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and +// this permission notice shall be included in all copies +// or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, +// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +using StgSharp.Entities; + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.Serialization; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace StgSharp.PipeLine +{ + /// + /// + /// + /// + /// Reset pipeline has risk, this operation is a direct operation to port in current node, the + /// port on the other node cannot get the change. + /// +#pragma warning disable CA1036 + public class PipeLineNode : IComparable + #pragma warning restore CA1036 + { + + private static Dictionary _emptyLayer = new(); + + private static PipeLineNode _emptyNode = new PipeLineNode( + string.Empty, null!, false ); + private IConvertableToBlueprintNode _mainOperation; + private string _name; + private protected bool _levelAvailable, _nativeRequested; + private protected Dictionary _inputInterfaces; + private protected Dictionary _outputInterfaces; + private protected int _level; + + internal PipeLineNode( + string name, + IConvertableToBlueprintNode node, + bool isNative ) + { + _levelAvailable = false; + _name = name; + _nativeRequested = isNative; + _mainOperation = node; + _inputInterfaces = new Dictionary(); + _outputInterfaces = new Dictionary(); + foreach( string portName in node.InputInterfacesName ) { + _inputInterfaces.Add( portName, null! ); + } + + foreach( string portName in node.OutputInterfacesName ) { + _outputInterfaces.Add( portName, null! ); + } + } + + #pragma warning disable CS8618 + internal PipeLineNode( + BlueprintNodeOperation operation, + string name, + bool isNative, + string[] inputPorts, + string[] outputPorts ) + #pragma warning restore CS8618 + { + if( ( inputPorts == null ) || ( inputPorts.Length == 0 ) ) { + throw new ArgumentNullException( nameof( inputPorts ) ); + } + if( ( outputPorts == null ) || ( outputPorts.Length == 0 ) ) { + throw new ArgumentNullException( nameof( outputPorts ) ); + } + _levelAvailable = false; + _name = name; + _nativeRequested = isNative; + operation = operation ?? DefaultOperation; + _mainOperation = new DefaultConvertableToBlueprintNode( + operation, inputPorts, outputPorts ); + _inputInterfaces = new Dictionary(); + _outputInterfaces = new Dictionary(); + foreach( string portName in inputPorts ) { + _inputInterfaces.Add( + portName, + SealedBlueprintPiipeline.SealOutput( this, name ) ); + } + foreach( string portName in outputPorts ) { + _outputInterfaces.Add( portName, null! ); + } + } + + public bool IsNative + { + get => _nativeRequested; + internal set => _nativeRequested = value; + } + + public static Dictionary EmptyPortLayer + { + get => _emptyLayer; + } + + public int Level + { + get + { + if( _levelAvailable ) { + return _level; + } + _level = 0; + foreach( KeyValuePair item in _inputInterfaces ) { + if( item.Value == null ) { + continue; + } + if( _level < item.Value.Level ) { + _level = item.Value.Level; + } + } + _level += 1; + _levelAvailable = true; + return _level; + } + } + + public static PipeLineNode Empty + { + get => _emptyNode; + } + + public string Name => _name; + + internal Dictionary InputInterfaces => _inputInterfaces; + + internal Dictionary OutputInterfaces => _outputInterfaces; + + internal IConvertableToBlueprintNode Value + { + get => _mainOperation; + } + + public void Append( + [NotNull] PipeLineNode next, + string thisOutputPortName, + string afterInputPortName ) + { + this._levelAvailable = false; + PipelineConnector pipeline = new PipelineConnector( this, next ); + if( next is EndingNode enode ) { + enode.SetCertainInputPort( afterInputPortName, pipeline ); + } else { + next.SetCertainInputPort( afterInputPortName, pipeline ); + } + SetCertainOutputPort( thisOutputPortName, pipeline ); + } + + public int CompareTo( PipeLineNode other ) + { + if( null == other ) { + throw new ArgumentNullException( nameof( other ) ); + } + + return this.Level.CompareTo( other.Level ); + } + + public void Prepend( + [NotNull] PipeLineNode former, + string formerOutputPortName, + string thisInputPortName ) + { + this._levelAvailable = false; + PipelineConnector pipeline = new PipelineConnector( former, this ); + if( former is BeginningNode bnode ) { + bnode.SetCertainOutputPort( formerOutputPortName, pipeline ); + } else { + former.SetCertainOutputPort( formerOutputPortName, pipeline ); + } + SetCertainInputPort( thisInputPortName, pipeline ); + } + + public virtual void Run() + { + try { + //Console.WriteLine(_name); + PipelineConnector.WaitAll( _inputInterfaces ); + if( _mainOperation != null ) { + _mainOperation.Operation( + in _inputInterfaces, in _outputInterfaces ); + } + } + catch( Exception ) { + throw; + } + } + + protected static void DefaultOperation( + in Dictionary input, + in Dictionary output ) + { + PipelineConnector.SkipAll( output ); + } + + #region port operation + + public PipelineConnector GetInputPort( string name ) + { + PipelineConnector ret; + if( !_inputInterfaces.TryGetValue( name, out ret ) ) { + throw new ArgumentOutOfRangeException( + $"Cannot find the interface named {name} in node {Name}." ); + } + return ret; + } + + public PipelineConnector GetOutputPort( string name ) + { + PipelineConnector ret; + if( !_outputInterfaces.TryGetValue( name, out ret ) ) { + throw new ArgumentOutOfRangeException( + $"Cannot find the interface named {name} in node {Name}." ); + } + return ret; + } + + public void SetCertainInputPort( + string name, + PipelineConnector pipeline ) + { + if( !_inputInterfaces.ContainsKey( name ) ) { + throw new ArgumentException( + $"Cannot find the interface named {name} in node {Name}." ); + } + _inputInterfaces[ name ] = pipeline; + } + + public void SetCertainOutputPort( + string name, + PipelineConnector pipeline ) + { + if( !_outputInterfaces.ContainsKey( name ) ) { + throw new ArgumentOutOfRangeException( + $"Cannot find the interface named {name} in node {Name}." ); + } + _outputInterfaces[ name ] = pipeline; + } + + #endregion + }//--------------------------------- end of class ----------------------------------- + + public class BlueprintNodeRunException : Exception + { + + protected BlueprintNodeRunException( + SerializationInfo info, + StreamingContext context ) + : base( info, context ) { } + + public BlueprintNodeRunException() { } + + public BlueprintNodeRunException( Exception ex ) + : base( string.Empty, ex ) { } + + public BlueprintNodeRunException( string message ) : base( message ) { } + + public BlueprintNodeRunException( + string message, + Exception innerException ) + : base( message, innerException ) { } + + } +} diff --git a/StgSharp.Common/PipeLine/PipeLineRunner.cs b/StgSharp.Common/PipeLine/PipeLineRunner.cs new file mode 100644 index 00000000..1352c9d9 --- /dev/null +++ b/StgSharp.Common/PipeLine/PipeLineRunner.cs @@ -0,0 +1,228 @@ +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// file="PipeLineRunner.cs" +// Project: StgSharp +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and +// this permission notice shall be included in all copies +// or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, +// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +using StgSharp.Threading; + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Data; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading; + +using System.Threading.Tasks; + +namespace StgSharp.PipeLine +{ + public static class PipeLineRunner + { + + private static NodeRunner[] allAvailableTask = CreateBlueprintRunnerArray( + ); + private static CancellationTokenSource cts = new CancellationTokenSource( + ); + private static ConcurrentStack blueprintInWaiting + = new ConcurrentStack(); + private static int _callingThread; + private static SemaphoreSlim bpLock = new SemaphoreSlim( 0, 1 ); + + /// + /// Only the following occasions of calling are valid: 1. no bp is + /// running or the only bp is quitting. 2. calling from the main thread or a + /// thread the current bp is running on. + /// + internal static bool IsValidCalling + { + get + { + if( ( NodeRunner.CurrentBlueprint == null ) || //no bp running at all + ( ( blueprintInWaiting.IsEmpty ) && ( NodeRunner.CurrentBlueprint.IsRunning == + false ) ) ) { + // a bp is quitting + //in case no bp is running + return true; + } + int? id = Task.CurrentId; + if( id is null ) { + // in case calling from main thread and current running bp + return _callingThread == Environment.CurrentManagedThreadId; + } + foreach( NodeRunner item in allAvailableTask ) { + if( item.Id == id ) { + //if calling from any bp running task + return true; + } + } + return false; + } + } + + public static void Run( BlueprintScheduler blueprint ) + { + //Console.WriteLine(); + if( blueprint == null ) { + return; + } + if( blueprint.IsRunning ) { + throw new InvalidOperationException( + "Attempt to run a blueprint instance twice." ); + } + if( IsValidCalling ) { + //Console.WriteLine("valid and run"); + if( InterruptAndRunNewBp( blueprint ) ) { + while( InterruptAndRunNewBp( NodeRunner.CurrentBlueprint ) ) { } + ; + } + } else { + bpLock.Wait(); + if( InterruptAndRunNewBp( blueprint ) ) { + while( InterruptAndRunNewBp( NodeRunner.CurrentBlueprint ) ) { } + } + + bpLock.Release(); + } + Interlocked.Exchange( ref _callingThread, -1 ); + } + + public static void SetMaxTaskCount( int size ) + { + if( size < 1 ) { + size = 1; + } + if( allAvailableTask.Length >= size ) { + for( int i = size; i < allAvailableTask.Length; i++ ) { + if( allAvailableTask[ i ] != null ) { + allAvailableTask[ i ].Cancel(); + } + } + } + Array.Resize( ref allAvailableTask, size ); + } + + public static void Terminate() + { + cts.Cancel(); + NodeRunner.CurrentBlueprint.Terminate(); + foreach( NodeRunner task in allAvailableTask ) { + task.Cts.Cancel(); + } + foreach( BlueprintScheduler bp in blueprintInWaiting ) { + bp.Terminate(); + } + blueprintInWaiting.Clear(); + } + + internal static bool InterruptAndRunNewBp( BlueprintScheduler newBp ) + { + Debug.Assert( newBp != null ); + if( ( newBp != NodeRunner.CurrentBlueprint ) && ( NodeRunner.CurrentBlueprint != + null ) ) { + //if a running bp exists + blueprintInWaiting.Push( NodeRunner.CurrentBlueprint ); + } + + //load new bp to current bp + Interlocked.Exchange( ref NodeRunner.CurrentBlueprint!, newBp ); + Interlocked.Exchange( + ref _callingThread, Environment.CurrentManagedThreadId ); + + //run beginning node to init it first. + if( !NodeRunner.CurrentBlueprint.IsRunning ) { + ( NodeRunner.CurrentBlueprint.BeginLayer as BeginningNode )!.Run( + ); + } + + //refresh all tasks + for( int i = 0; i < allAvailableTask.Length; i++ ) { + NodeRunner item = allAvailableTask[ i ]; + if( ( item is null ) || item.IsCompleted ) { + allAvailableTask[ i ] = NodeRunner.Run(); + } + } + PipeLineNode node; + while( !cts.Token.IsCancellationRequested && NodeRunner.CurrentBlueprint + .RequestNextNativeNode( out node ) ) { + node.Run(); + if( !NodeRunner.CurrentBlueprint.IsRunning ) { + break; + } + } + ( NodeRunner.CurrentBlueprint.EndLayer as EndingNode )!.Run(); + return blueprintInWaiting.TryPeek( out NodeRunner.CurrentBlueprint ); + } + + private static NodeRunner[] CreateBlueprintRunnerArray() + { + int count = Environment.ProcessorCount; + return new NodeRunner[ count < 2 ? count : count - 2]; + } + + } + + internal class NodeRunner : CancellableTask + { + + private static BlueprintScheduler _current; + + internal NodeRunner() + : base() + { + _startup = InternalRun; + } + + internal static ref BlueprintScheduler CurrentBlueprint + { + get => ref _current; + } + + internal static NodeRunner Run() + { + NodeRunner ret = new NodeRunner { _startup = InternalRun }; + ret._internalTask = Task.Run( ret.InternalAction ); + return ret; + } + + private static void InternalRun( CancellationToken token ) + { + //Console.WriteLine("Task Begin"); + PipeLineNode item; + while( ( CurrentBlueprint != null ) && CurrentBlueprint.IsRunning && !token.IsCancellationRequested && CurrentBlueprint.RequestNexGlobalNode( + out item ) ) { + //Console.WriteLine($"Get node of {item.Name}, going to run."); + item.Run(); + } + + //Console.WriteLine("Task Completed"); + } + + }//------------------------------------- End of Class ------------------------------------------ +} diff --git a/StgSharp.Common/PipeLine/RouteSwitch.cs b/StgSharp.Common/PipeLine/RouteSwitch.cs new file mode 100644 index 00000000..29d66368 --- /dev/null +++ b/StgSharp.Common/PipeLine/RouteSwitch.cs @@ -0,0 +1,112 @@ +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// file="RouteSwitch.cs" +// Project: StgSharp +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and +// this permission notice shall be included in all copies +// or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, +// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection.Emit; +using System.Security.Cryptography.X509Certificates; +using System.Text; + +namespace StgSharp.PipeLine +{ + public class RouteSwitch : PipeLineNode + { + + private protected Dictionary openingRule)> outputDictionary; + + public RouteSwitch( string name, bool isNative, string inputPorts ) + : base( + DefaultOperation, name, isNative, [inputPorts], [string.Empty] ) + { + outputDictionary = new Dictionary openingRule)>( + ); + } + + public new int Level + { + get + { + if( _levelAvailable ) { + return _level; + } + _level = 0; + KeyValuePair item = _inputInterfaces.First( + ); + if( item.Value == null ) { + throw new InvalidOperationException(); + } + if( _level <= item.Value.Level ) { + _level = item.Value.Level; + } + return _level; + } + } + + public new void AddBefore( + PipeLineNode after, + string thisOutputPortName, + string afterInputPortName ) + { + this.AppendNode( after, afterInputPortName, () => true ); + } + + public void AppendNode( + PipeLineNode node, + string portName, + Func openningRule ) + { + if( node == null ) { + throw new ArgumentNullException( nameof( node ) ); + } + string indexName = $"{node.Name}.{portName}"; + PipelineConnector p = new PipelineConnector( this, node ); + node.InputInterfaces[ portName ] = p; + outputDictionary.Add( indexName, (p, openningRule) ); + } + + public new void Run() + { + try { + PipelineConnector input = InputInterfaces.First().Value; + input.WaitForStart(); + foreach( KeyValuePair openingRule)> item in outputDictionary ) { + if( item.Value.openingRule() ) { + item.Value.pipeline.CompleteAndWriteData( input.Args ); + } + } + } + catch( Exception ) { + throw; + } + } + + } +} diff --git a/StgSharp.Common/PipeLine/SideNode.cs b/StgSharp.Common/PipeLine/SideNode.cs new file mode 100644 index 00000000..952c8fcf --- /dev/null +++ b/StgSharp.Common/PipeLine/SideNode.cs @@ -0,0 +1,125 @@ +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// file="SideNode.cs" +// Project: StgSharp +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and +// this permission notice shall be included in all copies +// or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, +// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace StgSharp.PipeLine +{ + internal sealed class BeginningNode : PipeLineNode + { + + private BlueprintScheduler _bp; + + public BeginningNode( BlueprintScheduler bp ) + : base( + DefaultOperation, name: "BeginningNode", true, ["default"], + ["default"] ) + { + _bp = bp; + } + + internal (string name, PipeLineConnectorArgs arg)[] InputData + { + set + { + if( value == null ) { + return; + } + foreach( (string name, PipeLineConnectorArgs arg) parameter in value ) { + OutputInterfaces[ parameter.name ].Args = parameter.arg; + } + } + } + + public override void Run() + { + _bp.RunningStat.Wait(); + PipelineConnector.SkipAll( _outputInterfaces ); + } + + public new void SetCertainOutputPort( + string name, + PipelineConnector pipeline ) + { + if( _outputInterfaces.ContainsKey( name ) ) { + _outputInterfaces[ name ] = pipeline; + } + _outputInterfaces.Add( name, pipeline ); + } + + } + + internal sealed class EndingNode : PipeLineNode + { + + private BlueprintScheduler _bp; + + public EndingNode( BlueprintScheduler bp ) + : base( + DefaultOperation, name: "EndingNode", true, ["default"], + ["default"] ) + { + _bp = bp; + } + + internal (string name, PipeLineConnectorArgs arg)[] OutputData + { + get { return InputInterfaces.Select( + key => (key.Key, key.Value.Args) ) + .ToArray(); } + } + + public override void Run() + { + PipelineConnector.WaitAll( _inputInterfaces ); + Interlocked.Exchange( ref _bp.currentGlobalNodeIndex, 0 ); + Interlocked.Exchange( ref _bp.currentNativeNodeIndex, 0 ); + _bp.RunningStat.Release(); + } + + public new void SetCertainInputPort( + string name, + PipelineConnector pipeline ) + { + if( _inputInterfaces.ContainsKey( name ) ) { + _inputInterfaces[ name ] = pipeline; + } + _inputInterfaces.Add( name, pipeline ); + } + + } +} \ No newline at end of file diff --git a/StgSharp.Common/PlainGeometryCollisionSensor.cs b/StgSharp.Common/PlainGeometryCollisionSensor.cs new file mode 100644 index 00000000..e8f2bfba --- /dev/null +++ b/StgSharp.Common/PlainGeometryCollisionSensor.cs @@ -0,0 +1,81 @@ +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// file="PlainGeometryCollisionSensor.cs" +// Project: StgSharp +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and +// this permission notice shall be included in all copies +// or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, +// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +using StgSharp.Geometries; + +using System; + +namespace StgSharp +{ + public class CollisionEventArgs:EventArgs + { + public CollisionEventArgs(IGeometry target, IGeometry boarder) + { + Target = target; + Boarder = boarder; + } + + public IGeometry Target { get; set; } + public IGeometry Boarder { get; set; } + } + + public class PlainGeometryCollisionSensor + where TBoarder : IGeometry + where TTarget : IGeometry + { + internal PlainGeometry _boarder; + internal PlainGeometry _target; + internal EventHandler _rule; + + public event EventHandler Rule + { + add { _rule += value; } + remove + { + if (value == null) + { + return; + } +#pragma warning disable CS8601 + _rule -= value; +#pragma warning restore CS8601 + } + } + + public PlainGeometry boarder => _boarder; + + public PlainGeometry target + { + get => _target; + set => _target = value; + } + + } +} diff --git a/StgSharp.Common/StateMachine.cs b/StgSharp.Common/StateMachine.cs new file mode 100644 index 00000000..a3599e21 --- /dev/null +++ b/StgSharp.Common/StateMachine.cs @@ -0,0 +1,72 @@ +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// file="StateMachine.cs" +// Project: StgSharp +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and +// this permission notice shall be included in all copies +// or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, +// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StgSharp +{ + public interface IStateMachine where T: Enum + { + + public T LastStableState + { + get; + } + + public bool TryEnterState(); + + public bool TryExitState(); + + public bool TrySwitchState(); + + } + + public interface IStateMachineWithSwitchSpan : IStateMachine + where TState: Enum + { + + public bool IsInStabelState + { + get; + } + + public TState NextStableState + { + get; + } + + public bool TrySwitchState(); + + } +} diff --git a/StgSharp.Common/StgSharp.Common.csproj b/StgSharp.Common/StgSharp.Common.csproj index 34092131..1a35b2b2 100644 --- a/StgSharp.Common/StgSharp.Common.csproj +++ b/StgSharp.Common/StgSharp.Common.csproj @@ -83,6 +83,10 @@ + + + + diff --git a/StgSharp.Common/Threading/MainThreadAssert.cs b/StgSharp.Common/Threading/MainThreadAssert.cs index f7dd494d..e9327a40 100644 --- a/StgSharp.Common/Threading/MainThreadAssert.cs +++ b/StgSharp.Common/Threading/MainThreadAssert.cs @@ -50,8 +50,7 @@ namespace StgSharp.Threading { if( isNotMainThread.Value ) { throw new InvalidOperationException( - $"Attempt to call sensitive operation which can be only called from main thread " - + $"from thread {Environment.CurrentManagedThreadId}." ); + $"Attempt to call sensitive operation which can be only called from main thread " + $"from thread {Environment.CurrentManagedThreadId}." ); } } diff --git a/StgSharp.Common/Timing/TimeFunction.cs b/StgSharp.Common/Timing/TimeFunction.cs new file mode 100644 index 00000000..388f07c3 --- /dev/null +++ b/StgSharp.Common/Timing/TimeFunction.cs @@ -0,0 +1,164 @@ +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// file="TimeFunction.cs" +// Project: StgSharp +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and +// this permission notice shall be included in all copies +// or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, +// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +using System; +using System.Collections.Generic; +using System.Text; + +namespace StgSharp.Timing +{ + public class TimeFunction + { + + private float _beginning, _ending; + private Func _timeRelatedCalculation; + private TimeSpanProvider _timeProvider; + + internal TimeFunction() { } + + public TimeFunction( + TimeSpanProvider timeSpanProvider, + Func timeRelatedCalculation, + float range ) + { + _timeProvider = timeSpanProvider; + _timeRelatedCalculation = timeRelatedCalculation; + if( timeSpanProvider == null ) { + return; + } + _beginning = _timeProvider.CurrentSecond; + _ending = _timeProvider.CurrentSecond + range; + } + + public virtual bool IsComplete + { + get => _timeProvider.CurrentSecond > _ending; + } + + public Func TimeRelatedCalculation + { + get { return _timeRelatedCalculation; } + set { _timeRelatedCalculation = value; } + } + + public static TimeFunction One + { + get => new TimeFunctionOne(); + } + + public TimeSpanProvider TimeSpanProvider + { + get { return _timeProvider; } + set { _timeProvider = value; } + } + + public virtual float Calculate() + { + if( _timeProvider.CurrentSecond < _ending ) { + return 0; + } + return _timeRelatedCalculation( + _timeProvider.CurrentSecond - _beginning ); + } + + public static TimeFunction Proportional( + TimeSpanProvider time, + float begin, + float range ) + { + return new TimeFunction( time, ( float t ) => t + begin, range ); + } + + public virtual TimeFunction Renew( + (Func func, float range) funcPair ) + { + return new TimeFunction( + _timeProvider, funcPair.func, funcPair.range ); + } + + public virtual TimeFunction Renew( + Func func, + float range ) + { + return new TimeFunction( _timeProvider, func, range ); + } + + public void Reset() + { + float range = _ending - _beginning; + _beginning = _timeProvider.CurrentSecond; + _ending = _beginning + range; + } + + public virtual TimeFunction Reverse() + { + float range = _ending - _beginning; + return new TimeFunction( + _timeProvider, p => _timeRelatedCalculation( range - p ), + range ); + } + + } + + public sealed class TimeFunctionOne : TimeFunction + { + + internal TimeFunctionOne() : base() { } + + public override bool IsComplete + { + get => true; + } + + public override float Calculate() + { + return 1; + } + + public override TimeFunction Renew( + (Func func, float range) funcPair ) + { + throw new NotSupportedException(); + } + + public override TimeFunction Renew( + Func func, + float range ) + { + throw new NotSupportedException(); + } + + #pragma warning disable CA1822 + public new void Reset() + #pragma warning restore CA1822 + { } + + } +} diff --git a/StgSharp.Common/Timing/TimeProvider.cs b/StgSharp.Common/Timing/TimeProvider.cs new file mode 100644 index 00000000..f045b73c --- /dev/null +++ b/StgSharp.Common/Timing/TimeProvider.cs @@ -0,0 +1,152 @@ +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// file="TimeProvider.cs" +// Project: StgSharp +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and +// this permission notice shall be included in all copies +// or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, +// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- + +using StgSharp.Timing; + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Threading; + +namespace StgSharp +{ + public static partial class StgSharp + { + + internal static StgSharpTime mainTimeProvider = new StgSharpTime(); + + internal static TimeSourceProviderBase MainTimeProvider => mainTimeProvider; + + } + + public sealed class StgSharpTime : TimeSourceProviderBase + { + + private static List subscriberList = new List( + ); + private static long accuracy; + private static Stopwatch mainProvider = new Stopwatch(); + private static Thread timeProvideThread; + + internal StgSharpTime() { } + + public static TimeSourceProviderBase OnlyInstance => StgSharp.MainTimeProvider; + + public override sealed void StartProvidingTime() + { + if( mainProvider.IsRunning ) { + return; + } + mainProvider.Start(); + + //speed test + long totalMS, internalFrequncy = Stopwatch.Frequency; + for( int i = 0; i < 100; i++ ) { + totalMS = mainProvider.ElapsedTicks / ( internalFrequncy / ( 1000L * 1000L ) ); + for( int t = 0; t < 10; t++ ) { + if( totalMS < 1000 ) { + subscriberList.Add( + new TimeSpanProvider( + 100L, TimeSpanProvider.DefaultProvider ) ); + } + } + } + mainProvider.Stop(); + subscriberList.Clear(); + totalMS = mainProvider.ElapsedTicks / ( internalFrequncy / ( 1000L * 1000L ) ) / 100L; + accuracy = ( totalMS * 2 ) / 3; + mainProvider.Reset(); + timeProvideThread = new Thread( new ThreadStart( ProvideTime ) ); + timeProvideThread.Start(); + } + + public override void StopProvidingTime() + { + lock( mainProvider ) { + mainProvider.Stop(); + } + } + + public void Terminate() + { + lock( mainProvider ) { + mainProvider.Stop(); + } + } + + protected override sealed void AddSubscriberUnsynced( + TimeSpanProvider subscriber ) + { + subscriberList.Add( subscriber ); + } + + protected override sealed void RemoveSubscriberUnsynced( + TimeSpanProvider subscriber ) + { + subscriberList.Remove( subscriber ); + } + + private void ProvideTime() + { + long totalMS, internalFrequncy = Stopwatch.Frequency; + lock( mainProvider ) { + mainProvider.Restart(); + } + while( mainProvider.IsRunning ) { + totalMS = mainProvider.ElapsedTicks / ( internalFrequncy / ( 1000L * 1000L ) ); + if( subscriberList.Count == 0 ) { + continue; + } + CheckSubscriberSemaphore.Wait(); + List toRemoveList = new List( + ); + foreach( TimeSpanProvider subscriber in subscriberList ) { + if( !subscriber.CheckTime( totalMS ) ) { + toRemoveList.Add( subscriber ); + InternalIO.InternalWriteLog( + $"Time subscriber {subscriber} is to be removed.", + LogType.Info ); + } + ; + } + if( toRemoveList.Count != 0 ) { + foreach( TimeSpanProvider subscriber in toRemoveList ) { + subscriberList.Remove( subscriber ); + } + } + CheckSubscriberSemaphore.Release(); + } + } + + } +} \ No newline at end of file diff --git a/StgSharp.Common/Timing/TimeSourceProvider.cs b/StgSharp.Common/Timing/TimeSourceProvider.cs new file mode 100644 index 00000000..ea1fdacc --- /dev/null +++ b/StgSharp.Common/Timing/TimeSourceProvider.cs @@ -0,0 +1,89 @@ +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// file="TimeSourceProvider.cs" +// Project: StgSharp +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and +// this permission notice shall be included in all copies +// or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, +// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +using StgSharp; + +using System; +using System.Linq; +using System.Threading; + +namespace StgSharp.Timing +{ + public abstract class TimeSourceProviderBase + { + + private SemaphoreSlim _addSubscriberSemaphore = new SemaphoreSlim( + 1, 1 ); + + protected SemaphoreSlim CheckSubscriberSemaphore + { + get => _addSubscriberSemaphore; + } + + public void AddSubscriber( TimeSpanProvider subscriber ) + { + try { + _addSubscriberSemaphore.Wait(); + AddSubscriberUnsynced( subscriber ); + } + catch( Exception ) { + throw; + } + finally { + _addSubscriberSemaphore.Release(); + } + } + + public void RemoveSubscriber( TimeSpanProvider subscriber ) + { + _addSubscriberSemaphore.Wait(); + try { + RemoveSubscriberUnsynced( subscriber ); + } + catch( Exception ) { + throw; + } + finally { + _addSubscriberSemaphore.Release(); + } + } + + public abstract void StartProvidingTime(); + + public abstract void StopProvidingTime(); + + protected abstract void AddSubscriberUnsynced( + TimeSpanProvider subscriber ); + + protected abstract void RemoveSubscriberUnsynced( + TimeSpanProvider subscriber ); + + } +} diff --git a/StgSharp.Common/Timing/TimeSpanAwaitingToken.cs b/StgSharp.Common/Timing/TimeSpanAwaitingToken.cs new file mode 100644 index 00000000..7621d81c --- /dev/null +++ b/StgSharp.Common/Timing/TimeSpanAwaitingToken.cs @@ -0,0 +1,165 @@ +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// file="TimeSpanAwaitingToken.cs" +// Project: StgSharp +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and +// this permission notice shall be included in all copies +// or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, +// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics.Contracts; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace StgSharp.Timing +{ + #nullable enable + + public sealed class TimeSpanAwaitingToken : IDisposable + { + + private static readonly ConcurrentStack s_unusedID = new ConcurrentStack( + [0] ); + private static int s_maxID; + private static readonly object s_lock = new object(); + + private EventHandler? _refreshHandler,_missHandler; + private int _size, _id; + + private object _participantObject = new object(); + private SemaphoreSlim _awaitingSemaphore; + + private TimeSpanProvider _provider; + + internal TimeSpanAwaitingToken( TimeSpanProvider provider ) + { + if( s_unusedID.Count == 1 ) { + lock( s_lock ) { + s_unusedID.TryPop( out int id ); + TokenID = id; + s_unusedID.Push( s_maxID++ ); + } + } else { + s_unusedID.TryPop( out int id ); + TokenID = id; + } + _provider = provider; + _size = 1; + _awaitingSemaphore = new SemaphoreSlim( 0, 1 ); + } + + internal TimeSpanAwaitingToken( TimeSpanProvider provider, int count ) + { + if( s_unusedID.Count == 1 ) { + lock( s_lock ) { + s_unusedID.TryPop( out int id ); + TokenID = id; + s_unusedID.Push( s_maxID++ ); + } + } else { + s_unusedID.TryPop( out int id ); + TokenID = id; + } + _provider = provider; + _size = count; + _awaitingSemaphore = new SemaphoreSlim( 0, _size ); + } + + public event EventHandler MissTimeSpanRefreshed + { + add { _missHandler += value; } + remove { _missHandler -= value; } + } + + public event EventHandler TimeSpanRefreshed + { + add { _refreshHandler += value; } + remove { _refreshHandler -= value; } + } + + public int TokenID + { + get => _id; + private set => _id = value; + } + + internal SemaphoreSlim AwaitingSemaphoreSlim + { + get => _awaitingSemaphore; + } + + public void Dispose() + { + _provider.QuitSpanAwaiting( this ); + s_unusedID.Push( TokenID ); + _awaitingSemaphore.Dispose(); + GC.SuppressFinalize( this ); + } + + public override int GetHashCode() + { + return _id; + } + + public void Participant() + { + lock( _participantObject ) { + _size++; + SemaphoreSlim newSemaphore = new SemaphoreSlim( + _awaitingSemaphore.CurrentCount, _size ); + Interlocked.Exchange( ref _awaitingSemaphore, newSemaphore ) + .Dispose(); + } + } + + public void WaitNextSpan() + { + _awaitingSemaphore.Wait(); + } + + internal void MissRefresh() + { + _missHandler?.Invoke( this, EventArgs.Empty ); + } + + [MethodImpl( MethodImplOptions.AggressiveInlining )] + internal void Refresh() + { + _refreshHandler?.Invoke( this, EventArgs.Empty ); + } + + ~TimeSpanAwaitingToken() + { + Dispose(); + } + + } + #nullable restore +} diff --git a/StgSharp.Common/Timing/TimeSpanProvider.cs b/StgSharp.Common/Timing/TimeSpanProvider.cs new file mode 100644 index 00000000..a29eb27d --- /dev/null +++ b/StgSharp.Common/Timing/TimeSpanProvider.cs @@ -0,0 +1,233 @@ +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// file="TimeSpanProvider.cs" +// Project: StgSharp +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and +// this permission notice shall be included in all copies +// or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, +// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading; + +namespace StgSharp.Timing +{ + /// + /// A microsecond-accuracy timer. It will refresh every a certain time span. + /// + public class TimeSpanProvider + { + + private bool _subscribed; + + private ConcurrentQueue _tokenToAdd = new ConcurrentQueue( + ); + private ConcurrentQueue _tokenToQuit; + private Counter timeSpanCount = new Counter( -1, 1, 1 ); + private HashSet _awaitingTokens; + private long _maxSpanCount; + private long _spanBegin; + private readonly long _spanLength; + private readonly TimeSourceProviderBase _timeSource; + + /// + /// Create a new and define the length of time span. Length + /// of a single time span is defined in microseconds. + /// + /// + /// + public TimeSpanProvider( + long spanMicroSeconds, + TimeSourceProviderBase provider ) + { + if( provider == null ) { + throw new ArgumentNullException( nameof( provider ) ); + } + _timeSource = provider; + _spanLength = spanMicroSeconds; + _maxSpanCount = int.MaxValue; + provider.AddSubscriber( this ); + _subscribed = true; + _awaitingTokens = new HashSet(); + _tokenToQuit = new ConcurrentQueue(); + } + + /// + /// Create a new and define the length of time span. Length + /// of a single time span is defined in seconds. + /// + /// + /// + public TimeSpanProvider( + double spanSeconds, + TimeSourceProviderBase provider ) + { + if( provider == null ) { + throw new ArgumentNullException( nameof( provider ) ); + } + _timeSource = provider; + _spanLength = ( long )( spanSeconds * 1000L * 1000L ); + _spanBegin = -_spanLength; + _maxSpanCount = long.MaxValue; + provider.AddSubscriber( this ); + _subscribed = true; + _awaitingTokens = new HashSet(); + _tokenToQuit = new ConcurrentQueue(); + } + + /// + /// Create a new and define the length of time span. Length + /// of a single time span is defined in microseconds. + /// + /// + /// + /// + public TimeSpanProvider( + long spanLength, + long maxSpan, + TimeSourceProviderBase provider ) + { + if( provider == null ) { + throw new ArgumentNullException( nameof( provider ) ); + } + if( maxSpan <= 0 ) { + throw new ArgumentException( + "Sapn count cannot be smaller than zero" ); + } + _timeSource = provider; + _spanLength = spanLength; + _spanBegin = -_spanLength; + provider.AddSubscriber( this ); + _subscribed = true; + _awaitingTokens = new HashSet(); + _tokenToQuit = new ConcurrentQueue(); + } + + public double SpanLength + { + get => ( _spanLength * 1.0 ) / ( 1000L * 1000L ); + } + + public float CurrentSecond + { + get => timeSpanCount.Value * SpanLengthLowPrecession; + } + + public float SpanLengthLowPrecession + { + get => ( _spanLength * 1.0f ) / ( 1000 * 1000 ); + } + + public int CurrentSpan + { + get => timeSpanCount.Value; + } + + /// + /// Time source provider provided in internal framework. + /// + public static TimeSourceProviderBase DefaultProvider => StgSharpTime.OnlyInstance; + + public TimeSpanAwaitingToken ParticipantSpanAwaiting( int count ) + { + TimeSpanAwaitingToken token = new TimeSpanAwaitingToken( + this, count ); + _tokenToAdd.Enqueue( token ); + return token; + } + + public void QuitSpanAwaiting( TimeSpanAwaitingToken token ) + { + _tokenToQuit.Enqueue( token ); + } + + public void StopSpanProviding() + { + Interlocked.Exchange( ref _maxSpanCount, 0 ); + } + + public void SubscribeToTimeSource( + TimeSourceProviderBase serviceHandler ) + { + if( serviceHandler == null ) { + throw new ArgumentNullException( nameof( serviceHandler ) ); + } + if( _subscribed ) { + return; + } + _subscribed = true; + serviceHandler.AddSubscriber( this ); + } + + public int ToInt32() + { + return timeSpanCount.Value; + } + + internal bool CheckTime( long microseconds ) + { + if( microseconds - _spanBegin < _spanLength ) { + return true; + } + while( !_tokenToAdd.IsEmpty ) { + _tokenToAdd.TryDequeue( out TimeSpanAwaitingToken tokenAdd ); + _awaitingTokens.Add( tokenAdd ); + } + while( !_tokenToQuit.IsEmpty ) { + _tokenToQuit.TryDequeue( out TimeSpanAwaitingToken tokenQuit ); + _awaitingTokens.Remove( tokenQuit ); + InternalIO.InternalWriteLog( + $"Awaiting token {tokenQuit!.TokenID} has been removed.", + LogType.Info ); + } + + _spanBegin = microseconds; + timeSpanCount++; + + foreach( TimeSpanAwaitingToken item in _awaitingTokens ) { + if( item.AwaitingSemaphoreSlim.CurrentCount == 0 ) { + item.AwaitingSemaphoreSlim.Release(); + item.Refresh(); + } else { + item.MissRefresh(); + } + } + + return timeSpanCount < _maxSpanCount; + } + + public static explicit operator int( + [NotNull]TimeSpanProvider provider ) + { + return provider.ToInt32(); + } + + } +} \ No newline at end of file diff --git a/StgSharp.Common/obj/x64/Debug/net8.0/StgSharp.Common.AssemblyInfo.cs b/StgSharp.Common/obj/x64/Debug/net8.0/StgSharp.Common.AssemblyInfo.cs index c8978676..f32dc0e0 100644 --- a/StgSharp.Common/obj/x64/Debug/net8.0/StgSharp.Common.AssemblyInfo.cs +++ b/StgSharp.Common/obj/x64/Debug/net8.0/StgSharp.Common.AssemblyInfo.cs @@ -14,7 +14,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("StgSharp.Common")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+6222f8c8be57d511d2ec40523717e20b87fcff9d")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+753cc167bc352df7a47cd17a1ea877666683f5f0")] [assembly: System.Reflection.AssemblyProductAttribute("StgSharp.Common")] [assembly: System.Reflection.AssemblyTitleAttribute("StgSharp.Common")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/StgSharp.Generator/Blueprint/BlueprintNodeAttribute.cs b/StgSharp.Generator/Blueprint/BlueprintNodeAttribute.cs index eb5ddc8b..ee3e0ba8 100644 --- a/StgSharp.Generator/Blueprint/BlueprintNodeAttribute.cs +++ b/StgSharp.Generator/Blueprint/BlueprintNodeAttribute.cs @@ -32,7 +32,7 @@ using System; using System.Collections.Generic; using System.Text; -namespace StgSharp.Blueprint +namespace StgSharp.PipeLine { [AttributeUsage( AttributeTargets.Method, AllowMultiple = false )] public class BlueprintNodeExecutionAttribute : Attribute { } diff --git a/StgSharp.Generator/SourceGenerator/BpNodeGenerator.cs b/StgSharp.Generator/SourceGenerator/BpNodeGenerator.cs index e70739e9..990bf9f6 100644 --- a/StgSharp.Generator/SourceGenerator/BpNodeGenerator.cs +++ b/StgSharp.Generator/SourceGenerator/BpNodeGenerator.cs @@ -33,7 +33,7 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using StgSharp.Blueprint; +using StgSharp.PipeLine; using System; using System.Collections.Generic; @@ -44,76 +44,83 @@ namespace StgSharp.Generator { internal class BpNodeSyntaxReceiver : ISyntaxReceiver { + + private static BpNodeSyntaxReceiver receiver = new BpNodeSyntaxReceiver( + ); private static readonly string _indexTypeName = typeof( PartialDictionary ).Name; - private static BpNodeSyntaxReceiver receiver = new BpNodeSyntaxReceiver(); - public List ValidMethod { get; private set; } = new List(); - public List InvalidMethod { get; private set; } = new List(); + public BpNodeSyntaxReceiver() { } - public BpNodeSyntaxReceiver() + public BpNodeSyntaxReceiver( SyntaxNode node ) { - + OnVisitSyntaxNode( node ); } - public BpNodeSyntaxReceiver(SyntaxNode node) + public List ValidMethod { - OnVisitSyntaxNode(node); - } + get; + private set; + } = new List(); - public void OnVisitSyntaxNode( SyntaxNode syntaxNode ) + public List InvalidMethod { - if( syntaxNode is MethodDeclarationSyntax mds && mds.AttributeLists + get; + private set; + } = new List(); + + public static void BuildNode( + SourceProductionContext context, + MethodDeclarationSyntax mds ) + { + if( mds.AttributeLists .SelectMany( list => list.Attributes ) - .Any( syntax => syntax.Name.ToString() == + .Any( + syntax => syntax.Name.ToString() == typeof( BlueprintNodeExecutionAttribute ).Name ) ) { SeparatedSyntaxList paramList = mds.ParameterList.Parameters; if( mds.Modifiers.Any( SyntaxKind.StaticKeyword ) && paramList.Count == 2 && paramList[ 0 ].Type!.ToString() == _indexTypeName && paramList[ 1 ].Type!.ToString() == _indexTypeName ) { - ValidMethod.Add(mds); - } - else - { - InvalidMethod.Add(mds); - } - } - } - - public static void BuildNode(SourceProductionContext context, MethodDeclarationSyntax mds) - { - if (mds.AttributeLists - .SelectMany(list => list.Attributes) - .Any(syntax => syntax.Name.ToString() == - typeof(BlueprintNodeExecutionAttribute).Name)) - { - SeparatedSyntaxList paramList = mds.ParameterList.Parameters; - if (mds.Modifiers.Any(SyntaxKind.StaticKeyword) && paramList.Count == - 2 && paramList[0].Type!.ToString() == _indexTypeName && paramList[ - 1].Type!.ToString() == - _indexTypeName) - { - var methodName = mds.Identifier.Text; - var sourceText = SourceText.From( """ - - """,encoding:Encoding.UTF8); - context.AddSource("GeneratedBlueprintNode.cs", sourceText); - } - else - { - var diagnostic = Diagnostic.Create( + string methodName = mds.Identifier.Text; + SourceText sourceText = SourceText.From( + string.Empty, encoding: Encoding.UTF8 ); + context.AddSource( "GeneratedBlueprintNode.cs", + sourceText ); + } else { + Diagnostic diagnostic = Diagnostic.Create( new DiagnosticDescriptor( - id:"SSE0001", + id: "SSE0001", title: "Invalid Blueprint Node Method", messageFormat: "Blueprint Node Method must be static and have two parameters of type PartialDictionary", category: "Blueprint Node", DiagnosticSeverity.Error, - isEnabledByDefault: true), - mds.GetLocation(),mds.Identifier.Text); - - context.ReportDiagnostic(diagnostic); + isEnabledByDefault: true ), + mds.GetLocation(), mds.Identifier.Text ); + + context.ReportDiagnostic( diagnostic ); } } } + + public void OnVisitSyntaxNode( SyntaxNode syntaxNode ) + { + if( syntaxNode is MethodDeclarationSyntax mds && mds.AttributeLists + .SelectMany( list => list.Attributes ) + .Any( + syntax => syntax.Name.ToString() == + typeof( BlueprintNodeExecutionAttribute ).Name ) ) { + SeparatedSyntaxList paramList = mds.ParameterList.Parameters; + if( mds.Modifiers.Any( SyntaxKind.StaticKeyword ) && paramList.Count == + 2 && paramList[ 0 ].Type!.ToString() == _indexTypeName && paramList[ + 1 ].Type!.ToString() == + _indexTypeName ) { + ValidMethod.Add( mds ); + } else { + InvalidMethod.Add( mds ); + } + } + } + } } diff --git a/StgSharp.Model/STEP/FileStructure/IStepObject.cs b/StgSharp.Model/STEP/FileStructure/IStepObject.cs index bdf1a443..a3bde67d 100644 --- a/StgSharp.Model/STEP/FileStructure/IStepObject.cs +++ b/StgSharp.Model/STEP/FileStructure/IStepObject.cs @@ -1,6 +1,36 @@ -using StgSharp.Blueprint; +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// file="IStepObject.cs" +// Project: StgSharp +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and +// this permission notice shall be included in all copies +// or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, +// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- using StgSharp.Geometries; using StgSharp.Math; +using StgSharp.PipeLine; using System; using System.Collections.Generic; @@ -8,14 +38,34 @@ using System.Text; namespace StgSharp.Modeling.STEP { - public abstract class IStepObject: StepExpressionBase , IGeometry + public abstract class IStepObject : StepExpressionBase, IGeometry { - public abstract Point this[int index] { get; set; } - public abstract Vec4[] VertexStream { get; } - public abstract CoordinationBase Coordination { get; } - public abstract int VertexCount { get; } - public abstract ReadOnlySpan VertexIndices { get; } + public abstract Point this[ int index ] + { + get; + set; + } + + public abstract Vec4[] VertexStream + { + get; + } + + public abstract CoordinationBase Coordination + { + get; + } + + public abstract int VertexCount + { + get; + } + + public abstract ReadOnlySpan VertexIndices + { + get; + } } } diff --git a/StgSharp.Model/STEP/FileStructure/StepModel.cs b/StgSharp.Model/STEP/FileStructure/StepModel.cs index 4cf42896..6476fe64 100644 --- a/StgSharp.Model/STEP/FileStructure/StepModel.cs +++ b/StgSharp.Model/STEP/FileStructure/StepModel.cs @@ -28,7 +28,7 @@ // //----------------------------------------------------------------------- //----------------------------------------------------------------------- -using StgSharp.Blueprint; +using StgSharp.PipeLine; using System; using System.Collections.Concurrent; using System.Collections.Generic;